|
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 | + |
0 commit comments