Skip to content

Commit 6274702

Browse files
Add global context for logger
1 parent acfa5c6 commit 6274702

4 files changed

Lines changed: 29 additions & 14 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ name: CI
22

33
on:
44
push:
5-
branches: [main]
6-
tags: [v*.*.*]
5+
branches: [ main ]
6+
tags: [ v*.*.* ]
77

88
pull_request:
9-
branches: [ "main" ]
9+
branches: [ main ]
1010
types:
1111
- synchronize
1212
- opened

context_logger/filter.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
import socket
66
from importlib.metadata import version, PackageNotFoundError
77
from logging import Filter, LogRecord
8+
from typing import Any
89

910

1011
class ContextSetupFilter(Filter):
1112

12-
def __init__(self, application_name: str, message_field: str):
13+
def __init__(self, application_name: str, message_field: str, global_context: dict[str, Any] | None = None):
1314
super().__init__()
1415
self._application_name = application_name
1516
self._message_field = message_field
17+
self._global_context = global_context if global_context else {}
1618

1719
def filter(self, record: LogRecord) -> bool:
1820
try:
@@ -26,6 +28,11 @@ def filter(self, record: LogRecord) -> bool:
2628

2729
if 'process_name' in record.msg:
2830
record.msg['process_name'] = record.processName
31+
32+
for key, value in self._global_context.items():
33+
if key not in record.msg:
34+
record.msg[key] = str(value)
35+
2936
except Exception as exception:
3037
print('Failed to handle log record:', exception)
3138

context_logger/logger.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def get_logger(logger_name: str) -> Any:
2727

2828
def setup_logging(application_name: str, log_level: str = 'INFO',
2929
log_file_path: Optional[str] = None, max_bytes: int = 1024 * 1024, backup_count: int = 5,
30-
add_call_info: bool = False, warn_on_overwrite: bool = True, message_field: str = 'message') -> None:
30+
add_call_info: bool = False, warn_on_overwrite: bool = True, message_field: str = 'message',
31+
global_context: dict[str, Any] | None = None) -> None:
3132
global LOGGER
3233

3334
if LOGGER:
@@ -36,22 +37,25 @@ def setup_logging(application_name: str, log_level: str = 'INFO',
3637

3738
LOGGER.cleanup()
3839

39-
LOGGER = Logger(application_name, log_level, log_file_path, max_bytes, backup_count, add_call_info, message_field)
40+
LOGGER = Logger(application_name, log_level, log_file_path, max_bytes, backup_count, add_call_info, message_field,
41+
global_context)
4042

4143
LOGGER.setup()
4244

4345

4446
class Logger(object):
4547

4648
def __init__(self, application_name: str, log_level: str, log_file_path: Optional[str], max_bytes: int,
47-
backup_count: int, add_call_info: bool, message_field: str) -> None:
49+
backup_count: int, add_call_info: bool, message_field: str,
50+
global_context: dict[str, Any] | None = None) -> None:
4851
self._application_name = application_name
4952
self._log_level = logging.getLevelName(log_level.upper())
5053
self._log_file_path = log_file_path
5154
self._max_bytes = max_bytes
5255
self._backup_count = backup_count
53-
self._message_field = message_field
5456
self._add_call_info = add_call_info
57+
self._message_field = message_field
58+
self._global_context = global_context
5559
self._handlers: list[Handler] = []
5660

5761
def setup(self) -> None:
@@ -131,7 +135,7 @@ def _create_console_handler(self) -> Handler:
131135

132136
handler = logging.StreamHandler(sys.stdout)
133137
handler.setFormatter(formatter)
134-
handler.addFilter(ContextSetupFilter(self._application_name, self._message_field))
138+
handler.addFilter(ContextSetupFilter(self._application_name, self._message_field, self._global_context))
135139

136140
return handler
137141

@@ -146,7 +150,7 @@ def _create_file_handler(self, log_file_path: str) -> RotatingFileHandler:
146150

147151
handler = RotatingFileHandler(log_file_path, maxBytes=self._max_bytes, backupCount=self._backup_count)
148152
handler.setFormatter(formatter)
149-
handler.addFilter(ContextSetupFilter(self._application_name, self._message_field))
153+
handler.addFilter(ContextSetupFilter(self._application_name, self._message_field, self._global_context))
150154

151155
return handler
152156

tests/loggerTest.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def setUp(self):
1919

2020
def test_structlog_logging(self):
2121
# Given
22-
setup_logging('example-app', warn_on_overwrite=False)
22+
setup_logging('example-app', warn_on_overwrite=False, global_context={'global1': 'value1'})
2323

2424
log = get_logger('ExampleClass')
2525

@@ -36,7 +36,7 @@ def test_structlog_logging(self):
3636

3737
def test_stdlib_logging(self):
3838
# Given
39-
setup_logging('example-app', warn_on_overwrite=False)
39+
setup_logging('example-app', warn_on_overwrite=False, global_context={'global1': 'value1'})
4040

4141
stdlib_log = logging.getLogger('ExampleClass')
4242

@@ -54,7 +54,8 @@ def test_file_logging(self):
5454
# Given
5555
log_file_path = f'{TESTS_DIR_PATH}/logs/example.log'
5656
shutil.rmtree(os.path.dirname(log_file_path), ignore_errors=True)
57-
setup_logging('example-app', 'INFO', log_file_path, add_call_info=True, warn_on_overwrite=False)
57+
setup_logging('example-app', 'INFO', log_file_path, add_call_info=True, warn_on_overwrite=False,
58+
global_context={'global1': 'value1'})
5859

5960
log = get_logger('ExampleClass')
6061
stdlib_log = logging.getLogger('ExampleClass')
@@ -82,6 +83,7 @@ def test_file_logging(self):
8283
self.assertEqual('This is an error message', log_entry.get('message'))
8384
self.assertEqual('Something terrible happened', log_entry.get('error_message'))
8485
self.assertEqual(1234, log_entry.get('error_code'))
86+
self.assertEqual('value1', log_entry.get('global1'))
8587
self.assertIsNotNone(log_entry.get('pathname'))
8688
self.assertIsNotNone(log_entry.get('func_name'))
8789
self.assertIsNotNone(log_entry.get('lineno'))
@@ -99,7 +101,8 @@ def test_overwriting_setup(self):
99101
stdlib_log = logging.getLogger('ExampleClass')
100102

101103
# When
102-
setup_logging('example-app', 'ERROR', log_file_path, add_call_info=False, message_field='msg')
104+
setup_logging('example-app', 'ERROR', log_file_path, add_call_info=False, message_field='msg',
105+
global_context={'global1': 'value1'})
103106

104107
log.info('This is a simple message')
105108
stdlib_log.error('This is an error message')
@@ -115,6 +118,7 @@ def test_overwriting_setup(self):
115118
self.assertEqual('This is an error message', log_entry.get('msg'))
116119
self.assertEqual('Something terrible happened', log_entry.get('error_message'))
117120
self.assertEqual(1234, log_entry.get('error_code'))
121+
self.assertEqual('value1', log_entry.get('global1'))
118122
self.assertIsNone(log_entry.get('pathname'))
119123
self.assertIsNone(log_entry.get('func_name'))
120124
self.assertIsNone(log_entry.get('lineno'))

0 commit comments

Comments
 (0)