jaegertracing / jaeger-client-python

🛑 This library is DEPRECATED!
https://jaegertracing.io/
Apache License 2.0
408 stars 155 forks source link

Suggestion for improvement - python logging integration #279

Closed lukeplausin closed 2 years ago

lukeplausin commented 4 years ago

Requirement - what kind of business use case are you trying to solve?

I've recently done some work instrumenting an application to use this library for tracing. Whilst I was doing this I developed a couple of custom features which I think could be helpful for others, so I would like to contribute back to the project.

Problem - what in Jaeger blocks you from solving the requirement?

In my use case it is important to capture logging output with the spans in order to make sense of what the application is doing. Since the project already uses the python logger extensively, and I didn't want to refactor all of the logging statements.

I like the with tracer.start_span mnemonic for opening spans, however once you have the span open, if you want to add a log statement inside the span you must explicitly call span.log_kv inside the span.

logger = logging.getLogger(__name__)
with tracer.start_span('TestSpan') as span:
    span.log_kv({'event': 'test message', 'life': 42})
    logger.debug('test message')

Proposal - what do you suggest to solve the problem or improve the existing situation?

Since my project already uses the python logging module, I decided to write a similar mnemonic to automatically capture output from python logging objects whilst within the span.

My log handling class uses the with mnemonic to add a custom log handler to the logger object whilst inside the scope of the current span. I've tested it with my application and it seems to work nicely.

logger = logging.getLogger(__name__)
with tracer.start_span('TestSpan') as span:
    with MyLogHandler(span=span, logger=logger) as lh:
        logger.debug('test message')

I think it would be really nice if it was possible to provide this functionality to devs with the jaeger client out of the box. If there was an optional logger argument that could do this whilst creating the span then it would make the process even more streamlined.

logger = logging.getLogger(__name__)
with tracer.start_span('TestSpan', logger=logger) as span:
    logger.debug('test message')
    # log will be automatically sent to the tracing client under the current span

Any open questions to address

I already have the code from MyLogHandler ready to go. Do you think it would be a useful addition? Any comments, suggestions, feedback are welcome.

yurishkuro commented 4 years ago

We cannot make changes to the OpenTracing API, so this approach isn't going to work.

I think there is a much simpler solution. You can add a static handler to the loggers which will access the current span from the thread-local storage using tracer.scope_manager.active_span. This way no changes to the tracing code are required at all.