|
2 | 2 | python-logstash-async |
3 | 3 | ===================== |
4 | 4 |
|
5 | | -Python logging handler for asynchronous event processing and transport to Logstash. |
6 | | -http://logstash.net/ |
| 5 | +Python Logstash Async is an asynchronous Python logging handler to submit |
| 6 | +log events to a remote Logstash instance. |
7 | 7 |
|
| 8 | +Unlike most other Python Logstash logging handlers, this package works asynchronously |
| 9 | +by collecting log events from Python's logging subsystem and then transmitting the |
| 10 | +collected events in a separate worker thread to Logstash. |
| 11 | +This way, the main application (or thread) where the log event occurred, doesn't need to |
| 12 | +wait until the submission to the remote Logstash instance succeeded. |
8 | 13 |
|
9 | | -About |
10 | | ------ |
| 14 | +This is especially useful for applications like websites or web services or any kind of |
| 15 | +request serving API where response times matter. |
11 | 16 |
|
12 | | -This Python logging handler is a fork of |
13 | | -https://github.com/vklochan/python-logstash. |
| 17 | +For more details, configuration options and usage examples please see the |
| 18 | +documentation at http://python-logstash-async.readthedocs.io/en/latest/. |
14 | 19 |
|
15 | | -It adds the following features: |
16 | | - |
17 | | - * Asynchronous transport of log events |
18 | | - * Store log events temporarily in a SQLite database until transport |
19 | | - to the Logstash server has been successful |
20 | | - * Transport of events via TCP and UDP, in the future hopefully via |
21 | | - the Beats protocol |
22 | | - * TCP transport optionally SSL-encrypted |
23 | | - * Special formatter ready to be used in Django projects |
24 | | - |
25 | | - |
26 | | -Asynchronous processing |
27 | | -^^^^^^^^^^^^^^^^^^^^^^^ |
28 | | - |
29 | | -Unlike the original ``python-logstash``, this handler will try to |
30 | | -handle log events as fast as possible so that the sending program |
31 | | -code can continue with its primary job. |
32 | | -In other words, for web applications or web services it is important |
33 | | -to not slow down request times due to logging delays, e.g. waiting |
34 | | -for network timeouts to the Logstash server or similar. |
35 | | - |
36 | | -So this handler will accept log events and pass them for further |
37 | | -processing to a separate worker thread which will try to send |
38 | | -the events to the configured Logstash server asynchronously. |
39 | | -If sending the events fails, the events are stored in a |
40 | | -local SQLite database for a later sending attempt. |
41 | | - |
42 | | -Whenever the application stops, to be more exact whenever |
43 | | -Python' logging subsystem is shutdown, the worker thread |
44 | | -is signaled to send any queued events and clean up itself |
45 | | -before shutdown. |
46 | | - |
47 | | -The sending intervals and timeouts can be configured in the |
48 | | -``logstash_async.constants`` module by the corresponding |
49 | | -module-level constants, see below for details. |
| 20 | +.. image:: https://readthedocs.org/projects/python-logstash-async/badge/?version=latest |
| 21 | + :target: http://python-logstash-async.readthedocs.io/en/latest/ |
| 22 | + :alt: Documentation Status |
50 | 23 |
|
51 | 24 |
|
52 | 25 | Installation |
53 | 26 | ------------ |
54 | 27 |
|
55 | | -Using pip:: |
| 28 | +The easiest method is to install directly from pypi using pip:: |
56 | 29 |
|
57 | 30 | pip install python-logstash-async |
58 | 31 |
|
59 | | -Usage |
60 | | ------ |
61 | | - |
62 | | -`AsynchronousLogstashHandler` is a custom logging handler which |
63 | | -sends Logstash messages using UDP and TCP. For example: |
64 | | - |
65 | | -.. code:: python |
66 | | -
|
67 | | - import logging |
68 | | - import sys |
69 | | - from logstash_async.handler import AsynchronousLogstashHandler |
70 | | -
|
71 | | - host = 'localhost' |
72 | | - port = 5959 |
73 | | -
|
74 | | - test_logger = logging.getLogger('python-logstash-logger') |
75 | | - test_logger.setLevel(logging.INFO) |
76 | | - test_logger.addHandler(AsynchronousLogstashHandler( |
77 | | - host, port, database_path='logstash.db'))) |
78 | | - # test_logger.addHandler(AsynchronousLogstashHandler(host, port)) |
79 | | -
|
80 | | - test_logger.error('python-logstash-async: test logstash error message.') |
81 | | - test_logger.info('python-logstash-async: test logstash info message.') |
82 | | - test_logger.warning('python-logstash-async: test logstash warning message.') |
83 | | -
|
84 | | - # add extra field to logstash message |
85 | | - extra = { |
86 | | - 'test_string': 'python version: ' + repr(sys.version_info), |
87 | | - 'test_boolean': True, |
88 | | - 'test_dict': {'a': 1, 'b': 'c'}, |
89 | | - 'test_float': 1.23, |
90 | | - 'test_integer': 123, |
91 | | - 'test_list': [1, 2, '3'], |
92 | | - } |
93 | | - test_logger.info('python-logstash: test extra fields', extra=extra) |
94 | | -
|
95 | | -When using the ``extra`` field make sure you don't use reserved names. |
96 | | -From `Python documentation <https://docs.python.org/2/library/logging.html>`_:: |
97 | | - |
98 | | - "The keys in the dictionary passed in extra should not clash |
99 | | - with the keys used by the logging system. |
100 | | - (See the `Formatter <https://docs.python.org/2/library/logging.html#logging.Formatter>`_ documentation |
101 | | - for more information on which keys are used by the logging system.)" |
102 | | - |
103 | | -You can also specify an additional extra dictionary in the logging configuration with static |
104 | | -values like the application name, environment, etc. These values will be merged with any |
105 | | -extra dictionary items passed in the logging call into the configured extra prefix. |
106 | | - |
107 | | - |
108 | | -Usage with Django |
109 | | ------------------ |
110 | | - |
111 | | -Modify your ``settings.py`` to integrate ``python-logstash-async`` with Django's logging: |
112 | | - |
113 | | -.. code:: python |
114 | | -
|
115 | | - LOGGING = { |
116 | | - ... |
117 | | - 'formatters': { |
118 | | - ... |
119 | | - 'logstash': { |
120 | | - '()': 'logstash_async.formatter.DjangoLogstashFormatter', |
121 | | - 'message_type': 'python-logstash', |
122 | | - 'fqdn': False, # Fully qualified domain name. Default value: false. |
123 | | - 'extra_prefix': 'dev', # |
124 | | - 'extra': { |
125 | | - 'application': PROJECT_APP, |
126 | | - 'project_path': PROJECT_APP_PATH, |
127 | | - 'environment': 'production' |
128 | | - } |
129 | | - }, |
130 | | - }, |
131 | | - 'handlers': { |
132 | | - ... |
133 | | - 'logstash': { |
134 | | - 'level': 'DEBUG', |
135 | | - 'class': 'logstash_async.handler.AsynchronousLogstashHandler', |
136 | | - 'transport': 'logstash_async.transport.TcpTransport', |
137 | | - 'host': 'logstash.host.tld', |
138 | | - 'port': 5959, |
139 | | - 'ssl_enable': True, |
140 | | - 'ssl_verify': True, |
141 | | - 'ca_certs': 'etc/ssl/certs/logstash_ca.crt', |
142 | | - 'certfile': '/etc/ssl/certs/logstash.crt', |
143 | | - 'keyfile': '/etc/ssl/private/logstash.key', |
144 | | - 'database_path': '{}/logstash.db'.format(PROJECT_ROOT), |
145 | | - }, |
146 | | - }, |
147 | | - 'loggers': { |
148 | | - 'django.request': { |
149 | | - 'handlers': ['logstash'], |
150 | | - 'level': 'DEBUG', |
151 | | - 'propagate': True, |
152 | | - }, |
153 | | - }, |
154 | | - ... |
155 | | - } |
156 | | -
|
157 | | -This would result in a Logstash event like the following |
158 | | -(note: to some extend dependent of your Logstash configuration): |
159 | | - |
160 | | -.. code:: json |
161 | | -
|
162 | | - { |
163 | | - "@timestamp": "2016-10-23T15:11:16.853Z", |
164 | | - "@version": "1", |
165 | | - "extra": { |
166 | | - "application": "django_example", |
167 | | - "django_version": "1.10.2", |
168 | | - "environment": "production", |
169 | | - "func_name": "get_response", |
170 | | - "interpreter": "/home/enrico/example/venv/bin/python", |
171 | | - "interpreter_version": "2.7.12", |
172 | | - "line": 152, |
173 | | - "logger_name": "django.request", |
174 | | - "path": "/home/enrico/example/venv/lib/python2.7/site-packages/django/core/handlers/base.py", |
175 | | - "process_name": "MainProcess", |
176 | | - "project_path": "/home/enrico/example/app", |
177 | | - "req_host": "localhost", |
178 | | - "req_method": "GET", |
179 | | - "req_referer": "", |
180 | | - "req_remote_address": "127.0.0.1", |
181 | | - "req_uri": "http://localhost/hosts/nonexistent/", |
182 | | - "req_user": "enrico", |
183 | | - "req_useragent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1", |
184 | | - "request": "<WSGIRequest: GET '/hosts/nonexistent/'>", |
185 | | - "status_code": 404, |
186 | | - "thread_name": "Thread-1" |
187 | | - }, |
188 | | - "host": "my.host.tld", |
189 | | - "level": "WARNING", |
190 | | - "logsource": "endor.l8failed.net", |
191 | | - "message": "Not Found: /hosts/nonexistent/", |
192 | | - "pid": 23605, |
193 | | - "port": 56170, |
194 | | - "program": "manage.py", |
195 | | - "type": "python-logstash" |
196 | | - } |
197 | | -
|
198 | | -
|
199 | | -Configuration |
200 | | -------------- |
201 | 32 |
|
202 | | -Options for configuring the log handler |
203 | | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 33 | +If you prefer, you can download python-logstash-async and install it |
| 34 | +directly from source:: |
204 | 35 |
|
205 | | -host |
206 | | - The host of the Logstash server (no default) |
| 36 | + $ python setup.py install |
207 | 37 |
|
208 | | -port |
209 | | - The port of the Logstash server (default 5959) |
210 | 38 |
|
211 | | -transport |
212 | | - Callable or path to a compatible transport class |
213 | | - (default: 'logstash_async.transport.TcpTransport'). |
| 39 | +Get the Source |
| 40 | +-------------- |
214 | 41 |
|
215 | | - You can specify your own transport class, e.g. to implement |
216 | | - a transport via Redis or the Beats protocol. |
217 | | - If you support pass a string, it should be a path to a |
218 | | - class which can be imported. |
219 | | - If you pass anything else, it should be an object of a class |
220 | | - with a similar interface as `logstash_async.transport.TcpTransport`. |
221 | | - Especially it should provide a `close()` and a `send()` method. |
| 42 | +The source code is available at https://github.com/eht16/python-logstash-async/. |
222 | 43 |
|
223 | | -ssl_enable |
224 | | - Should SSL be enabled for the connection? (default: False) |
225 | | - Only used for `logstash_async.transport.TcpTransport`. |
226 | 44 |
|
227 | | -ssl_verify |
228 | | - Should the server's SSL certificate be verified? (default: True) |
229 | | - Only used for `logstash_async.transport.TcpTransport`. |
230 | | - |
231 | | -keyfile |
232 | | - The path to client side SSL key file (default: None) |
233 | | - Only used for `logstash_async.transport.TcpTransport`. |
234 | | - |
235 | | -certfile |
236 | | - The path to client side SSL certificate file (default: None) |
237 | | - Only used for `logstash_async.transport.TcpTransport`. |
238 | | - |
239 | | -ca_certs |
240 | | - The path to the file containing recognized CA certificates |
241 | | - (default: None) |
242 | | - Only used for `logstash_async.transport.TcpTransport`. |
243 | | - |
244 | | -database_path |
245 | | - The path to the file containing queued events (default: ':memory:') |
246 | | - |
247 | | -enable |
248 | | - Flag to enable log processing (default is True, disabling |
249 | | - might be handy for local testing, etc.) |
250 | | - |
251 | | - |
252 | | -Options for configuring the log formatter |
253 | | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
254 | | - |
255 | | -The following settings are only valid for the provided formatters |
256 | | -`logstash_async.handler.LogstashFormatter` and |
257 | | -`logstash_async.handler.DjangoLogstashFormatter`. |
258 | | - |
259 | | -You can use any other formatter by configuring Python's logging |
260 | | -system accordingly. Any other formatter's `format()` method just |
261 | | -should return valid JSON suitable to be sent to Logstash |
262 | | -(see `Example Logstash Configuration`_ below). |
263 | | - |
264 | | -Options: |
265 | | - |
266 | | -message_type |
267 | | - The `type` field in the message sent to Logstash |
268 | | - (default: 'python-logstash') |
269 | | - |
270 | | -tags |
271 | | - Additional tags to include in the Logstash message (default: None) |
272 | | - |
273 | | -fqdn |
274 | | - Use the system's FQDN (fully qualified domain name) in the `host` |
275 | | - field of the message sent to Logstash. |
276 | | - `socket.getfqdn()` is used to retrieve the FQDN, otherwise |
277 | | - `socket.gethostname()` is used for the default hostname. |
278 | | - (default: False) |
279 | | - |
280 | | -extra_prefix |
281 | | - Name of the field in the resulting message sent to Logstash where |
282 | | - all additional fields are grouped into. Consider it as some sort |
283 | | - of namespace for all non-standard fields in the log event. |
284 | | - This field will take any items passed in as extra fields via |
285 | | - the `extra` configuration option (see below) as well as any extra |
286 | | - items passed in the logging call. |
287 | | - |
288 | | - To disable grouping of the extra items and have them on the top |
289 | | - level of the log event message, simply set this option to `None` |
290 | | - or the empty string. |
291 | | - (default: 'extra') |
292 | | - |
293 | | -extra |
294 | | - Dictionary with static items to be included in the message sent |
295 | | - to Logstash. This dictionary will be merged with any other extra |
296 | | - items passed in the logging call. |
297 | | - (default: None) |
298 | | - |
299 | | - |
300 | | -Options for the asynchronous processing (in module logstash_async.constants) |
301 | | -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
302 | | - |
303 | | -SOCKET_TIMEOUT |
304 | | - Timeout in seconds for TCP connections (default: 5.0) |
305 | | - |
306 | | -QUEUE_CHECK_INTERVAL |
307 | | - Interval in seconds to check the internal queue for new messages |
308 | | - to be cached in the database (default: 2.0) |
309 | | - |
310 | | -QUEUED_EVENTS_FLUSH_INTERVAL |
311 | | - Interval in seconds to send cached events from the database |
312 | | - to Logstash (default 10.0) |
313 | | - |
314 | | -QUEUED_EVENTS_FLUSH_COUNT |
315 | | - Count of cached events to send cached events from the database |
316 | | - to Logstash; events are sent to Logstash whenever |
317 | | - `QUEUED_EVENTS_FLUSH_COUNT` or `QUEUED_EVENTS_FLUSH_INTERVAL` is reached, |
318 | | - whatever happens first (default 50) |
319 | | - |
320 | | - |
321 | | -Example Logstash Configuration |
322 | | ------------------------------- |
323 | | - |
324 | | -Example ``logstash.conf`` for unencrypted TCP transport:: |
325 | | - |
326 | | - input { |
327 | | - tcp { |
328 | | - host => "127.0.0.1" |
329 | | - port => 5959 |
330 | | - mode => server |
331 | | - codec => json |
332 | | - } |
333 | | - } |
| 45 | +Contributing |
| 46 | +------------ |
334 | 47 |
|
| 48 | +Found a bug or got a feature request? Please report it at |
| 49 | +https://github.com/eht16/python-logstash-async/issues. |
335 | 50 |
|
336 | | -Example ``logstash.conf`` for SSL-encrypted TCP transport:: |
337 | 51 |
|
338 | | - input { |
339 | | - tcp { |
340 | | - host => "127.0.0.1" |
341 | | - port => 5958 |
342 | | - mode => server |
343 | | - codec => json |
| 52 | +Author |
| 53 | +------ |
344 | 54 |
|
345 | | - ssl_enable => true |
346 | | - ssl_verify => true |
347 | | - ssl_extra_chain_certs => ["/etc/ssl/certs/logstash_ca.crt"] |
348 | | - ssl_cert => "/etc/ssl/certs/logstash.crt" |
349 | | - ssl_key => "/etc/ssl/private/logstash.key" |
350 | | - } |
351 | | - } |
| 55 | +Enrico Tröger <enrico.troeger@uvena.de> |
0 commit comments