loggers classes added
lgz committed
Oct 13, 2017 at 00:05 UTC
d2f80005882558cbd68310475be12e8b49073abf
1 file changed
+173
python.d/python_modules/bases/loggers.py
new
+173
@@ -0,0 +1,173 @@
1
+# -*- coding: utf-8 -*-
2
+# Description:
3
+# Author: Ilya Mashchenko (l2isbad)
4
+
5
+import logging
6
+
7
+try:
8
+ from time import monotonic as time
9
+except ImportError:
10
+ from time import time
11
+
12
+from bases.collection import on_try_except_finally
13
+
14
+
15
+LOGGING_LEVELS = {50: 'CRITICAL',
16
+ 40: 'ERROR',
17
+ 30: 'WARNING',
18
+ 20: 'INFO',
19
+ 10: 'DEBUG',
20
+ 0: 'NOTSET'}
21
+
22
+DEFAULT_LOG_LINE_FORMAT = '%(asctime)s: %(name)s %(levelname)s : %(message)s'
23
+DEFAULT_LOG_TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
24
+
25
+PYTHON_D_LOG_LINE_FORMAT = '%(asctime)s: %(name)s %(levelname)s: %(module_name)s: %(job_name)s: %(message)s'
26
+PYTHON_D_LOG_NAME = 'python.d'
27
+
28
+
29
+def limiter(log_max_count=30, allowed_in_seconds=60):
30
+ def on_decorator(func):
31
+
32
+ def on_call(*args, **kwargs):
33
+ self = args[0]
34
+
35
+ if self._logger_counters.allowed > log_max_count:
36
+ current_time = time()
37
+ if current_time - self._logger_counters.time_to_compare <= allowed_in_seconds:
38
+ self._logger_counters.dropped += 1
39
+ return
40
+ self._logger_counters.allowed = 0
41
+ self._logger_counters.time_to_compare = current_time
42
+
43
+ self._logger_counters.allowed += 1
44
+ self._logger_counters.logged += 1
45
+ func(*args, **kwargs)
46
+
47
+ return on_call
48
+ return on_decorator
49
+
50
+
51
+class LoggerCounters:
52
+ def __init__(self):
53
+ self.logged = 0
54
+ self.dropped = 0
55
+ self.allowed = 0
56
+ self.time_to_compare = time()
57
+
58
+ def __repr__(self):
59
+ return '<LoggerCounter: {{logged: {logged}, dropped: {dropped}}}>'.format(logged=self.logged,
60
+ dropped=self.dropped)
61
+
62
+
63
+class BaseLogger(object):
64
+ def __init__(self, logger_name, log_fmt=DEFAULT_LOG_LINE_FORMAT, date_fmt=DEFAULT_LOG_TIME_FORMAT,
65
+ handler=logging.StreamHandler):
66
+ """
67
+ :param logger_name: <str>
68
+ :param log_fmt: <str>
69
+ :param date_fmt: <str>
70
+ :param handler: <logging handler>
71
+ """
72
+ self.logger = logging.getLogger(logger_name)
73
+ if not self.has_handlers():
74
+ self.severity = 'INFO'
75
+ self.logger.addHandler(handler())
76
+ self.set_formatter(fmt=log_fmt, date_fmt=date_fmt)
77
+
78
+ def __repr__(self):
79
+ return '<Logger: {name})>'.format(name=self.logger.name)
80
+
81
+ def set_formatter(self, fmt, date_fmt=DEFAULT_LOG_TIME_FORMAT):
82
+ """
83
+ :param fmt: <str>
84
+ :param date_fmt: <str>
85
+ :return:
86
+ """
87
+ if self.has_handlers():
88
+ self.logger.handlers[0].setFormatter(logging.Formatter(fmt=fmt, datefmt=date_fmt))
89
+
90
+ def has_handlers(self):
91
+ return self.logger.handlers
92
+
93
+ @property
94
+ def severity(self):
95
+ return self.logger.getEffectiveLevel()
96
+
97
+ @severity.setter
98
+ def severity(self, level):
99
+ """
100
+ :param level: <str> or <int>
101
+ :return:
102
+ """
103
+ if level in [lvl for item in LOGGING_LEVELS.items() for lvl in item]:
104
+ self.logger.setLevel(level)
105
+
106
+ def debug(self, *msg, **kwargs):
107
+ self.logger.debug(' '.join(map(str, msg)), **kwargs)
108
+
109
+ def info(self, *msg, **kwargs):
110
+ self.logger.info(' '.join(map(str, msg)), **kwargs)
111
+
112
+ def warning(self, *msg, **kwargs):
113
+ self.logger.warning(' '.join(map(str, msg)), **kwargs)
114
+
115
+ def error(self, *msg, **kwargs):
116
+ self.logger.error(' '.join(map(str, msg)), **kwargs)
117
+
118
+ def alert(self, *msg, **kwargs):
119
+ self.logger.critical(' '.join(map(str, msg)), **kwargs)
120
+
121
+ @on_try_except_finally(on_finally=(exit, 1))
122
+ def fatal(self, *msg, **kwargs):
123
+ self.logger.critical(' '.join(map(str, msg)), **kwargs)
124
+
125
+
126
+class PythonDLogger:
127
+ def __init__(self, logger_name=PYTHON_D_LOG_NAME, log_fmt=PYTHON_D_LOG_LINE_FORMAT):
128
+ """
129
+ :param logger_name: <str>
130
+ :param log_fmt: <str>
131
+ """
132
+ self.logger = BaseLogger(logger_name, log_fmt=log_fmt)
133
+ self.module_name = 'plugin'
134
+ self.job_name = 'main'
135
+ self._logger_counters = LoggerCounters()
136
+
137
+ def debug(self, *msg):
138
+ self.logger.debug(*msg, extra={'module_name': self.module_name,
139
+ 'job_name': self.job_name or self.module_name})
140
+
141
+ def info(self, *msg):
142
+ self.logger.info(*msg, extra={'module_name': self.module_name,
143
+ 'job_name': self.job_name or self.module_name})
144
+
145
+ def warning(self, *msg):
146
+ self.logger.warning(*msg, extra={'module_name': self.module_name,
147
+ 'job_name': self.job_name or self.module_name})
148
+
149
+ def error(self, *msg):
150
+ self.logger.error(*msg, extra={'module_name': self.module_name,
151
+ 'job_name': self.job_name or self.module_name})
152
+
153
+ def alert(self, *msg):
154
+ self.logger.alert(*msg, extra={'module_name': self.module_name,
155
+ 'job_name': self.job_name or self.module_name})
156
+
157
+ def fatal(self, *msg):
158
+ self.logger.fatal(*msg, extra={'module_name': self.module_name,
159
+ 'job_name': self.job_name or self.module_name})
160
+
161
+
162
+class PythonDLimitedLogger(PythonDLogger):
163
+ @limiter()
164
+ def info(self, *msg):
165
+ PythonDLogger.info(self, *msg)
166
+
167
+ @limiter()
168
+ def warning(self, *msg):
169
+ PythonDLogger.warning(self, *msg)
170
+
171
+ @limiter()
172
+ def error(self, *msg):
173
+ PythonDLogger.error(self, *msg)