azmeuk
azmeuk

Reputation: 4506

How to catch python warnings with sentry?

With sentry_sdk, the sentry documentation explain how to automatically catch exceptions or logging messages. However, how can I catch a python warning, like a DeprecationWarning that would be raised with

warnings.warn(DeprecationWarning, "warning message")

Upvotes: 7

Views: 4402

Answers (4)

Aaron
Aaron

Reputation: 2679

First, We tell python to redirect warnings to the logging system (as mentioned in Ahmed Hany's answer). From: https://docs.python.org/3/library/logging.html#logging.captureWarnings

logging.captureWarnings(capture)

If capture is True, warnings issued by the warnings module will be redirected to the logging system.

Second, Sentry will capture error-level log records by default, but we can adjust this behaviour to also capture warnings. See: https://docs.sentry.io/platforms/python/guides/logging/

Here's a complete example (for django):

settings.py

import logging
import os
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration

# Ensure that warnings are enabled
os.environ["PYTHONWARNINGS"] = "default"

# Ensure that logging captures warnings issued by warnings.warn()
logging.captureWarnings(True)

sentry_sdk.init(
    dsn="...",
    integrations=[
        LoggingIntegration(
            level = logging.INFO,           # Capture info and above as breadcrumbs (this is the default)
            event_level = logging.WARNING,  # Send warnings as events (default is logging.ERROR)
        ),
        DjangoIntegration(),
    ],
    ...
)

Upvotes: 9

Ahmed Hany
Ahmed Hany

Reputation: 1040

There's no certain API in sentry for sending warnings, However, you need to ensure you're logging these with the general logging infrastructure that you are using.

For example, if you are using Django, you have to change the logging level to be Warning like below in the settings.py file

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'verbose': {
            'format': '%(asctime)s %(levelname)s [%(name)s:%(lineno)s] %(module)s %(process)d %(thread)d %(message)s'
        }
    },
    'handlers': {
        'console': {
            'level': 'WARNING',
            'class': 'logging.StreamHandler'
        },
    },
    'loggers': {
        "": {
            "level": "WARNING",
            'handlers': ['console'],
            "propagate": True
        }
    }
}

and no change in sentry config

import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

sentry_config = {
    'dsn': os.getenv("SENTRY_DSN", "YOUR CDN"),
    'integrations': [DjangoIntegration()],
    # Set traces_sample_rate to 1.0 to capture 100%
    # of transactions for performance monitoring.
    # We recommend adjusting this value in production.
    'traces_sample_rate': 1.0,
    # If you wish to associate users to errors (assuming you are using
    # django.contrib.auth) you may enable sending PII data.
    'send_default_pii': True
}
sentry_sdk.init(**sentry_config)

In case you don't have Logging infrastructure, you can implement your own, check this Question, it has a lot of examples of how you would create a custom logger.

It's all about changing your level to be WARNING and creating a console handler(StreamHandler), then Sentry will take care of the rest

Edit: I meant to capture logging.warning(), but for warnings.warn() you have to log them, Python provides a built-in integration between the logging module and the warnings module to let you do this; just call logging.captureWarnings(True) at the start of your script or your custom logger and all warnings emitted by the warnings module will automatically be logged at level WARNING.

Upvotes: 2

Faisal Shahbaz
Faisal Shahbaz

Reputation: 528

In Python you can either capture a caught exception or the one currently held in sys.exc_info() by not passing an argument:

from sentry_sdk import capture_exception

try:
    a_potentially_failing_function()
except Exception as e:
    # Alternatively the argument can be omitted
    capture_exception(e)

Another common operation is to capture a bare message. A message is textual information that should be sent to Sentry. Typically messages are not emitted, but they can be useful for some teams.

from sentry_sdk import capture_message

capture_message('Something went wrong')

Upvotes: 1

systemime
systemime

Reputation: 59

if Exception:

try:
    ...
except Exception as exc:
    sentry_sdk.capture_exception(exc)

if message:

sentry_sdk.capture_message("xxx")

Upvotes: 1

Related Questions