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

Setup opentelemetry #1280

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
85 changes: 85 additions & 0 deletions app/config/logging.py
Original file line number Diff line number Diff line change
@@ -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
)
85 changes: 1 addition & 84 deletions app/config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,13 @@
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

azure = Azure()

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")

Expand Down Expand Up @@ -109,7 +106,6 @@
}

MIDDLEWARE = (
"opencensus.ext.django.middleware.OpencensusMiddleware",
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.security.SecurityMiddleware",
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
5 changes: 2 additions & 3 deletions app/config/wsgi.py
Original file line number Diff line number Diff line change
@@ -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()
2 changes: 1 addition & 1 deletion app/deploy/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 1 addition & 8 deletions app/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -83,10 +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
Loading