From 5e5374c3c3e1498fa1ef6d74eb7bf2d58d31430e Mon Sep 17 00:00:00 2001 From: Viraj Kanwade Date: Sat, 12 Jul 2025 13:45:44 -0700 Subject: [PATCH 1/6] Handle datetime.utcnow deprecation --- json_logging/util.py | 4 ++-- tests-performance/benmark_micro.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/json_logging/util.py b/json_logging/util.py index c69d98a..8ac39d5 100644 --- a/json_logging/util.py +++ b/json_logging/util.py @@ -3,7 +3,7 @@ import os import re import sys -from datetime import datetime +from datetime import datetime, timezone from logging import Logger, StreamHandler import json_logging @@ -71,7 +71,7 @@ def validate_subclass(subclass, superclass): return True -_epoch = datetime(1970, 1, 1) +_epoch = datetime(1970, 1, 1, tzinfo=timezone.utc) def epoch_nano_second(datetime_): diff --git a/tests-performance/benmark_micro.py b/tests-performance/benmark_micro.py index 99ec8a9..4b61020 100644 --- a/tests-performance/benmark_micro.py +++ b/tests-performance/benmark_micro.py @@ -1,9 +1,9 @@ # coding=utf-8 import time import timeit -from datetime import datetime +from datetime import datetime, timezone -utcnow = datetime.utcnow() +utcnow = datetime.now(timezone.utc) numbers = 1000000 # timeit_timeit = timeit.timeit(lambda: '%04d-%02d-%02dT%02d:%02d:%02dZ' % ( From db7b742e5e291881b6084c9526f884cc43197df5 Mon Sep 17 00:00:00 2001 From: Viraj Kanwade Date: Sat, 12 Jul 2025 13:51:58 -0700 Subject: [PATCH 2/6] Support Python 3.9 to 3.12 --- tests/helpers/constants.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/helpers/constants.py b/tests/helpers/constants.py index 9a355ba..33f8422 100644 --- a/tests/helpers/constants.py +++ b/tests/helpers/constants.py @@ -1,6 +1,8 @@ """Constants shared by multiple tests""" -STANDARD_MSG_ATTRIBUTES = { +import sys + +_msg_attrs = [ "written_at", "written_ts", "msg", @@ -11,4 +13,9 @@ "module", "line_no", "correlation_id", -} +] + +if sys.version_info.major == 3 and sys.version_info.minor >= 12: + _msg_attrs.append("taskName") + +STANDARD_MSG_ATTRIBUTES = set(_msg_attrs) From 4fa1d539d660c9b4c857a85be42543cbcb537b6f Mon Sep 17 00:00:00 2001 From: Viraj Kanwade Date: Mon, 9 Sep 2024 15:50:09 -0700 Subject: [PATCH 3/6] upgrade github workflow config code_quality.yml --- .github/workflows/code_quality.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index 93d37ee..0c311a2 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -13,9 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.9 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: Install dependencies @@ -40,11 +40,11 @@ jobs: steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: "Git checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install dependencies run: | python -m pip install --upgrade pip @@ -63,11 +63,11 @@ jobs: steps: - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.9 - name: "Git checkout" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Install dependencies run: | python -m pip install --upgrade pip From 19ce2ada67ce0d83832f093fcd121f1164dc99e0 Mon Sep 17 00:00:00 2001 From: Viraj Kanwade Date: Sat, 12 Jul 2025 14:01:20 -0700 Subject: [PATCH 4/6] pyupgrade python3.9 plus --- example/connexion-example/hello.py | 4 ++-- example/custom_log_format_request.py | 6 +++--- json_logging/__init__.py | 1 - json_logging/dto.py | 6 +++--- json_logging/formatters.py | 15 ++++++--------- json_logging/framework/__init__.py | 1 - json_logging/framework/connexion/__init__.py | 1 - json_logging/framework/fastapi/__init__.py | 1 - json_logging/framework/flask/__init__.py | 1 - json_logging/framework/quart/__init__.py | 1 - json_logging/framework/sanic/__init__.py | 1 - json_logging/framework_base.py | 1 - json_logging/util.py | 3 +-- setup.py | 2 +- tests-performance/benmark_micro.py | 1 - tests/helpers/handler.py | 2 +- 16 files changed, 17 insertions(+), 30 deletions(-) diff --git a/example/connexion-example/hello.py b/example/connexion-example/hello.py index 78837f5..09b9dec 100755 --- a/example/connexion-example/hello.py +++ b/example/connexion-example/hello.py @@ -14,11 +14,11 @@ def post_greeting(name): logger.info("test log statement") logger.info("test log statement with extra props", extra={'props': {"extra_property": 'extra_value'}}) - return 'Hello {name}'.format(name=name) + return f'Hello {name}' def exclude_from_request_instrumentation(name): - return 'Hello {name}. this request wont log request instrumentation information'.format(name=name) + return f'Hello {name}. this request wont log request instrumentation information' def create(): diff --git a/example/custom_log_format_request.py b/example/custom_log_format_request.py index e753267..a766e20 100644 --- a/example/custom_log_format_request.py +++ b/example/custom_log_format_request.py @@ -19,7 +19,7 @@ def _format_log_object(self, record, request_util): request = record.request_response_data._request response = record.request_response_data._response - json_log_object = super(CustomRequestJSONLog, self)._format_log_object(record, request_util) + json_log_object = super()._format_log_object(record, request_util) json_log_object.update({ "customized_prop": "customized value", }) @@ -32,10 +32,10 @@ class CustomDefaultRequestResponseDTO(json_logging.dto.DefaultRequestResponseDTO """ def __init__(self, request, **kwargs): - super(CustomDefaultRequestResponseDTO, self).__init__(request, **kwargs) + super().__init__(request, **kwargs) def on_request_complete(self, response): - super(CustomDefaultRequestResponseDTO, self).on_request_complete(response) + super().on_request_complete(response) self.status = response.status diff --git a/json_logging/__init__.py b/json_logging/__init__.py index e26864a..d2314a4 100644 --- a/json_logging/__init__.py +++ b/json_logging/__init__.py @@ -1,4 +1,3 @@ -# coding=utf-8 import json import logging import sys diff --git a/json_logging/dto.py b/json_logging/dto.py index a68136c..0a48c68 100644 --- a/json_logging/dto.py +++ b/json_logging/dto.py @@ -14,7 +14,7 @@ def __init__(self, request, **kwargs): invoked when request start, where to extract any necessary information from the request object :param request: request object """ - super(RequestResponseDTOBase, self).__init__(**kwargs) + super().__init__(**kwargs) self._request = request def on_request_complete(self, response): @@ -31,14 +31,14 @@ class DefaultRequestResponseDTO(RequestResponseDTOBase): """ def __init__(self, request, **kwargs): - super(DefaultRequestResponseDTO, self).__init__(request, **kwargs) + super().__init__(request, **kwargs) utcnow = datetime.now(timezone.utc) self._request_start = utcnow self["request_received_at"] = util.iso_time_format(utcnow) # noinspection PyAttributeOutsideInit def on_request_complete(self, response): - super(DefaultRequestResponseDTO, self).on_request_complete(response) + super().on_request_complete(response) utcnow = datetime.now(timezone.utc) time_delta = utcnow - self._request_start self["response_time_ms"] = int(time_delta.total_seconds()) * 1000 + int(time_delta.microseconds / 1000) diff --git a/json_logging/formatters.py b/json_logging/formatters.py index 9c3417d..fa5570b 100644 --- a/json_logging/formatters.py +++ b/json_logging/formatters.py @@ -22,11 +22,8 @@ except NameError: basestring = str -if sys.version_info < (3, 0): - EASY_SERIALIZABLE_TYPES = (basestring, bool, dict, float, int, list, type(None)) -else: - LOG_RECORD_BUILT_IN_ATTRS.append('stack_info') - EASY_SERIALIZABLE_TYPES = (str, bool, dict, float, int, list, type(None)) +LOG_RECORD_BUILT_IN_ATTRS.append('stack_info') +EASY_SERIALIZABLE_TYPES = (str, bool, dict, float, int, list, type(None)) def _sanitize_log_msg(record): @@ -45,7 +42,7 @@ class BaseJSONFormatter(logging.Formatter): base_object_common = {} def __init__(self, *args, **kw): - super(BaseJSONFormatter, self).__init__(*args, **kw) + super().__init__(*args, **kw) if json_logging.COMPONENT_ID and json_logging.COMPONENT_ID != json_logging.EMPTY_VALUE: self.base_object_common["component_id"] = json_logging.COMPONENT_ID if json_logging.COMPONENT_NAME and json_logging.COMPONENT_NAME != json_logging.EMPTY_VALUE: @@ -120,7 +117,7 @@ def format_exception(cls, exc_info): return ''.join(traceback.format_exception(*exc_info)) if exc_info else '' def _format_log_object(self, record, request_util): - json_log_object = super(JSONLogFormatter, self)._format_log_object(record, request_util) + json_log_object = super()._format_log_object(record, request_util) json_log_object.update({ "msg": _sanitize_log_msg(record), @@ -144,7 +141,7 @@ class JSONLogWebFormatter(JSONLogFormatter): """ def _format_log_object(self, record, request_util): - json_log_object = super(JSONLogWebFormatter, self)._format_log_object(record, request_util) + json_log_object = super()._format_log_object(record, request_util) if json_logging.CORRELATION_ID_FIELD not in json_log_object: json_log_object.update({ @@ -160,7 +157,7 @@ class JSONRequestLogFormatter(BaseJSONFormatter): """ def _format_log_object(self, record, request_util): - json_log_object = super(JSONRequestLogFormatter, self)._format_log_object(record, request_util) + json_log_object = super()._format_log_object(record, request_util) request_adapter = request_util.request_adapter response_adapter = request_util.response_adapter diff --git a/json_logging/framework/__init__.py b/json_logging/framework/__init__.py index 9bad579..e69de29 100644 --- a/json_logging/framework/__init__.py +++ b/json_logging/framework/__init__.py @@ -1 +0,0 @@ -# coding=utf-8 diff --git a/json_logging/framework/connexion/__init__.py b/json_logging/framework/connexion/__init__.py index 695f2a7..e2fbabf 100644 --- a/json_logging/framework/connexion/__init__.py +++ b/json_logging/framework/connexion/__init__.py @@ -1,4 +1,3 @@ -# coding=utf-8 import logging import sys diff --git a/json_logging/framework/fastapi/__init__.py b/json_logging/framework/fastapi/__init__.py index 79cea21..76042bd 100644 --- a/json_logging/framework/fastapi/__init__.py +++ b/json_logging/framework/fastapi/__init__.py @@ -1,4 +1,3 @@ - def is_fastapi_present(): # noinspection PyPep8,PyBroadException try: diff --git a/json_logging/framework/flask/__init__.py b/json_logging/framework/flask/__init__.py index 03857ea..f9b29a8 100644 --- a/json_logging/framework/flask/__init__.py +++ b/json_logging/framework/flask/__init__.py @@ -1,4 +1,3 @@ -# coding=utf-8 import logging import json_logging diff --git a/json_logging/framework/quart/__init__.py b/json_logging/framework/quart/__init__.py index 4043a70..3b05c8f 100644 --- a/json_logging/framework/quart/__init__.py +++ b/json_logging/framework/quart/__init__.py @@ -1,4 +1,3 @@ -# coding=utf-8 import logging import sys diff --git a/json_logging/framework/sanic/__init__.py b/json_logging/framework/sanic/__init__.py index 9edba8b..4e4bea4 100644 --- a/json_logging/framework/sanic/__init__.py +++ b/json_logging/framework/sanic/__init__.py @@ -1,4 +1,3 @@ -# coding=utf-8 import logging import logging.config diff --git a/json_logging/framework_base.py b/json_logging/framework_base.py index 29bc3fc..df6eadf 100644 --- a/json_logging/framework_base.py +++ b/json_logging/framework_base.py @@ -1,4 +1,3 @@ -# coding=utf-8 class BaseRequestInfoExtractor: """ Helper class help to extract logging-relevant information from HTTP request object diff --git a/json_logging/util.py b/json_logging/util.py index 8ac39d5..d2f7cf0 100644 --- a/json_logging/util.py +++ b/json_logging/util.py @@ -1,4 +1,3 @@ -# coding=utf-8 import logging import os import re @@ -96,7 +95,7 @@ def currentframe(_no_of_go_up_level): return sys.exc_info()[_no_of_go_up_level - 1].tb_frame.f_back -class RequestUtil(object): +class RequestUtil: """ util for extract request's information """ diff --git a/setup.py b/setup.py index 2b732b9..c079c59 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ if version_info_major == 3: long_description = open('README.rst', encoding="utf8").read() else: - io_open = io.open('README.rst', encoding="utf8") + io_open = open('README.rst', encoding="utf8") long_description = io_open.read() setup( diff --git a/tests-performance/benmark_micro.py b/tests-performance/benmark_micro.py index 4b61020..4fb6438 100644 --- a/tests-performance/benmark_micro.py +++ b/tests-performance/benmark_micro.py @@ -1,4 +1,3 @@ -# coding=utf-8 import time import timeit from datetime import datetime, timezone diff --git a/tests/helpers/handler.py b/tests/helpers/handler.py index 6b67d2e..e90acec 100644 --- a/tests/helpers/handler.py +++ b/tests/helpers/handler.py @@ -9,7 +9,7 @@ def __init__(self, level=logging.NOTSET) -> None: """Create a new log handler.""" super().__init__(level=level) self.level = level - self.messages: List[str] = [] + self.messages: list[str] = [] def emit(self, record: logging.LogRecord) -> None: """Keep the log records in a list in addition to the log text.""" From becd3f96b60488248e6b84a3cd78cf04633beb11 Mon Sep 17 00:00:00 2001 From: Viraj Kanwade Date: Sat, 12 Jul 2025 13:36:43 -0700 Subject: [PATCH 5/6] remove references to python 2 --- setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c079c59..d90116d 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ description="JSON Python Logging", long_description=long_description, author="Bob T.", - keywords=["json", "elastic", "python", "python3", "python2", "logging", "logging-library", "json", "elasticsearch", + keywords=["json", "elastic", "python", "python3", "logging", "logging-library", "json", "elasticsearch", "elk", "elk-stack", "logstash", "kibana"], platforms='any', url="https://github.com/thangbn/json-logging", @@ -28,7 +28,6 @@ 'License :: OSI Approved :: Apache Software License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: System :: Logging', 'Framework :: Flask', From 84763e842a7077dbe1d9f085c876399bd90ef20e Mon Sep 17 00:00:00 2001 From: Viraj Kanwade Date: Sun, 20 Jul 2025 07:47:06 -0700 Subject: [PATCH 6/6] Incorporated Gemini code review suggestions --- setup.py | 8 ++------ tests/helpers/constants.py | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index d90116d..cc7b1cd 100644 --- a/setup.py +++ b/setup.py @@ -3,12 +3,8 @@ from setuptools import setup, find_packages -version_info_major = sys.version_info[0] -if version_info_major == 3: - long_description = open('README.rst', encoding="utf8").read() -else: - io_open = open('README.rst', encoding="utf8") - long_description = io_open.read() +with open('README.rst', encoding="utf8") as f: + long_description = f.read() setup( name="json-logging", diff --git a/tests/helpers/constants.py b/tests/helpers/constants.py index 33f8422..335b140 100644 --- a/tests/helpers/constants.py +++ b/tests/helpers/constants.py @@ -15,7 +15,7 @@ "correlation_id", ] -if sys.version_info.major == 3 and sys.version_info.minor >= 12: +if sys.version_info >= (3, 12): _msg_attrs.append("taskName") STANDARD_MSG_ATTRIBUTES = set(_msg_attrs)