Skip to content

Commit aa0d5b0

Browse files
committed
feat: Add opt-in root exit spans to logging
Signed-off-by: Ferenc Géczi <[email protected]>
1 parent c222d96 commit aa0d5b0

File tree

2 files changed

+46
-29
lines changed

2 files changed

+46
-29
lines changed

src/instana/instrumentation/logging.py

+27-26
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from collections.abc import Mapping
99

1010
from ..log import logger
11-
from ..util.traceutils import get_active_tracer
11+
from ..util.traceutils import get_tracer_tuple, tracing_is_off
1212

1313

1414
@wrapt.patch_function_wrapper('logging', 'Logger._log')
@@ -17,33 +17,34 @@ def log_with_instana(wrapped, instance, argv, kwargs):
1717
# argv[1] = message
1818
# argv[2] = args for message
1919
try:
20-
active_tracer = get_active_tracer()
20+
tracer, parent_span, _ = get_tracer_tuple()
2121

2222
# Only needed if we're tracing and serious log
23-
if active_tracer and argv[0] >= logging.WARN:
24-
25-
msg = str(argv[1])
26-
args = argv[2]
27-
if args and len(args) == 1 and isinstance(args[0], Mapping) and args[0]:
28-
args = args[0]
29-
30-
# get the formatted log message
31-
msg = msg % args
32-
33-
# get additional information if an exception is being handled
34-
parameters = None
35-
(t, v, tb) = sys.exc_info()
36-
if t is not None and v is not None:
37-
parameters = '{} {}'.format(t , v)
38-
39-
# create logging span
40-
with active_tracer.start_active_span('log', child_of=active_tracer.active_span) as scope:
41-
scope.span.log_kv({ 'message': msg })
42-
if parameters is not None:
43-
scope.span.log_kv({ 'parameters': parameters })
44-
# extra tags for an error
45-
if argv[0] >= logging.ERROR:
46-
scope.span.mark_as_errored()
23+
if tracing_is_off() or argv[0] < logging.WARN:
24+
return wrapped(*argv, **kwargs)
25+
26+
msg = str(argv[1])
27+
args = argv[2]
28+
if args and len(args) == 1 and isinstance(args[0], Mapping) and args[0]:
29+
args = args[0]
30+
31+
# get the formatted log message
32+
msg = msg % args
33+
34+
# get additional information if an exception is being handled
35+
parameters = None
36+
(t, v, tb) = sys.exc_info()
37+
if t is not None and v is not None:
38+
parameters = '{} {}'.format(t , v)
39+
40+
# create logging span
41+
with tracer.start_active_span('log', child_of=parent_span) as scope:
42+
scope.span.log_kv({ 'message': msg })
43+
if parameters is not None:
44+
scope.span.log_kv({ 'parameters': parameters })
45+
# extra tags for an error
46+
if argv[0] >= logging.ERROR:
47+
scope.span.mark_as_errored()
4748
except Exception:
4849
logger.debug('log_with_instana:', exc_info=True)
4950

tests/clients/test_logging.py

+19-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import logging
55
import unittest
6-
from instana.singletons import tracer
6+
from instana.singletons import agent, tracer
77

88

99
class TestLogging(unittest.TestCase):
@@ -14,8 +14,8 @@ def setUp(self):
1414
self.logger = logging.getLogger('unit test')
1515

1616
def tearDown(self):
17-
""" Do nothing for now """
18-
return None
17+
""" Ensure that allow_exit_as_root has the default value """
18+
agent.options.allow_exit_as_root = False
1919

2020
def test_no_span(self):
2121
with tracer.start_active_span('test'):
@@ -58,3 +58,19 @@ def test_parameters(self):
5858

5959
self.assertIsNotNone(spans[0].data["log"].get('parameters'))
6060

61+
def test_no_root_exit_span(self):
62+
agent.options.allow_exit_as_root = True
63+
self.logger.info('info message')
64+
65+
spans = self.recorder.queued_spans()
66+
self.assertEqual(0, len(spans))
67+
68+
def test_root_exit_span(self):
69+
agent.options.allow_exit_as_root = True
70+
self.logger.warning('foo %s', 'bar')
71+
72+
spans = self.recorder.queued_spans()
73+
self.assertEqual(1, len(spans))
74+
self.assertEqual(2, spans[0].k)
75+
76+
self.assertEqual('foo bar', spans[0].data["log"].get('message'))

0 commit comments

Comments
 (0)