Skip to content

Commit

Permalink
for MPP-3467: add googlecloudprofiler to PrivateRelayConfig.ready
Browse files Browse the repository at this point in the history
Also moves get_version_info to privaterelay.apps
  • Loading branch information
groovecoder committed Jan 25, 2024
1 parent 1fdb597 commit 15548d1
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 41 deletions.
1 change: 1 addition & 0 deletions .env-dist
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ FXA_PROFILE_ENDPOINT=https://profile.stage.mozaws.net/v1
FXA_BASE_ORIGIN=https://accounts.stage.mozaws.net
FXA_ACCOUNTS_ENDPOINT=https://api-accounts.stage.mozaws.net/v1
GOOGLE_ANALYTICS_ID="UA-77033033-33"
GOOGLE_APPLICATION_CREDENTIALS=
BASKET_ORIGIN="https://basket-dev.allizom.org"
SECRET_KEY=unsafe-secret-key-for-dev-envs
ADMIN_ENABLED=
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ junit.xml
state.json
har/
allure-results/
allure-report/
allure-report/
gcp_key.json
version.json
2 changes: 2 additions & 0 deletions .profile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
echo "${GOOGLE_CREDENTIALS_B64}" | base64 -d > gcp_key.json
2 changes: 2 additions & 0 deletions bin/pre_compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
echo "${GOOGLE_CREDENTIALS_B64}" | base64 -d > gcp_key.json
35 changes: 35 additions & 0 deletions docs/profiler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Profiler

This doc describes how we profile Relay code.

## Google Cloud Profiler

We use Google Cloud Profiler: https://cloud.google.com/profiler/docs/about-profiler

### Setup

Our google cloud profiler agent uses a service account with `roles/cloudprofiler.agent`
role. So, you need a JSON key file for the account, and you need to set the
`GOOGLE_APPLICATION_CREDENTIALS` environment variable to the fully qualified name of the
JSON key file.

#### Local servers

1. Get the JSON key file from another Relay ENGR
2. Update your `.env` `GOOGLE_APPLICATION_CREDENTIALS` value to the fully-qualified name
of the JSON key file.

#### Dev server

For the dev server, we use a `.profile` (and/or `bin/pre_compile`) script which copies
the `GOOGLE_CREDENTIALS_B64` environment variable value into a `gcp_key.json` file at
build time.

#### Stage & Prod

TBD: Figure out if we should use Compute Engine, GKE, Flexible Environment, or Standard
Environment instructions from https://cloud.google.com/profiler/docs/profiling-python#using-profiler

### Viewing profiler data

Go to https://console.cloud.google.com/profiler/fxprivaterelay-nonprod/cpu?project=moz-fx-fxprivate-nonprod-6df0
75 changes: 74 additions & 1 deletion privaterelay/apps.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from typing import Any
from functools import cache
import json
from pathlib import Path
from typing import Any, Tuple, TypedDict
import requests
import os

Expand All @@ -10,10 +13,80 @@
ROOT_DIR = os.path.abspath(os.curdir)


class VersionInfo(TypedDict):
source: str
version: str
commit: str
build: str


@cache
def get_version_info(base_dir: str | Path | None = None) -> VersionInfo:
"""Return version information written by build process."""
if base_dir is None:
base_path = Path(settings.BASE_DIR)
else:
base_path = Path(base_dir)
version_json_path = base_path / "version.json"
info = {}
if version_json_path.exists():
with version_json_path.open() as version_file:
try:
info = json.load(version_file)
except ValueError:
pass
if not hasattr(info, "get"):
info = {}
version_info = VersionInfo(
source=info.get("source", "https://github.com/mozilla/fx-private-relay"),
version=info.get("version", "unknown"),
commit=info.get("commit", "unknown"),
build=info.get("build", "not built"),
)
return version_info


def get_profiler_startup_data() -> Tuple[str | None, str | None, str | None]:
if settings.RELAY_CHANNEL not in ("dev", "stage", "prod"):
return (None, None, None)

if settings.RELAY_CHANNEL in ("dev", "stage"):
service = "fxprivaterelay-nonprod"
project_id = "moz-fx-fxprivate-nonprod-6df0"
if settings.RELAY_CHANNEL == "prod":
service = "fxprivaterelay"
project_id = "moz-fx-fxprivaterel-prod-6700"

version_info = get_version_info()
version = version_info.get("version", "unknown")

return service, version, project_id


class PrivateRelayConfig(AppConfig):
name = "privaterelay"

def ready(self) -> None:
# Set up Google Cloud Profiler
service, version, project_id = get_profiler_startup_data()
if service != None:
import googlecloudprofiler

# Make sure the expect gcp_key.json file exists
gcp_key_json_path = Path(settings.BASE_DIR) / "gcp_key.json"
if gcp_key_json_path.exists():
with gcp_key_json_path.open() as gcp_key_file:
try:
# Make sure the expect gcp_key.json file is valid json
json.load(gcp_key_file)
googlecloudprofiler.start(
service=service,
service_version=version,
project_id=project_id,
)
except ValueError:
print(f"error during json.load({gcp_key_file})")

import privaterelay.signals

assert privaterelay.signals # Suppress "imported but unused" warnings
Expand Down
2 changes: 1 addition & 1 deletion privaterelay/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pytest_django.fixtures import SettingsWrapper
import pytest

from privaterelay.utils import get_version_info
from privaterelay.apps import get_version_info


@pytest.fixture
Expand Down
2 changes: 1 addition & 1 deletion privaterelay/tests/utils_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
from waffle.utils import get_cache as get_waffle_cache
import pytest

from ..apps import get_version_info
from ..plans import get_premium_country_language_mapping
from ..utils import (
AcceptLanguageError,
flag_is_active_in_task,
get_countries_info_from_request_and_mapping,
get_version_info,
guess_country_from_accept_lang,
)

Expand Down
37 changes: 1 addition & 36 deletions privaterelay/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from decimal import Decimal
from functools import cache, wraps
from pathlib import Path
from functools import wraps
from string import ascii_uppercase
from typing import Callable, TypedDict, cast
import json
import logging
import random

Expand Down Expand Up @@ -478,36 +476,3 @@ def flag_is_active_in_task(flag_name: str, user: AbstractBaseUser | None) -> boo
return True

return False


class VersionInfo(TypedDict):
source: str
version: str
commit: str
build: str


@cache
def get_version_info(base_dir: str | Path | None = None) -> VersionInfo:
"""Return version information written by build process."""
if base_dir is None:
base_path = Path(settings.BASE_DIR)
else:
base_path = Path(base_dir)
version_json_path = base_path / "version.json"
info = {}
if version_json_path.exists():
with version_json_path.open() as version_file:
try:
info = json.load(version_file)
except ValueError:
pass
if not hasattr(info, "get"):
info = {}
version_info = VersionInfo(
source=info.get("source", "https://github.com/mozilla/fx-private-relay"),
version=info.get("version", "unknown"),
commit=info.get("commit", "unknown"),
build=info.get("build", "not built"),
)
return version_info
2 changes: 1 addition & 1 deletion privaterelay/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
)
from emails.utils import incr_if_enabled

from .apps import PrivateRelayConfig
from .apps import PrivateRelayConfig, get_version_info
from .fxa_utils import _get_oauth2_session, NoSocialToken


Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module = [
"django_ftl",
"django_ftl.bundles",
"google_measurement_protocol",
"googlecloudprofiler",
"jwcrypto",
"jwcrypto.jwe",
"jwcrypto.jwk",
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dockerflow==2024.1.0
drf-spectacular==0.27.1
drf-spectacular-sidecar==2024.1.1
google-measurement-protocol==1.1.0
google-cloud-profiler==4.1.0
gunicorn==21.2.0
jwcrypto==1.5.1
markus[datadog]==4.2.0
Expand Down

0 comments on commit 15548d1

Please sign in to comment.