From 227a53874dfcc279016acdae5eddb3b2a8a3b218 Mon Sep 17 00:00:00 2001 From: Nino Date: Tue, 5 Nov 2024 10:28:17 +0100 Subject: [PATCH 1/2] setup opentelemetry --- app/config/logging.py | 85 ++++++++++++++++++++++++++++++++++++++++++ app/config/settings.py | 85 +----------------------------------------- app/config/wsgi.py | 5 +-- app/deploy/config.ini | 2 +- app/requirements.txt | 2 +- 5 files changed, 90 insertions(+), 89 deletions(-) create mode 100644 app/config/logging.py diff --git a/app/config/logging.py b/app/config/logging.py new file mode 100644 index 000000000..5414dba5c --- /dev/null +++ b/app/config/logging.py @@ -0,0 +1,85 @@ +import os +from typing import Any + +from azure.monitor.opentelemetry.exporter import ( + AzureMonitorLogExporter, + AzureMonitorTraceExporter, +) +from opentelemetry import trace +from opentelemetry.instrumentation.django import DjangoInstrumentor +from opentelemetry.instrumentation.psycopg2 import Psycopg2Instrumentor +from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler +from opentelemetry.sdk._logs.export import BatchLogRecordProcessor +from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor + + +def start_logging(): + LOGGING_HANDLERS: dict[str, dict[str, Any]] = { + "console": { + "class": "logging.StreamHandler", + }, + } + LOGGER_HANDLERS = [ + "console", + ] + + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") + APPLICATIONINSIGHTS_CONNECTION_STRING = os.getenv( + "APPLICATIONINSIGHTS_CONNECTION_STRING" + ) + + def response_hook(span, request, response): + if ( + span + and span.is_recording() + and hasattr(request, "user") + and request.user is not None + and hasattr(request.user, "is_authenticated") + and request.user.is_authenticated is True + ): + span.set_attributes({"django.user.name": request.user.username}) + + MONITOR_SERVICE_NAME = "zaken-backend" + resource: Resource = Resource.create({"service.name": MONITOR_SERVICE_NAME}) + + tracer_provider: TracerProvider = TracerProvider(resource=resource) + trace.set_tracer_provider(tracer_provider) + if APPLICATIONINSIGHTS_CONNECTION_STRING: + span_exporter: AzureMonitorTraceExporter = AzureMonitorTraceExporter( + connection_string=APPLICATIONINSIGHTS_CONNECTION_STRING + ) + tracer_provider.add_span_processor( + BatchSpanProcessor(span_exporter=span_exporter) + ) + log_exporter: AzureMonitorLogExporter = AzureMonitorLogExporter( + connection_string=APPLICATIONINSIGHTS_CONNECTION_STRING + ) + logger_provider: LoggerProvider = LoggerProvider(resource=resource) + logger_provider.add_log_record_processor( + BatchLogRecordProcessor(log_exporter, schedule_delay_millis=3000) + ) + + class AzureLoggingHandler(LoggingHandler): + def __init__(self): + super().__init__(logger_provider=logger_provider) + + LOGGING_HANDLERS.update( + { + "azure": { + "()": AzureLoggingHandler, + "formatter": "elaborate", + "level": os.getenv("LOGGING_LEVEL", "WARNING"), + } + } + ) + + LOGGER_HANDLERS.append("azure") + if os.getenv("LOGGING_LEVEL", "WARNING") == "DEBUG": + Psycopg2Instrumentor().instrument( + tracer_provider=tracer_provider, skip_dep_check=True + ) + DjangoInstrumentor().instrument( + tracer_provider=tracer_provider, response_hook=response_hook + ) diff --git a/app/config/settings.py b/app/config/settings.py index c05f25298..9c8b071fd 100644 --- a/app/config/settings.py +++ b/app/config/settings.py @@ -6,7 +6,6 @@ from celery.schedules import crontab from dotenv import load_dotenv from keycloak_oidc.default_settings import * # noqa -from opencensus.ext.azure.trace_exporter import AzureExporter from .azure_settings import Azure @@ -14,8 +13,6 @@ load_dotenv() -# config_integration.trace_integrations(["requests", "logging"]) - BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY") @@ -109,7 +106,6 @@ } MIDDLEWARE = ( - "opencensus.ext.django.middleware.OpencensusMiddleware", "corsheaders.middleware.CorsMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.security.SecurityMiddleware", @@ -183,85 +179,6 @@ TAG_NAME = os.getenv("TAG_NAME", "default-release") -LOGGING_LEVEL = os.getenv("LOGGING_LEVEL", "DEBUG") - -LOGGING = { - "version": 1, - "disable_existing_loggers": True, - "handlers": { - "console": {"class": "logging.StreamHandler", "level": LOGGING_LEVEL}, - "celery": {"level": LOGGING_LEVEL, "class": "logging.StreamHandler"}, - }, - "root": {"handlers": ["console"], "level": LOGGING_LEVEL}, - "loggers": { - "apps": { - "handlers": ["console"], - "level": LOGGING_LEVEL, - "propagate": True, - }, - "utils": { - "handlers": ["console"], - "level": LOGGING_LEVEL, - "propagate": True, - }, - "django": { - "handlers": ["console"], - "level": LOGGING_LEVEL, - "propagate": True, - }, - "": { - "level": LOGGING_LEVEL, - "handlers": ["console"], - "propagate": True, - }, - "celery": { - "handlers": ["celery", "console"], - "level": LOGGING_LEVEL, - "propagate": True, - }, - "mozilla_django_oidc": {"handlers": ["console"], "level": "INFO"}, - }, -} - -APPLICATIONINSIGHTS_CONNECTION_STRING = os.getenv( - "APPLICATIONINSIGHTS_CONNECTION_STRING" -) - -if APPLICATIONINSIGHTS_CONNECTION_STRING: - # Only log queries when in DEBUG due to high cost - def filter_traces(envelope): - if LOGGING_LEVEL == "DEBUG": - return True - log_data = envelope.data.baseData - if "query" in log_data["name"].lower(): - return False - if log_data["name"] == "GET /": - return False - if "applicationinsights" in log_data.message.lower(): - return False - return True - - exporter = AzureExporter(connection_string=APPLICATIONINSIGHTS_CONNECTION_STRING) - exporter.add_telemetry_processor(filter_traces) - OPENCENSUS = { - "TRACE": { - "SAMPLER": "opencensus.trace.samplers.ProbabilitySampler(rate=1)", - "EXPORTER": exporter, - } - } - LOGGING["handlers"]["azure"] = { - "level": LOGGING_LEVEL, - "class": "opencensus.ext.azure.log_exporter.AzureLogHandler", - "connection_string": APPLICATIONINSIGHTS_CONNECTION_STRING, - } - - LOGGING["root"]["handlers"] = ["azure", "console"] - LOGGING["loggers"]["django"]["handlers"] = ["azure", "console"] - LOGGING["loggers"][""]["handlers"] = ["azure", "console"] - LOGGING["loggers"]["apps"]["handlers"] = ["azure", "console"] - LOGGING["loggers"]["utils"]["handlers"] = ["azure", "console"] - LOGGING["loggers"]["celery"]["handlers"] = ["azure", "console", "celery"] - """ TODO: Only a few of these settings are actually used for our current flow, but the mozilla_django_oidc OIDCAuthenticationBackend required these to be set. @@ -306,7 +223,7 @@ def filter_traces(envelope): ) LOCAL_DEVELOPMENT_AUTHENTICATION = ( - os.getenv("LOCAL_DEVELOPMENT_AUTHENTICATION", False) == "True" + os.getenv("LOCAL_DEVELOPMENT_AUTHENTICATION", "False") == "True" ) DATA_UPLOAD_MAX_MEMORY_SIZE = 5242880 DATA_UPLOAD_MAX_NUMBER_FIELDS = 6000 diff --git a/app/config/wsgi.py b/app/config/wsgi.py index 850933564..be531a05e 100644 --- a/app/config/wsgi.py +++ b/app/config/wsgi.py @@ -1,7 +1,6 @@ -import os - from django.core.wsgi import get_wsgi_application -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings") +from .logging import start_logging +start_logging() application = get_wsgi_application() diff --git a/app/deploy/config.ini b/app/deploy/config.ini index 24cca1ab8..d83926691 100644 --- a/app/deploy/config.ini +++ b/app/deploy/config.ini @@ -36,4 +36,4 @@ cheaper-busyness-max = 70 ; Above this threshold, spawn new workers cheaper-busyness-backlog-alert = 16 ; Spawn emergency workers if more than this many requests are waiting in the queue cheaper-busyness-backlog-step = 2 ; How many emergency workers to create if there are too many requests in the queue buffer-size = 32768 -lazy-apps = true +# lazy-apps = true diff --git a/app/requirements.txt b/app/requirements.txt index b1647ec23..36d3d29b0 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -44,7 +44,6 @@ deepdiff prettyprinter gemma-zds-client==1.0.0 idna==3.7 -importlib-metadata==4.8.1 inflection==0.5.1 josepy==1.13.0 jsonschema==4.4.0 @@ -90,3 +89,4 @@ opencensus-ext-django==0.8.0 opencensus-ext-logging==0.1.1 opencensus-ext-postgresql==0.1.3 opencensus-ext-requests==0.8.0 +azure-monitor-opentelemetry==1.6.2 From 07305bdbd3e6d3d5bd206fe555fc8cd5bdec8558 Mon Sep 17 00:00:00 2001 From: Nino Date: Wed, 6 Nov 2024 09:46:12 +0100 Subject: [PATCH 2/2] remove dependencies --- app/requirements.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/requirements.txt b/app/requirements.txt index 36d3d29b0..7b4f5a648 100644 --- a/app/requirements.txt +++ b/app/requirements.txt @@ -82,11 +82,4 @@ zipp==3.19.1 django_webtest==1.9.9 python-dotenv==0.19.2 applicationinsights==0.11.10 -opencensus==0.11.2 -opencensus-context==0.1.3 -opencensus-ext-azure==1.1.9 -opencensus-ext-django==0.8.0 -opencensus-ext-logging==0.1.1 -opencensus-ext-postgresql==0.1.3 -opencensus-ext-requests==0.8.0 azure-monitor-opentelemetry==1.6.2