Skip to content

Commit 63bb741

Browse files
committed
feat(logger): accept arbitrary keyword=value for ephemeral metadata
1 parent 67532d7 commit 63bb741

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

aws_lambda_powertools/logging/logger.py

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import os
55
import random
66
import sys
7-
from typing import IO, Any, Callable, Dict, Iterable, Optional, TypeVar, Union
7+
from typing import IO, Any, Callable, Dict, Iterable, Mapping, Optional, TypeVar, Union
88

99
import jmespath
1010

@@ -359,6 +359,101 @@ def decorate(event, context, *args, **kwargs):
359359

360360
return decorate
361361

362+
def info(
363+
self,
364+
msg: object,
365+
*args,
366+
exc_info=None,
367+
stack_info: bool = False,
368+
stacklevel: int = 2,
369+
extra: Optional[Mapping[str, object]] = None,
370+
**kwargs,
371+
):
372+
# NOTE: We need to solve stack frame location for Python <3.8
373+
extra = extra or {}
374+
extra = {**extra, **kwargs}
375+
if sys.version_info < (3, 8):
376+
return self._logger.info(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra)
377+
return self._logger.info(
378+
msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra
379+
)
380+
381+
def error(
382+
self,
383+
msg: object,
384+
*args,
385+
exc_info=None,
386+
stack_info: bool = False,
387+
stacklevel: int = 2,
388+
extra: Optional[Mapping[str, object]] = None,
389+
**kwargs,
390+
):
391+
# NOTE: We need to solve stack frame location for Python <3.8
392+
extra = extra or {}
393+
extra = {**extra, **kwargs}
394+
if sys.version_info < (3, 8):
395+
return self._logger.error(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra)
396+
return self._logger.error(
397+
msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra
398+
)
399+
400+
def exception(
401+
self,
402+
msg: object,
403+
*args,
404+
exc_info=None,
405+
stack_info: bool = False,
406+
stacklevel: int = 2,
407+
extra: Optional[Mapping[str, object]] = None,
408+
**kwargs,
409+
):
410+
# NOTE: We need to solve stack frame location for Python <3.8
411+
extra = extra or {}
412+
extra = {**extra, **kwargs}
413+
if sys.version_info < (3, 8):
414+
return self._logger.exception(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra)
415+
return self._logger.exception(
416+
msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra
417+
)
418+
419+
def critical(
420+
self,
421+
msg: object,
422+
*args,
423+
exc_info=None,
424+
stack_info: bool = False,
425+
stacklevel: int = 2,
426+
extra: Optional[Mapping[str, object]] = None,
427+
**kwargs,
428+
):
429+
# NOTE: We need to solve stack frame location for Python <3.8
430+
extra = extra or {}
431+
extra = {**extra, **kwargs}
432+
if sys.version_info < (3, 8):
433+
return self._logger.critical(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra)
434+
return self._logger.critical(
435+
msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra
436+
)
437+
438+
def warning(
439+
self,
440+
msg: object,
441+
*args,
442+
exc_info=None,
443+
stack_info: bool = False,
444+
stacklevel: int = 2,
445+
extra: Optional[Mapping[str, object]] = None,
446+
**kwargs,
447+
):
448+
# NOTE: We need to solve stack frame location for Python <3.8
449+
extra = extra or {}
450+
extra = {**extra, **kwargs}
451+
if sys.version_info < (3, 8):
452+
return self._logger.warning(msg, *args, exc_info=exc_info, stack_info=stack_info, extra=extra)
453+
return self._logger.warning(
454+
msg, *args, exc_info=exc_info, stack_info=stack_info, stacklevel=stacklevel, extra=extra
455+
)
456+
362457
def append_keys(self, **additional_keys):
363458
self.registered_formatter.append_keys(**additional_keys)
364459

tests/functional/test_logger.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,25 @@ def test_logger_extra_kwargs(stdout, service_name):
415415
assert "request_id" not in no_extra_fields_log
416416

417417

418+
def test_logger_kwargs_no_extra(stdout, service_name):
419+
# GIVEN Logger is initialized
420+
logger = Logger(service=service_name, stream=stdout)
421+
422+
# WHEN `request_id` is an extra field in a log message to the existing structured log
423+
fields = {"request_id": "blah"}
424+
425+
logger.info("with extra fields", **fields)
426+
logger.info("without extra fields")
427+
428+
extra_fields_log, no_extra_fields_log = capture_multiple_logging_statements_output(stdout)
429+
430+
# THEN first log should have request_id field in the root structure
431+
assert "request_id" in extra_fields_log
432+
433+
# THEN second log should not have request_id in the root structure
434+
assert "request_id" not in no_extra_fields_log
435+
436+
418437
def test_logger_log_twice_when_log_filter_isnt_present_and_root_logger_is_setup(monkeypatch, stdout, service_name):
419438
# GIVEN Lambda configures the root logger with a handler
420439
root_logger = logging.getLogger()

0 commit comments

Comments
 (0)