mirror of
https://git.yoctoproject.org/poky
synced 2026-02-07 17:26:36 +01:00
Fixes "2efb14648 toaster: Monitoring - implement Django logging system" when running in a container. When running in a container, the previous approach of using BASE_DIR is not a writable path. Also, we really do not want to be writing logs into the source tree, as the BASE_DIR was resolving to bitbake/lib/toaster/logs Since Toaster is only ever running in an environment where oe-init-buildenv or similar has been sourced, we should instead write the logs to BUILDDIR. Using BUILDDIR to logs make path writable but django-log-viewer does'nt manage to write logs using an absolute path as BUILDDIR, where the existing toaster_ui.log was already being written. Also drop the /logs/ directory, as it has not been created which also breaks in a container environment To handle the constraints linked to django-log-viewer and /logs/, we've updated bitbake/bin/toaster to create a toaster_logs/ directory in BUILDDIR if it doesn't exist, when toaster starts up. Also manage to set BUILDDIR/toaster_logs/ as default location for toaster logs. (Bitbake rev: efbd9d54f57be7a7a10f0b56e7e62c25974e99e6) Signed-off-by: Alassane Yattara <alassane.yattara@savoirfairelinux.com> Signed-off-by: Tim Orling <tim.orling@konsulko.com> Tested-by: Tim Orling <tim.orling@konsulko.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
159 lines
4.4 KiB
Python
159 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import logging
|
|
import json
|
|
from pathlib import Path
|
|
from django.http import HttpRequest
|
|
|
|
BUILDDIR = Path(os.environ.get('BUILDDIR', '/tmp'))
|
|
|
|
def log_api_request(request, response, view, logger_name='api'):
|
|
"""Helper function for LogAPIMixin"""
|
|
|
|
repjson = {
|
|
'view': view,
|
|
'path': request.path,
|
|
'method': request.method,
|
|
'status': response.status_code
|
|
}
|
|
|
|
logger = logging.getLogger(logger_name)
|
|
logger.info(
|
|
json.dumps(repjson, indent=4, separators=(", ", " : "))
|
|
)
|
|
|
|
|
|
def log_view_mixin(view):
|
|
def log_view_request(*args, **kwargs):
|
|
# get request from args else kwargs
|
|
request = None
|
|
if len(args) > 0:
|
|
for req in args:
|
|
if isinstance(req, HttpRequest):
|
|
request = req
|
|
break
|
|
elif request is None:
|
|
request = kwargs.get('request')
|
|
|
|
response = view(*args, **kwargs)
|
|
view_name = 'unknown'
|
|
if hasattr(request, 'resolver_match'):
|
|
if hasattr(request.resolver_match, 'view_name'):
|
|
view_name = request.resolver_match.view_name
|
|
|
|
log_api_request(
|
|
request, response, view_name, 'toaster')
|
|
return response
|
|
return log_view_request
|
|
|
|
|
|
|
|
class LogAPIMixin:
|
|
"""Logs API requests
|
|
|
|
tested with:
|
|
- APIView
|
|
- ModelViewSet
|
|
- ReadOnlyModelViewSet
|
|
- GenericAPIView
|
|
|
|
Note: you can set `view_name` attribute in View to override get_view_name()
|
|
"""
|
|
|
|
def get_view_name(self):
|
|
if hasattr(self, 'view_name'):
|
|
return self.view_name
|
|
return super().get_view_name()
|
|
|
|
def finalize_response(self, request, response, *args, **kwargs):
|
|
log_api_request(request, response, self.get_view_name())
|
|
return super().finalize_response(request, response, *args, **kwargs)
|
|
|
|
|
|
LOGGING_SETTINGS = {
|
|
'version': 1,
|
|
'disable_existing_loggers': False,
|
|
'filters': {
|
|
'require_debug_false': {
|
|
'()': 'django.utils.log.RequireDebugFalse'
|
|
}
|
|
},
|
|
'formatters': {
|
|
'datetime': {
|
|
'format': '%(asctime)s %(levelname)s %(message)s'
|
|
},
|
|
'verbose': {
|
|
'format': '{levelname} {asctime} {module} {name}.{funcName} {process:d} {thread:d} {message}',
|
|
'datefmt': "%d/%b/%Y %H:%M:%S",
|
|
'style': '{',
|
|
},
|
|
'api': {
|
|
'format': '\n{levelname} {asctime} {name}.{funcName}:\n{message}',
|
|
'style': '{'
|
|
}
|
|
},
|
|
'handlers': {
|
|
'mail_admins': {
|
|
'level': 'ERROR',
|
|
'filters': ['require_debug_false'],
|
|
'class': 'django.utils.log.AdminEmailHandler'
|
|
},
|
|
'console': {
|
|
'level': 'DEBUG',
|
|
'class': 'logging.StreamHandler',
|
|
'formatter': 'datetime',
|
|
},
|
|
'file_django': {
|
|
'level': 'INFO',
|
|
'class': 'logging.handlers.TimedRotatingFileHandler',
|
|
'filename': BUILDDIR / 'toaster_logs/django.log',
|
|
'when': 'D', # interval type
|
|
'interval': 1, # defaults to 1
|
|
'backupCount': 10, # how many files to keep
|
|
'formatter': 'verbose',
|
|
},
|
|
'file_api': {
|
|
'level': 'INFO',
|
|
'class': 'logging.handlers.TimedRotatingFileHandler',
|
|
'filename': BUILDDIR / 'toaster_logs/api.log',
|
|
'when': 'D',
|
|
'interval': 1,
|
|
'backupCount': 10,
|
|
'formatter': 'verbose',
|
|
},
|
|
'file_toaster': {
|
|
'level': 'INFO',
|
|
'class': 'logging.handlers.TimedRotatingFileHandler',
|
|
'filename': BUILDDIR / 'toaster_logs/web.log',
|
|
'when': 'D',
|
|
'interval': 1,
|
|
'backupCount': 10,
|
|
'formatter': 'verbose',
|
|
},
|
|
},
|
|
'loggers': {
|
|
'django.request': {
|
|
'handlers': ['file_django', 'console'],
|
|
'level': 'WARN',
|
|
'propagate': True,
|
|
},
|
|
'django': {
|
|
'handlers': ['file_django', 'console'],
|
|
'level': 'WARNING',
|
|
'propogate': True,
|
|
},
|
|
'toaster': {
|
|
'handlers': ['file_toaster'],
|
|
'level': 'INFO',
|
|
'propagate': False,
|
|
},
|
|
'api': {
|
|
'handlers': ['file_api'],
|
|
'level': 'INFO',
|
|
'propagate': False,
|
|
}
|
|
}
|
|
}
|