diff options
Diffstat (limited to 'bitbake/lib/toaster/toastermain/logs.py')
-rw-r--r-- | bitbake/lib/toaster/toastermain/logs.py | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/toastermain/logs.py b/bitbake/lib/toaster/toastermain/logs.py new file mode 100644 index 0000000000..62d871963a --- /dev/null +++ b/bitbake/lib/toaster/toastermain/logs.py | |||
@@ -0,0 +1,158 @@ | |||
1 | #!/usr/bin/env python3 | ||
2 | # -*- coding: utf-8 -*- | ||
3 | |||
4 | import os | ||
5 | import logging | ||
6 | import json | ||
7 | from pathlib import Path | ||
8 | from django.http import HttpRequest | ||
9 | |||
10 | BUILDDIR = Path(os.environ.get('BUILDDIR', '/tmp')) | ||
11 | |||
12 | def log_api_request(request, response, view, logger_name='api'): | ||
13 | """Helper function for LogAPIMixin""" | ||
14 | |||
15 | repjson = { | ||
16 | 'view': view, | ||
17 | 'path': request.path, | ||
18 | 'method': request.method, | ||
19 | 'status': response.status_code | ||
20 | } | ||
21 | |||
22 | logger = logging.getLogger(logger_name) | ||
23 | logger.info( | ||
24 | json.dumps(repjson, indent=4, separators=(", ", " : ")) | ||
25 | ) | ||
26 | |||
27 | |||
28 | def log_view_mixin(view): | ||
29 | def log_view_request(*args, **kwargs): | ||
30 | # get request from args else kwargs | ||
31 | request = None | ||
32 | if len(args) > 0: | ||
33 | for req in args: | ||
34 | if isinstance(req, HttpRequest): | ||
35 | request = req | ||
36 | break | ||
37 | elif request is None: | ||
38 | request = kwargs.get('request') | ||
39 | |||
40 | response = view(*args, **kwargs) | ||
41 | view_name = 'unknown' | ||
42 | if hasattr(request, 'resolver_match'): | ||
43 | if hasattr(request.resolver_match, 'view_name'): | ||
44 | view_name = request.resolver_match.view_name | ||
45 | |||
46 | log_api_request( | ||
47 | request, response, view_name, 'toaster') | ||
48 | return response | ||
49 | return log_view_request | ||
50 | |||
51 | |||
52 | |||
53 | class LogAPIMixin: | ||
54 | """Logs API requests | ||
55 | |||
56 | tested with: | ||
57 | - APIView | ||
58 | - ModelViewSet | ||
59 | - ReadOnlyModelViewSet | ||
60 | - GenericAPIView | ||
61 | |||
62 | Note: you can set `view_name` attribute in View to override get_view_name() | ||
63 | """ | ||
64 | |||
65 | def get_view_name(self): | ||
66 | if hasattr(self, 'view_name'): | ||
67 | return self.view_name | ||
68 | return super().get_view_name() | ||
69 | |||
70 | def finalize_response(self, request, response, *args, **kwargs): | ||
71 | log_api_request(request, response, self.get_view_name()) | ||
72 | return super().finalize_response(request, response, *args, **kwargs) | ||
73 | |||
74 | |||
75 | LOGGING_SETTINGS = { | ||
76 | 'version': 1, | ||
77 | 'disable_existing_loggers': False, | ||
78 | 'filters': { | ||
79 | 'require_debug_false': { | ||
80 | '()': 'django.utils.log.RequireDebugFalse' | ||
81 | } | ||
82 | }, | ||
83 | 'formatters': { | ||
84 | 'datetime': { | ||
85 | 'format': '%(asctime)s %(levelname)s %(message)s' | ||
86 | }, | ||
87 | 'verbose': { | ||
88 | 'format': '{levelname} {asctime} {module} {name}.{funcName} {process:d} {thread:d} {message}', | ||
89 | 'datefmt': "%d/%b/%Y %H:%M:%S", | ||
90 | 'style': '{', | ||
91 | }, | ||
92 | 'api': { | ||
93 | 'format': '\n{levelname} {asctime} {name}.{funcName}:\n{message}', | ||
94 | 'style': '{' | ||
95 | } | ||
96 | }, | ||
97 | 'handlers': { | ||
98 | 'mail_admins': { | ||
99 | 'level': 'ERROR', | ||
100 | 'filters': ['require_debug_false'], | ||
101 | 'class': 'django.utils.log.AdminEmailHandler' | ||
102 | }, | ||
103 | 'console': { | ||
104 | 'level': 'DEBUG', | ||
105 | 'class': 'logging.StreamHandler', | ||
106 | 'formatter': 'datetime', | ||
107 | }, | ||
108 | 'file_django': { | ||
109 | 'level': 'INFO', | ||
110 | 'class': 'logging.handlers.TimedRotatingFileHandler', | ||
111 | 'filename': BUILDDIR / 'toaster_logs/django.log', | ||
112 | 'when': 'D', # interval type | ||
113 | 'interval': 1, # defaults to 1 | ||
114 | 'backupCount': 10, # how many files to keep | ||
115 | 'formatter': 'verbose', | ||
116 | }, | ||
117 | 'file_api': { | ||
118 | 'level': 'INFO', | ||
119 | 'class': 'logging.handlers.TimedRotatingFileHandler', | ||
120 | 'filename': BUILDDIR / 'toaster_logs/api.log', | ||
121 | 'when': 'D', | ||
122 | 'interval': 1, | ||
123 | 'backupCount': 10, | ||
124 | 'formatter': 'verbose', | ||
125 | }, | ||
126 | 'file_toaster': { | ||
127 | 'level': 'INFO', | ||
128 | 'class': 'logging.handlers.TimedRotatingFileHandler', | ||
129 | 'filename': BUILDDIR / 'toaster_logs/web.log', | ||
130 | 'when': 'D', | ||
131 | 'interval': 1, | ||
132 | 'backupCount': 10, | ||
133 | 'formatter': 'verbose', | ||
134 | }, | ||
135 | }, | ||
136 | 'loggers': { | ||
137 | 'django.request': { | ||
138 | 'handlers': ['file_django', 'console'], | ||
139 | 'level': 'WARN', | ||
140 | 'propagate': True, | ||
141 | }, | ||
142 | 'django': { | ||
143 | 'handlers': ['file_django', 'console'], | ||
144 | 'level': 'WARNING', | ||
145 | 'propogate': True, | ||
146 | }, | ||
147 | 'toaster': { | ||
148 | 'handlers': ['file_toaster'], | ||
149 | 'level': 'INFO', | ||
150 | 'propagate': False, | ||
151 | }, | ||
152 | 'api': { | ||
153 | 'handlers': ['file_api'], | ||
154 | 'level': 'INFO', | ||
155 | 'propagate': False, | ||
156 | } | ||
157 | } | ||
158 | } | ||