getsentry / sentry-python

The official Python SDK for Sentry.io
https://sentry.io/for/python/
MIT License
1.89k stars 498 forks source link

Save stack traces from logging stack_info=True #1204

Open pdewacht opened 3 years ago

pdewacht commented 3 years ago

Python's logging module has an option to attach a stack trace to a logging message:

logger.error("...", stack_info=True)

This stack trace is lost when logging to Sentry. It'd be very helpful to have it available.

antonpirker commented 2 years ago

Hello @pdewacht ! Thanks for bringing this up. It makes sense, we will look into this.

skrap commented 2 years ago

This stack trace is lost when logging to Sentry. It'd be very helpful to have it available.

Apologies if this is too much "me too" but I wanted to raise a specific use case here to make sure it's considered. Right now I get error strings via a callback. I log those error strings to get them into sentry. Many of them fingerprint differently, because they have specific details in them which cause the logged message to change. E.g. "Frobnicator 0x3124 coolant leak on valve 15" is not grouped with "Frobnicator 0x4671 coolant leak on valve 2".

I was hoping to be able to send stacks with the logged messages, so that similar stacks would be grouped together. Right now each item comes as its own separate sentry issue.

anentropic commented 2 years ago

I was expecting logger.exception (and any logging with exc_info=True) to show up with a formatted traceback, like when calling the SDK's capture_exception function. But it doesn't seem to happen, instead I just get an "error" breadcrumb with the plain text of the traceback, which is truncated unfortunately.

I found this answer https://stackoverflow.com/a/46841264/202168 suggesting that maybe stack_info=True is also required in the logging calls, and now this issue where it seems like that currently doesn't work either.

Just wanted to see what is the intended behaviour - should logging.exception calls show up as a properly formatted traceback in Sentry, with the default logging integration, or it's not meant to be used that way?

souredoutlook commented 2 years ago

Hi @antonpirker I wanted to add some feedback from a recent ticket in Zendesk (#66078) about Sentry's default interaction with logging.exception() compared to a service like logz.io:

Our code is doing logging.exception(msg) in python. Logz.io is smart enough to use that to log the stack trace for the exception but somehow sentry is missing that.

To get the stacktrace with the Sentry SDK you need to utilize the attach_stacktrace option however this would attach stacktraces to all logging.* calls. This seems to be because Sentry SDK appears to treat calls to logging.exception(msg) the same as sentry.capture_message(msg).

One brainstormed solution would be to only include a stacktrace if it's included in the logging as suggested above. Another would be to make attach_stacktrace configurable by event level (i.e. debug, info, warn, error) with a backwards compatible default.

em-ids commented 2 years ago

Is there any update on plans to address this? Not including a stack trace with logging.exception seems like a pretty major issue for python users. I like sentry a lot but if sentry is not going to work correctly when logging.exception it kind of makes me wonder whether I understand what the tool is for.

Thanks.

antonpirker commented 2 years ago

Hello!

Yes, having the stack trace included when using logging.exception and also logging.error(stack_info=True) makes totally sense!

We have a lot on our plate right now, so we will not be able to implement this sooner then later.

But we are always happy to accept PRs if someone wants to help implementing this!

PeterJCLaw commented 2 years ago

Just found this issue having recently wanted this feature. Currently I'm mimicking this with some logic in my before_send which looks a bit like:

        # Based on logic from `sentry_sdk/client.py`'s `_Client._prepare_event`
        with sentry_sdk.utils.capture_internal_exceptions():
            __traceback_hide__ = True  # noqa: F841  # Tell Sentry not to include this frame
            event['threads'] = {
                'values': [
                    {
                        'stacktrace': sentry_sdk.utils.current_stacktrace(with_locals=False),
                        'crashed': False,
                        'current': True,
                    },
                ],
            }

Something I found odd was that using with_locals=True (the default) the trace seemed to be built ok (no exceptions thrown here), however the events never made it to Sentry. It's possible I was doing something wrong (and I am on a relatively old SDK version -- sentry-sdk==1.3.0), though this might be worth watching out for when implementing this.

xmo-odoo commented 1 year ago

Just wanted to see what is the intended behaviour - should logging.exception calls show up as a properly formatted traceback in Sentry, with the default logging integration, or it's not meant to be used that way?

Maybe it's been fixed since but according to Sentry's docs it should

"An exception happened" will send the current exception from sys.exc_info() with the stack trace and everything to the Sentry Python SDK. If there's no exception, the current stack will be attached.

Although that's definitely a non-standard behaviour, the logging docs hint that exception is just an alias for error(exc_info=True) (which the code confirms) and furthermore state that:

This method should only be called from an exception handler.

masimo12358 commented 11 months ago

Is it possible to add stack trace to a message, when using sentry_sdk.capture_message(... ?

sentrivana commented 11 months ago

Hey @masimo12358, not on a per message basis (unless you add it yourself in before_send), but if you don't mind stack traces being attached globally for all messages, you can initialize the SDK with attach_stacktrace=True.