Browse Source

Add context (#71)

* add traces context

* add trace context section in readme

* fix type

* Update README.md

* Update README.md

* small fix to readme

* fix typo

Co-authored-by: Nico <86240618+nico-shishkin@users.noreply.github.com>
opensearch
Miri 2 years ago
committed by GitHub
parent
commit
7e9a48fa06
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 139 additions and 5 deletions
  1. +45
    -1
      README.md
  2. +7
    -1
      logzio/handler.py
  3. +3
    -1
      requirements.txt
  4. +4
    -2
      setup.py
  5. +80
    -0
      tests/test_add_context.py

+ 45
- 1
README.md View File

@ -100,6 +100,7 @@ LOGGING = {
'level': 'INFO',
'formatter': 'logzioFormat',
'token': '<<LOGZIO-TOKEN>>',
'logzio_type': 'python-handler',
'logs_drain_timeout': 5,
'url': 'https://<<LOGZIO-URL>>:8071',
'retries_no': 4,
@ -211,9 +212,52 @@ LOGGING = {
- logzio_type - Log type, for searching in logz.io (defaults to "python"), it cannot contain a space.
- appname - Your django app
Please note that if you are using `python 3.8` it is preferred to use the `logging.config.dictConfig` method, as mentioned in [python's documentation](https://docs.python.org/3/library/logging.config.html#configuration-file-format).
## Trace context
If you're sending traces with OpenTelemetry instrumentation (auto or manual), you can correlate your logs with the trace context.
That way, your logs will have traces data in it, such as service name, span id and trace id.
To enable this feature, set the `add_context` param in your handler configuration to `True`, like in this example:
```python
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'logzioFormat': {
'format': '{"additional_field": "value"}',
'validate': False
}
},
'handlers': {
'logzio': {
'class': 'logzio.handler.LogzioHandler',
'level': 'INFO',
'formatter': 'logzioFormat',
'token': '<<LOGZIO-TOKEN>>',
'logzio_type': 'python-handler',
'logs_drain_timeout': 5,
'url': 'https://<<LOGZIO-URL>>:8071',
'retries_no': 4,
'retry_timeout': 2,
'add_context': True
}
},
'loggers': {
'': {
'level': 'DEBUG',
'handlers': ['logzio'],
'propagate': True
}
}
}
```
Please note that if you are using `python 3.8`, it is preferred to use the `logging.config.dictConfig` method, as mentioned in [python's documentation](https://docs.python.org/3/library/logging.config.html#configuration-file-format).
## Release Notes
- 4.0.0
- Add ability to automatically attach trace context to the logs.
- 3.1.1
- Bug fixes (issue #68, exception message formatting)
- Added CI: Tests and Auto release


+ 7
- 1
logzio/handler.py View File

@ -8,6 +8,8 @@ import logging.handlers
from .sender import LogzioSender
from .exceptions import LogzioException
from opentelemetry.instrumentation.logging import LoggingInstrumentor
class LogzioHandler(logging.Handler):
@ -20,13 +22,17 @@ class LogzioHandler(logging.Handler):
backup_logs=True,
network_timeout=10.0,
retries_no=4,
retry_timeout=2):
retry_timeout=2,
add_context=False):
if not token:
raise LogzioException('Logz.io Token must be provided')
self.logzio_type = logzio_type
if add_context:
LoggingInstrumentor().instrument(set_logging_format=True)
self.logzio_sender = LogzioSender(
token=token,
url=url,


+ 3
- 1
requirements.txt View File

@ -1 +1,3 @@
requests>=2.27.0
requests>=2.27.0
protobuf==3.20.1
opentelemetry-instrumentation-logging==0.32b0

+ 4
- 2
setup.py View File

@ -3,7 +3,7 @@
from setuptools import setup, find_packages
setup(
name="logzio-python-handler",
version='3.1.1',
version='4.0.0',
description="Logging handler to send logs to your Logz.io account with bulk SSL",
keywords="logging handler logz.io bulk https",
author="roiravhon",
@ -13,7 +13,9 @@ setup(
license="Apache License 2",
packages=find_packages(),
install_requires=[
"requests>=2.27.0"
"requests>=2.27.0",
"protobuf==3.20.1",
"opentelemetry-instrumentation-logging==0.32b0"
],
test_requires=[
"future"


+ 80
- 0
tests/test_add_context.py View File

@ -0,0 +1,80 @@
import fnmatch
import logging.config
import os
import time
import json
from unittest import TestCase
from .mockLogzioListener import listener
def _find(pattern, path):
result = []
for root, dirs, files in os.walk(path):
for name in files:
if fnmatch.fnmatch(name, pattern):
result.append(os.path.join(root, name))
break # Not descending recursively
return result
class TestAddContext(TestCase):
def setUp(self):
self.logzio_listener = listener.MockLogzioListener()
self.logzio_listener.clear_logs_buffer()
self.logzio_listener.clear_server_error()
self.logs_drain_timeout = 1
self.retries_no = 4
self.retry_timeout = 2
logging_configuration = {
"version": 1,
"formatters": {
"logzio": {
"format": '{"key": "value"}',
"validate": False
}
},
"handlers": {
"LogzioHandler": {
"class": "logzio.handler.LogzioHandler",
"formatter": "logzio",
"level": "DEBUG",
"token": "token",
'logzio_type': "type",
'logs_drain_timeout': self.logs_drain_timeout,
'url': "http://" + self.logzio_listener.get_host() + ":" + str(self.logzio_listener.get_port()),
'debug': True,
'retries_no': self.retries_no,
'retry_timeout': self.retry_timeout,
'add_context': True
}
},
"loggers": {
"test": {
"handlers": ["LogzioHandler"],
"level": "DEBUG"
}
}
}
logging.config.dictConfig(logging_configuration)
self.logger = logging.getLogger('test')
for curr_file in _find("logzio-failures-*.txt", "."):
os.remove(curr_file)
def test_add_context(self):
log_message = "this log should have a trace context"
self.logger.info(log_message)
time.sleep(self.logs_drain_timeout * 2)
logs_list = self.logzio_listener.logs_list
for current_log in logs_list:
if log_message in current_log:
log_dict = json.loads(current_log)
self.assertTrue('otelSpanID' in log_dict)
self.assertTrue('otelTraceID' in log_dict)
self.assertTrue('otelServiceName' in log_dict)

Loading…
Cancel
Save