Metrics: collect application metrics via vector #246
89
blender_extensions/middleware.py
Normal file
89
blender_extensions/middleware.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
from contextlib import ExitStack
|
||||||
|
import json
|
||||||
|
import socket
|
||||||
|
import time
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import connections
|
||||||
|
|
||||||
|
|
||||||
|
class VectorClient:
|
||||||
|
def __init__(self):
|
||||||
|
self._socket = None
|
||||||
|
self.hostname = socket.gethostname()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def socket(self):
|
||||||
|
if not self._socket:
|
||||||
|
self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
return self._socket
|
||||||
|
|
||||||
|
def send(self, data):
|
||||||
|
self.socket.sendto(
|
||||||
|
bytes(json.dumps(data), "utf-8"),
|
||||||
|
("127.0.0.1", settings.VECTOR_UDP_PORT),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
vector_client = VectorClient()
|
||||||
|
|
||||||
|
|
||||||
|
class QueryLogger:
|
||||||
|
def __init__(self, alias):
|
||||||
|
self.alias = alias
|
||||||
|
self.durations = []
|
||||||
|
|
||||||
|
def __call__(self, execute, sql, params, many, context):
|
||||||
|
start = time.perf_counter()
|
||||||
|
try:
|
||||||
|
return execute(sql, params, many, context)
|
||||||
|
finally:
|
||||||
|
duration = time.perf_counter() - start
|
||||||
|
self.durations.append(duration)
|
||||||
|
|
||||||
|
|
||||||
|
def metrics_middleware(get_response):
|
||||||
|
"""All timings reported as integer milliseconds."""
|
||||||
|
|
||||||
|
def middleware(request):
|
||||||
|
# pre-request setup
|
||||||
|
start = time.perf_counter()
|
||||||
|
context_managers = []
|
||||||
|
query_loggers = []
|
||||||
|
for connection in connections.all():
|
||||||
|
query_logger = QueryLogger(connection.alias)
|
||||||
|
query_loggers.append(query_logger)
|
||||||
|
context_managers.append(connection.execute_wrapper(query_logger))
|
||||||
|
|
||||||
|
# request processing
|
||||||
|
with ExitStack() as stack:
|
||||||
|
for context_manager in context_managers:
|
||||||
|
stack.enter_context(context_manager)
|
||||||
|
response = get_response(request)
|
||||||
|
|
||||||
|
# post-request reporting
|
||||||
|
request_time = int(1000 * (time.perf_counter() - start))
|
||||||
|
db_metrics = {}
|
||||||
|
for query_logger in query_loggers:
|
||||||
|
db_metrics[query_logger.alias] = {
|
||||||
|
"query_count": len(query_logger.durations),
|
||||||
|
"query_time_sum": int(1000 * sum(query_logger.durations)),
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"db": db_metrics,
|
||||||
|
"hostname": vector_client.hostname,
|
||||||
|
"http": {
|
||||||
|
"path": request.path,
|
||||||
|
"request_time": request_time,
|
||||||
|
"remote_addr": request.META.get("REMOTE_ADDR"),
|
||||||
|
"status_code": response.status_code,
|
||||||
|
"user_agent": request.headers.get("user-agent"),
|
||||||
|
},
|
||||||
|
"service_name": settings.SERVICE_NAME,
|
||||||
|
}
|
||||||
|
vector_client.send(data)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
return middleware
|
@ -79,6 +79,7 @@ INSTALLED_APPS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
'blender_extensions.middleware.metrics_middleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
@ -354,3 +355,6 @@ if os.environ.get('ADMINS') is not None:
|
|||||||
ADMINS = [[_.strip() for _ in adm.split(':')] for adm in os.environ.get('ADMINS').split(',')]
|
ADMINS = [[_.strip() for _ in adm.split(':')] for adm in os.environ.get('ADMINS').split(',')]
|
||||||
EMAIL_SUBJECT_PREFIX = f'[{ALLOWED_HOSTS[0]}]'
|
EMAIL_SUBJECT_PREFIX = f'[{ALLOWED_HOSTS[0]}]'
|
||||||
SERVER_EMAIL = f'django@{ALLOWED_HOSTS[0]}'
|
SERVER_EMAIL = f'django@{ALLOWED_HOSTS[0]}'
|
||||||
|
|
||||||
|
SERVICE_NAME = os.getenv('SERVICE_NAME', 'dummy_service_name')
|
||||||
|
VECTOR_UDP_PORT = 18125
|
||||||
|
Loading…
Reference in New Issue
Block a user