Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bdaniels/opentelemetry #888

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/dso_api/dynamic_api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ def refresh_from_db(self, using=None, fields=None):
the queryset/manager and queryset iterator.
"""
if fields and fields[0] not in self.__dict__:

message = (
f"Deferred attribute access: field '{fields[0]}' "
f"was excluded by .only() but was still accessed."
Expand Down
93 changes: 46 additions & 47 deletions src/dso_api/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import sentry_sdk
import sentry_sdk.utils
from corsheaders.defaults import default_headers
from django.core.exceptions import ImproperlyConfigured
from opencensus.trace import config_integration
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration

Expand Down Expand Up @@ -285,7 +283,6 @@
},
"root": {"level": "INFO", "handlers": ["console"]},
"loggers": {
"opencensus": {"handlers": ["console"], "level": DJANGO_LOG_LEVEL, "propagate": False},
"django": {"handlers": ["console"], "level": DJANGO_LOG_LEVEL, "propagate": False},
"django.utils.autoreload": {"handlers": ["console"], "level": "INFO", "propagate": False},
"dso_api": {"handlers": ["console"], "level": DSO_API_LOG_LEVEL, "propagate": False},
Expand All @@ -309,53 +306,55 @@
}

if CLOUD_ENV.lower().startswith("azure"):
if AZURE_APPI_CONNECTION_STRING is None:
raise ImproperlyConfigured(
"Please specify the 'AZURE_APPI_CONNECTION_STRING' environment variable."
)
if AZURE_APPI_AUDIT_CONNECTION_STRING is None:
logging.warning(
"Using AZURE_APPI_CONNECTION_STRING as AZURE_APPI_AUDIT_CONNECTION_STRING."
)

MIDDLEWARE.append("opencensus.ext.django.middleware.OpencensusMiddleware")
OPENCENSUS = {
"TRACE": {
"SAMPLER": "opencensus.trace.samplers.ProbabilitySampler(rate=1)",
"EXPORTER": f"""opencensus.ext.azure.trace_exporter.AzureExporter(
connection_string='{AZURE_APPI_CONNECTION_STRING}',
service_name='dso-api'
)""", # noqa: E202
"EXCLUDELIST_PATHS": [],
}
}
config_integration.trace_integrations(["logging"])
azure_json = base_log_fmt.copy()
azure_json.update({"message": "%(message)s"})
audit_azure_json = {"audit": True}
audit_azure_json.update(azure_json)
LOGGING["formatters"]["azure"] = {"format": json.dumps(azure_json)}
LOGGING["formatters"]["audit_azure"] = {"format": json.dumps(audit_azure_json)}
LOGGING["handlers"]["azure"] = {
"level": "DEBUG",
"class": "opencensus.ext.azure.log_exporter.AzureLogHandler",
"connection_string": AZURE_APPI_CONNECTION_STRING,
"formatter": "azure",
}
LOGGING["handlers"]["audit_azure"] = {
"level": "DEBUG",
"class": "opencensus.ext.azure.log_exporter.AzureLogHandler",
"connection_string": AZURE_APPI_AUDIT_CONNECTION_STRING,
"formatter": "audit_azure",
}

LOGGING["root"]["handlers"] = ["azure"]
LOGGING["root"]["level"] = DJANGO_LOG_LEVEL
for logger_name, logger_details in LOGGING["loggers"].items():
if "audit_console" in logger_details["handlers"]:
LOGGING["loggers"][logger_name]["handlers"] = ["audit_azure", "console"]
LOGGING["loggers"][logger_name]["handlers"] = ["console", "audit_console"]
else:
LOGGING["loggers"][logger_name]["handlers"] = ["azure", "console"]
LOGGING["loggers"][logger_name]["handlers"] = ["console"]

from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry.instrumentation.django import DjangoInstrumentor
from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor
from opentelemetry.sdk.resources import Resource
from opentelemetry.semconv.resource import ResourceAttributes

# Configure OpenTelemetry to use Azure Monitor with the specified connection string
AZURE_APPI_CONNECTION_STRING = os.getenv("AZURE_APPI_CONNECTION_STRING")
if AZURE_APPI_CONNECTION_STRING is not None:
configure_azure_monitor(
connection_string=AZURE_APPI_CONNECTION_STRING,
logger_name="root",
instrumentation_options={
"azure_sdk": {"enabled": False},
"django": {"enabled": False},
"fastapi": {"enabled": False},
"flask": {"enabled": False}, # Configure flask manually
"psycopg2": {"enabled": False}, # Configure psycopg2 manually
"requests": {"enabled": True},
"urllib": {"enabled": True},
"urllib3": {"enabled": True},
},
resource=Resource.create({ResourceAttributes.SERVICE_NAME: "dso-api"}),
)
logger = logging.getLogger("root")
logger.info("OpenTelemetry has been enabled")

def response_hook(span, request, response):
if span and span.is_recording():
email = request.get_token_subject
if (
getattr(request, "get_token_claims", None)
and "email" in request.get_token_claims
):
email = request.get_token_claims["email"]
span.set_attribute("user.AuthenticatedId", email)

# Instrument Django app
DjangoInstrumentor().instrument(response_hook=response_hook)
print("django instrumentor enabled")

Psycopg2Instrumentor().instrument(enable_commenter=True, commenter_options={})
print("psycopg instrumentor enabled")

# -- Third party app settings

Expand Down
6 changes: 3 additions & 3 deletions src/requirements.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
azure-monitor-opentelemetry == 1.6.2
azure-identity == 1.17.1
cachetools == 5.5.0
Django == 4.2.15
django-environ == 0.11.2
django-cors-headers == 4.4.0
Expand All @@ -22,9 +25,6 @@ Markdown == 3.7
more-ds == 0.0.6
more-itertools == 10.5.0
openapi-spec-validator == 0.7.1
opencensus-ext-azure >= 1.1.13
opencensus-ext-django >= 0.8
opencensus-ext-logging >= 0.1.1
orjson == 3.10.7
python-string-utils == 1.0.0
requests == 2.32.3
Expand Down
Loading