From aaa03d4a51fb78d9b0029784d9792c2e36337082 Mon Sep 17 00:00:00 2001 From: Paulo Vital Date: Thu, 10 Oct 2024 14:55:05 +0200 Subject: [PATCH] fix: _log() Multiple Values for 'stacklevel'. The error `_log() got multiple values for keyword argument 'stacklevel'` may occur when you pass both a positional argument and a keyword argument with the same name (`stacklevel`) to the `Logger._log()` function. This fix checks if the `stacklevel` is a key of the `kwargs` dictionary before calling the `Logger._log()` function, considering it if present. Signed-off-by: Paulo Vital --- src/instana/instrumentation/logging.py | 14 ++++++++++---- tests/clients/test_logging.py | 10 ++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/instana/instrumentation/logging.py b/src/instana/instrumentation/logging.py index 77d110516..f8fc43542 100644 --- a/src/instana/instrumentation/logging.py +++ b/src/instana/instrumentation/logging.py @@ -16,17 +16,23 @@ def log_with_instana(wrapped, instance, argv, kwargs): # argv[0] = level # argv[1] = message # argv[2] = args for message - if sys.version_info >= (3, 13): - stacklevel = 3 + + # We take into consideration if `stacklevel` is already present in `kwargs`. + # This prevents the error `_log() got multiple values for keyword argument 'stacklevel'` + if "stacklevel" in kwargs.keys(): + stacklevel = kwargs.pop("stacklevel") else: stacklevel = 2 + if sys.version_info >= (3, 13): + stacklevel = 3 + try: - tracer, parent_span, _ = get_tracer_tuple() - # Only needed if we're tracing and serious log if tracing_is_off() or argv[0] < logging.WARN: return wrapped(*argv, **kwargs, stacklevel=stacklevel) + tracer, parent_span, _ = get_tracer_tuple() + msg = str(argv[1]) args = argv[2] if args and len(args) == 1 and isinstance(args[0], Mapping) and args[0]: diff --git a/tests/clients/test_logging.py b/tests/clients/test_logging.py index 923b3f388..71436f8f8 100644 --- a/tests/clients/test_logging.py +++ b/tests/clients/test_logging.py @@ -96,3 +96,13 @@ def log_custom_warning(): self.assertEqual(self.caplog.records[0].funcName, "log_custom_warning") self.logger.removeHandler(handler) + + def test_stacklevel_as_kwarg(self): + with tracer.start_active_span("test"): + self.logger.warning("foo %s", "bar", stacklevel=2) + + spans = self.recorder.queued_spans() + self.assertEqual(2, len(spans)) + self.assertEqual(2, spans[0].k) + + self.assertEqual("foo bar", spans[0].data["log"].get("message"))