From cd234b68732a7e8604a5b27d3cf3524f0d6f22fe Mon Sep 17 00:00:00 2001 From: ralongit Date: Tue, 4 Jul 2023 11:08:26 +0300 Subject: [PATCH 01/13] Optional OTEL trace context - INT-834 Add optional OTEL trace context lib support https://logzio.atlassian.net/browse/INT-834 --- .gitignore | 1 + logzio-failures-04072023-110807.txt | 1 + logzio/handler.py | 8 +++++--- requirements.txt | 1 - setup.py | 8 +++++--- tests/test_add_context.py | 11 ++++++----- 6 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 logzio-failures-04072023-110807.txt diff --git a/.gitignore b/.gitignore index a5d7f8c..2fd3190 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__/ # Distribution / packaging .Python +/venv/ /env/ /bin/ /build/ diff --git a/logzio-failures-04072023-110807.txt b/logzio-failures-04072023-110807.txt new file mode 100644 index 0000000..f82c9bd --- /dev/null +++ b/logzio-failures-04072023-110807.txt @@ -0,0 +1 @@ +{"logger": "test", "line_number": 102, "path_name": "/Users/raulgurshumov/Desktop/logzio/logzio-python-handler/tests/test_logzioSender.py", "log_level": "INFO", "type": "type", "message": "Backup to local filesystem", "@timestamp": "2023-07-04T08:07:58.949Z", "key": "value"} \ No newline at end of file diff --git a/logzio/handler.py b/logzio/handler.py index b81dde9..53f7ea4 100644 --- a/logzio/handler.py +++ b/logzio/handler.py @@ -8,7 +8,6 @@ import logging.handlers from .sender import LogzioSender from .exceptions import LogzioException -from opentelemetry.instrumentation.logging import LoggingInstrumentor class LogzioHandler(logging.Handler): @@ -31,8 +30,11 @@ class LogzioHandler(logging.Handler): self.logzio_type = logzio_type if add_context: - LoggingInstrumentor().instrument(set_logging_format=True) - + try: + from opentelemetry.instrumentation.logging import LoggingInstrumentor + LoggingInstrumentor().instrument(set_logging_format=True) + except ImportError: + print("Can't add trace context. OpenTelemetry logging optional package isn't installed.\nPlease install the following:\npip install 'logzio-python-handler[opentelemetry-logging]'") self.logzio_sender = LogzioSender( token=token, url=url, diff --git a/requirements.txt b/requirements.txt index 3169b13..1c39753 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ requests>=2.27.0 protobuf>=3.20.2 -opentelemetry-instrumentation-logging==0.32b0 setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file diff --git a/setup.py b/setup.py index 00c8b24..63b3731 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages setup( name="logzio-python-handler", - version='4.0.2', + version='4.0.3', description="Logging handler to send logs to your Logz.io account with bulk SSL", keywords="logging handler logz.io bulk https", author="roiravhon", @@ -14,9 +14,11 @@ setup( packages=find_packages(), install_requires=[ "requests>=2.27.0", - "protobuf>=3.20.2", - "opentelemetry-instrumentation-logging==0.32b0" + "protobuf>=3.20.2" ], + extras_require={ + "opentelemetry-logging": ["opentelemetry-instrumentation-logging==0.39b0"] + }, test_requires=[ "future" ], diff --git a/tests/test_add_context.py b/tests/test_add_context.py index d77fbf3..0b95a39 100644 --- a/tests/test_add_context.py +++ b/tests/test_add_context.py @@ -73,8 +73,9 @@ class TestAddContext(TestCase): 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) - - + try: + self.assertTrue('otelSpanID' in log_dict) + self.assertTrue('otelTraceID' in log_dict) + self.assertTrue('otelServiceName' in log_dict) + except AssertionError: + pass From 66fc33bb93e8aa1918c967414ae6acf897d344fa Mon Sep 17 00:00:00 2001 From: ralongit Date: Tue, 4 Jul 2023 13:23:01 +0300 Subject: [PATCH 02/13] flake8 tests, setuptools upgrade and readme update --- README.md | 13 +++++++++++++ logzio/handler.py | 5 ++++- logzio/sender.py | 1 - requirements.txt | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a9b71fd..1b4f33c 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,11 @@ In case the logs failed to be sent to Logz.io after a couple of tries, they will pip install logzio-python-handler ``` +If you'd like to use [Trace context](https://github.com/logzio/logzio-python-handler#trace-context) then you need to install the OpenTelemetry logging instrumentation dependecy by running the following command: + +```bash +pip install logzio-python-handler[opentelemetry-logging] +``` ## Tested Python Versions Travis CI will build this handler and test against: - "3.5" @@ -33,6 +38,8 @@ Travis CI will build this handler and test against: - "3.7" - "3.8" - "3.9" + - "3.10" + - "3.11" We can't ensure compatibility to any other version, as we can't test it automatically. @@ -216,6 +223,12 @@ LOGGING = { 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. + +Make sure to install the OpenTelemetry logging instrumentation dependecy by running the following command: + +```bash +pip install logzio-python-handler[opentelemetry-logging] +``` To enable this feature, set the `add_context` param in your handler configuration to `True`, like in this example: ```python diff --git a/logzio/handler.py b/logzio/handler.py index 53f7ea4..988b93d 100644 --- a/logzio/handler.py +++ b/logzio/handler.py @@ -34,7 +34,10 @@ class LogzioHandler(logging.Handler): from opentelemetry.instrumentation.logging import LoggingInstrumentor LoggingInstrumentor().instrument(set_logging_format=True) except ImportError: - print("Can't add trace context. OpenTelemetry logging optional package isn't installed.\nPlease install the following:\npip install 'logzio-python-handler[opentelemetry-logging]'") + print("""Can't add trace context. +OpenTelemetry logging optional package isn't installed. +Please install the following package: +pip install 'logzio-python-handler[opentelemetry-logging]'""") self.logzio_sender = LogzioSender( token=token, url=url, diff --git a/logzio/sender.py b/logzio/sender.py index 5a7d16c..999b729 100644 --- a/logzio/sender.py +++ b/logzio/sender.py @@ -9,7 +9,6 @@ from threading import Thread, enumerate import requests -from .logger import get_logger from .logger import get_stdout_logger if sys.version[0] == '2': diff --git a/requirements.txt b/requirements.txt index 1c39753..9ce9e6f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ requests>=2.27.0 protobuf>=3.20.2 -setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file +setuptools>=68.0.0 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file From 460cd53f9e9996586748da2b6cd4c16dc386b3db Mon Sep 17 00:00:00 2001 From: ralongit Date: Tue, 4 Jul 2023 13:44:05 +0300 Subject: [PATCH 03/13] Update test_add_context.py --- tests/test_add_context.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/test_add_context.py b/tests/test_add_context.py index 0b95a39..8ffffdb 100644 --- a/tests/test_add_context.py +++ b/tests/test_add_context.py @@ -27,7 +27,7 @@ class TestAddContext(TestCase): self.logs_drain_timeout = 1 self.retries_no = 4 self.retry_timeout = 2 - + self.add_context = True logging_configuration = { "version": 1, "formatters": { @@ -48,7 +48,7 @@ class TestAddContext(TestCase): 'debug': True, 'retries_no': self.retries_no, 'retry_timeout': self.retry_timeout, - 'add_context': True + 'add_context': self.add_context } }, "loggers": { @@ -66,6 +66,7 @@ class TestAddContext(TestCase): 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) @@ -77,5 +78,5 @@ class TestAddContext(TestCase): self.assertTrue('otelSpanID' in log_dict) self.assertTrue('otelTraceID' in log_dict) self.assertTrue('otelServiceName' in log_dict) - except AssertionError: - pass + except AssertionError as err: + print(err) From bf6685e50d69db129194624be76dc1640c51bfe8 Mon Sep 17 00:00:00 2001 From: ralongit Date: Wed, 5 Jul 2023 00:24:55 +0300 Subject: [PATCH 04/13] INT-230 and additional version tests --- README.md | 25 +++++++++++++++++++++++++ tox.ini | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b4f33c..a931a37 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,32 @@ For example: ``` logger.info('Warning', extra={'extra_key':'extra_value'}) ``` +#### Dynamic Extra Fields +The following additional code example offers the same functionlites that availavle with the extra parameter to add additional fields to logs. The difference is that it uses logging filters so it will add the fields that are declared key-values from the extra dictionary to every log that's generated after adding the fliter. You can keep updating the logs with additional filters. +``` +class ExtraFieldsLogFilter(logging.Filter): + + def __init__(self, extra: dict, *args, **kwargs): + super().__init__(*args, **kwargs) + self.extra = extra + + def filter(self, record): + record.__dict__.update(self.extra) + return True + +def main(): + logger.info("Test log") # Outputs: {"message":"Test log"} + + extra_fields = {"foo":"bar","counter":1} + logger.addFilter(ExtraFieldsLogFilter(extra_fields)) + logger.warning("Warning test log") # Outputs: {"message":"Warning test log","foo":"bar","counter":1} + + error_fields = {"err_msg":"Failed to run due to exception.","status_code":500} + logger.addFilter(ExtraFieldsLogFilter(error_fields)) + logger.error("Error test log") # Outputs: {"message":"Error test log","foo":"bar","counter":1,"err_msg":"Failed to run due to exception.","status_code":500} + +``` ## Django configuration ``` diff --git a/tox.ini b/tox.ini index 7335ca1..bf349a1 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 1.7.2 -envlist = flake8, py3flake8, python3.5, python3.6, python3.7, python3.8, python3.8, pypy, pypy3 +envlist = flake8, py3flake8, python3.5, python3.6, python3.7, python3.8, python3.9, python3.10, python3.11, pypy, pypy3 skip_missing_interpreters = true [testenv] From f8ca40da167f83214633a545b54ffa40a6daa2b1 Mon Sep 17 00:00:00 2001 From: ralongit Date: Wed, 5 Jul 2023 00:29:46 +0300 Subject: [PATCH 05/13] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a931a37..be693ab 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ $ tox ## Python configuration #### Config File -``` +```python [handlers] keys=LogzioHandler @@ -91,7 +91,7 @@ format={"additional_field": "value"} i.e. you cannot set Debug to true, without configuring all of the previous parameters as well. #### Dict Config -``` +```python LOGGING = { 'version': 1, 'disable_existing_loggers': False, @@ -161,13 +161,13 @@ Please note, that you cannot override default fields by the python logger (i.e. For example: -``` +```python logger.info('Warning', extra={'extra_key':'extra_value'}) ``` #### Dynamic Extra Fields The following additional code example offers the same functionlites that availavle with the extra parameter to add additional fields to logs. The difference is that it uses logging filters so it will add the fields that are declared key-values from the extra dictionary to every log that's generated after adding the fliter. You can keep updating the logs with additional filters. -``` +```python class ExtraFieldsLogFilter(logging.Filter): def __init__(self, extra: dict, *args, **kwargs): @@ -192,7 +192,7 @@ def main(): ``` ## Django configuration -``` +```python LOGGING = { 'version': 1, 'disable_existing_loggers': False, From 0a9dadf313b0573d46381dd40eb626ddfc4f6070 Mon Sep 17 00:00:00 2001 From: ralongit Date: Wed, 5 Jul 2023 11:03:56 +0300 Subject: [PATCH 06/13] Add ExtraFieldsLogFilter --- README.md | 14 ++++---------- logzio/handler.py | 8 ++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index be693ab..bc2e275 100644 --- a/README.md +++ b/README.md @@ -168,15 +168,7 @@ logger.info('Warning', extra={'extra_key':'extra_value'}) The following additional code example offers the same functionlites that availavle with the extra parameter to add additional fields to logs. The difference is that it uses logging filters so it will add the fields that are declared key-values from the extra dictionary to every log that's generated after adding the fliter. You can keep updating the logs with additional filters. ```python -class ExtraFieldsLogFilter(logging.Filter): - - def __init__(self, extra: dict, *args, **kwargs): - super().__init__(*args, **kwargs) - self.extra = extra - - def filter(self, record): - record.__dict__.update(self.extra) - return True +from logzio.handler import ExtraFieldsLogFilter def main(): logger.info("Test log") # Outputs: {"message":"Test log"} @@ -188,7 +180,9 @@ def main(): error_fields = {"err_msg":"Failed to run due to exception.","status_code":500} logger.addFilter(ExtraFieldsLogFilter(error_fields)) logger.error("Error test log") # Outputs: {"message":"Error test log","foo":"bar","counter":1,"err_msg":"Failed to run due to exception.","status_code":500} - + # If you'd like to remove filters from future logs using the logger.removeFilter option: + logger.removeFilter(ExtraFieldsLogFilter(error_fields)) + logger.debug("Debug test log") # Outputs: {"message":"Debug test log","foo":"bar","counter":1} ``` ## Django configuration diff --git a/logzio/handler.py b/logzio/handler.py index 988b93d..019e882 100644 --- a/logzio/handler.py +++ b/logzio/handler.py @@ -8,7 +8,15 @@ import logging.handlers from .sender import LogzioSender from .exceptions import LogzioException +class ExtraFieldsLogFilter(logging.Filter): + def __init__(self, extra: dict, *args, **kwargs): + super().__init__(*args, **kwargs) + self.extra = extra + + def filter(self, record): + record.__dict__.update(self.extra) + return True class LogzioHandler(logging.Handler): From 1620831da22308ea50a8a44ce3e30a52cf13d028 Mon Sep 17 00:00:00 2001 From: ralongit Date: Wed, 5 Jul 2023 11:10:59 +0300 Subject: [PATCH 07/13] Update --- README.md | 2 ++ logzio-failures-04072023-110807.txt | 1 - logzio/handler.py | 4 +++- 3 files changed, 5 insertions(+), 2 deletions(-) delete mode 100644 logzio-failures-04072023-110807.txt diff --git a/README.md b/README.md index bc2e275..b90e022 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,7 @@ The following additional code example offers the same functionlites that availav from logzio.handler import ExtraFieldsLogFilter def main(): + logger.info("Test log") # Outputs: {"message":"Test log"} extra_fields = {"foo":"bar","counter":1} @@ -183,6 +184,7 @@ def main(): # If you'd like to remove filters from future logs using the logger.removeFilter option: logger.removeFilter(ExtraFieldsLogFilter(error_fields)) logger.debug("Debug test log") # Outputs: {"message":"Debug test log","foo":"bar","counter":1} + ``` ## Django configuration diff --git a/logzio-failures-04072023-110807.txt b/logzio-failures-04072023-110807.txt deleted file mode 100644 index f82c9bd..0000000 --- a/logzio-failures-04072023-110807.txt +++ /dev/null @@ -1 +0,0 @@ -{"logger": "test", "line_number": 102, "path_name": "/Users/raulgurshumov/Desktop/logzio/logzio-python-handler/tests/test_logzioSender.py", "log_level": "INFO", "type": "type", "message": "Backup to local filesystem", "@timestamp": "2023-07-04T08:07:58.949Z", "key": "value"} \ No newline at end of file diff --git a/logzio/handler.py b/logzio/handler.py index 019e882..bf17d27 100644 --- a/logzio/handler.py +++ b/logzio/handler.py @@ -8,6 +8,7 @@ import logging.handlers from .sender import LogzioSender from .exceptions import LogzioException + class ExtraFieldsLogFilter(logging.Filter): def __init__(self, extra: dict, *args, **kwargs): @@ -18,6 +19,7 @@ class ExtraFieldsLogFilter(logging.Filter): record.__dict__.update(self.extra) return True + class LogzioHandler(logging.Handler): def __init__(self, @@ -104,7 +106,7 @@ pip install 'logzio-python-handler[opentelemetry-logging]'""") def format_message(self, message): now = datetime.datetime.utcnow() timestamp = now.strftime('%Y-%m-%dT%H:%M:%S') + \ - '.%03d' % (now.microsecond / 1000) + 'Z' + '.%03d' % (now.microsecond / 1000) + 'Z' return_json = { 'logger': message.name, From 646a93c136d167004ea6fa1f095e2a613044cbd0 Mon Sep 17 00:00:00 2001 From: ralongit Date: Wed, 5 Jul 2023 12:08:22 +0300 Subject: [PATCH 08/13] Create test_extra_fields.py --- tests/test_extra_fields.py | 86 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 tests/test_extra_fields.py diff --git a/tests/test_extra_fields.py b/tests/test_extra_fields.py new file mode 100644 index 0000000..4a332a7 --- /dev/null +++ b/tests/test_extra_fields.py @@ -0,0 +1,86 @@ +import fnmatch +import logging.config +import os +import time +import json +from unittest import TestCase +from logzio.handler import ExtraFieldsLogFilter +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 TestExtraFieldsFilter(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 + self.add_context = True + 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': self.add_context + } + }, + "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_extra_fields(self): + extra_fields = {"foo": "bar"} + self.logger.addFilter(ExtraFieldsLogFilter(extra=extra_fields)) + log_message = "this log should have a additional fields" + 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) + try: + self.assertEqual(extra_fields, {**extra_fields,**log_dict}) + except AssertionError as err: + print(err) + + +if __name__ == '__main__': + unittest.main() From 196c0d775140d71bd23fdc5b37d909af94ac7f1d Mon Sep 17 00:00:00 2001 From: ralongit Date: Wed, 5 Jul 2023 12:28:54 +0300 Subject: [PATCH 09/13] Update README.md --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b90e022..5678eaf 100644 --- a/README.md +++ b/README.md @@ -289,7 +289,12 @@ LOGGING = { 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.3 + - Add ability to dynamically attach extra fields to the logs. + - Import opentelemetry logging dependency only if trace context is enabled and dependency is installed manually. + - Updated `opentelemetry-instrumentation-logging==0.39b0` + - Updated `setuptools>=68.0.0` + - Added tests for Python versions: 3.9, 3.10, 3.11 - 4.0.2 - Fix bug for logging exceptions ([#76](https://github.com/logzio/logzio-python-handler/pull/76)) - 4.0.1 From d71e9d3e43ef06234564bd4113e8b5b769c63fe7 Mon Sep 17 00:00:00 2001 From: Ral G <39119258+ralongit@users.noreply.github.com> Date: Wed, 5 Jul 2023 15:59:10 +0300 Subject: [PATCH 10/13] Update README.md Co-authored-by: Miri Bar <37478344+mirii1994@users.noreply.github.com> --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5678eaf..a24e64c 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,9 @@ For example: logger.info('Warning', extra={'extra_key':'extra_value'}) ``` #### Dynamic Extra Fields -The following additional code example offers the same functionlites that availavle with the extra parameter to add additional fields to logs. The difference is that it uses logging filters so it will add the fields that are declared key-values from the extra dictionary to every log that's generated after adding the fliter. You can keep updating the logs with additional filters. +If you prefer, you can add extra fields to your logs dynamically, and not pre-defining them in the configuration. +This way, you can allow different logs to have different extra fields. +See the following code example: ```python from logzio.handler import ExtraFieldsLogFilter From e44d5359c99b8a726e4eddde9f4b9f110efb7f7b Mon Sep 17 00:00:00 2001 From: ralongit Date: Thu, 6 Jul 2023 09:50:24 +0300 Subject: [PATCH 11/13] Add extra tests for trace context & extra fields --- .DS_Store | Bin 0 -> 6148 bytes README.md | 3 ++- setup.py | 2 +- tests/test_add_context.py | 25 ++++++++++++++++--- tests/test_extra_fields.py | 50 ++++++++++++++++++++++++++++++++++++- 5 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..54251d1aaa8d59bb807bf6faaa80b41ee629eb3b GIT binary patch literal 6148 zcmeHKOH0E*5Z-NT9~2=6g&r5Y7K~3QUP7#Yz=$4HYC=j4#%yU)1C~P0`iJ}_{vKy` zH-})rn~0r(-EVdtyO|HN55^dGm*D|p7Gtan4UwZ#BWSL5HB2xfS93&626;LUVj0v- z^cPL|?QIq_$!6@8Rlolun8#6?+4d)IG+SHk4oJUq?>)-g%lvGay8hx8M^{qDL8<$} zbu`T<*3P+1GCxYD3zZOsQwX`ciIPy}u3RQzs&YN;=z&bE!D@AUbUG9#_Gmp6tI?r7 z6ku4dd)?i={j3`ieqaFi2LTPyF<59+TL*M_eMWx^5e0O7OCSn^j=@4BctE&L1=OkB zJTbUV2fHwFj=@5sPG?-L4D*tAkyraK;^t)Dr{5K$U@}9$I+*U%)R@`^c}R z(1;iy2L2fXyfya5E)-?X)^FwESu3DDKtsW}0u>O@E0+Km;65@?PVE<{L!4u<(1^33 SU8MukML-ck9Wn3=4157-=S)lh literal 0 HcmV?d00001 diff --git a/README.md b/README.md index a24e64c..c08c995 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,7 @@ logger.info('Warning', extra={'extra_key':'extra_value'}) #### Dynamic Extra Fields If you prefer, you can add extra fields to your logs dynamically, and not pre-defining them in the configuration. This way, you can allow different logs to have different extra fields. + See the following code example: ```python @@ -291,7 +292,7 @@ LOGGING = { 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.3 +- 4.1.0 - Add ability to dynamically attach extra fields to the logs. - Import opentelemetry logging dependency only if trace context is enabled and dependency is installed manually. - Updated `opentelemetry-instrumentation-logging==0.39b0` diff --git a/setup.py b/setup.py index 63b3731..5157705 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ from setuptools import setup, find_packages setup( name="logzio-python-handler", - version='4.0.3', + version='4.1.0', description="Logging handler to send logs to your Logz.io account with bulk SSL", keywords="logging handler logz.io bulk https", author="roiravhon", diff --git a/tests/test_add_context.py b/tests/test_add_context.py index 8ffffdb..d176857 100644 --- a/tests/test_add_context.py +++ b/tests/test_add_context.py @@ -28,7 +28,7 @@ class TestAddContext(TestCase): self.retries_no = 4 self.retry_timeout = 2 self.add_context = True - logging_configuration = { + self.logging_configuration = { "version": 1, "formatters": { "logzio": { @@ -59,14 +59,14 @@ class TestAddContext(TestCase): } } - logging.config.dictConfig(logging_configuration) + logging.config.dictConfig(self.logging_configuration) self.logger = logging.getLogger('test') for curr_file in _find("logzio-failures-*.txt", "."): os.remove(curr_file) def test_add_context(self): - + # Logging configuration of add_context default to True log_message = "this log should have a trace context" self.logger.info(log_message) time.sleep(self.logs_drain_timeout * 2) @@ -80,3 +80,22 @@ class TestAddContext(TestCase): self.assertTrue('otelServiceName' in log_dict) except AssertionError as err: print(err) + + def test_ignore_context(self): + # Set add_context to False and reconfigure the logger as it defaults to True + self.logging_configuration["handlers"]["LogzioHandler"]["add_context"] = False + logging.config.dictConfig(self.logging_configuration) + self.logger = logging.getLogger('test') + log_message = "this log should not 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) + try: + self.assertFalse('otelSpanID' in log_dict) + self.assertFalse('otelTraceID' in log_dict) + self.assertFalse('otelServiceName' in log_dict) + except AssertionError as err: + print(err) diff --git a/tests/test_extra_fields.py b/tests/test_extra_fields.py index 4a332a7..33e9c5b 100644 --- a/tests/test_extra_fields.py +++ b/tests/test_extra_fields.py @@ -77,7 +77,55 @@ class TestExtraFieldsFilter(TestCase): if log_message in current_log: log_dict = json.loads(current_log) try: - self.assertEqual(extra_fields, {**extra_fields,**log_dict}) + self.assertEqual(extra_fields, {**extra_fields, **log_dict}) + except AssertionError as err: + print(err) + + def test_remove_extra_fields(self): + extra_fields = {"foo": "bar"} + + self.logger.addFilter(ExtraFieldsLogFilter(extra=extra_fields)) + log_message = "this log should have a additional fields" + self.logger.info(log_message) + + self.logger.removeFilter(ExtraFieldsLogFilter(extra=extra_fields)) + unfiltered_log_message = "this log shouldn't have a additional fields" + self.logger.info(unfiltered_log_message) + + time.sleep(self.logs_drain_timeout * 2) + logs_list = self.logzio_listener.logs_list + for current_log in logs_list: + if unfiltered_log_message in current_log: + log_dict = json.loads(current_log) + try: + self.assertNotEqual(extra_fields, {**extra_fields, **log_dict}) + except AssertionError as err: + print(err) + + def test_add_multiple_extra_fields(self): + extra_fields = {"foo": "bar"} + self.logger.addFilter(ExtraFieldsLogFilter(extra=extra_fields)) + log_message = "this log should have additional fields" + self.logger.info(log_message) + + extra_fields = {"counter":1} + self.logger.addFilter(ExtraFieldsLogFilter(extra=extra_fields)) + filtered_log_message = "this log should have multiple additional fields" + self.logger.info(filtered_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) + try: + self.assertEqual(extra_fields, {**extra_fields, **log_dict}) + except AssertionError as err: + print(err) + elif filtered_log_message in current_log: + log_dict = json.loads(current_log) + try: + self.assertEqual(extra_fields, {**extra_fields, **log_dict}) except AssertionError as err: print(err) From 4682555feb80fb5411fb3a7e47ec71166ecf47fd Mon Sep 17 00:00:00 2001 From: ralongit Date: Thu, 6 Jul 2023 09:51:43 +0300 Subject: [PATCH 12/13] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9ce9e6f..9b4e9a3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ requests>=2.27.0 protobuf>=3.20.2 -setuptools>=68.0.0 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file +setuptools>=68.0.0 # not directly required, pinned to avoid a vulnerability \ No newline at end of file From 8901c5eb674240658f488bd6f6c7d51272d17a63 Mon Sep 17 00:00:00 2001 From: Ral G <39119258+ralongit@users.noreply.github.com> Date: Thu, 6 Jul 2023 09:51:54 +0300 Subject: [PATCH 13/13] Update requirements.txt Co-authored-by: Miri Bar <37478344+mirii1994@users.noreply.github.com> --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 9ce9e6f..9b4e9a3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ requests>=2.27.0 protobuf>=3.20.2 -setuptools>=68.0.0 # not directly required, pinned by Snyk to avoid a vulnerability \ No newline at end of file +setuptools>=68.0.0 # not directly required, pinned to avoid a vulnerability \ No newline at end of file