Logging
Learn about logging with Python.
The logging integration adds support for the logging framework from Python's standard library. Depending on your settings, logs can be captured as Sentry logs, as error events, or as breadcrumbs, or a combination of those.
Sentry Logs
Enable the Sentry Logs feature with sentry_sdk.init(enable_logs=True) to unlock Sentry's full logging power. With Sentry Logs, you can search, filter, and analyze logs from across your entire application in one place.
Install sentry-sdk from PyPI:
pip install "sentry-sdk"
To capture log records as Sentry logs, set enable_logs to True. The logging integration is a default integration, so it will be enabled automatically when you initialize the Sentry SDK.
import sentry_sdk
sentry_sdk.init(
dsn="___PUBLIC_DSN___",
# Add data like request headers and IP for users, if applicable;
# see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
send_default_pii=True,
enable_logs=True,
)
import logging
def main():
sentry_sdk.init(...) # same as above
logging.info("Logging some info")
logging.error("Logging an error")
main()
This will capture both logs and send them to Sentry Logs. Additionally, an error event will be created from the ERROR-level log. In addition to that, a breadcrumb will be created from the INFO-level log.
As long as enable_logs is True, logs with a level of INFO and higher will be captured as Sentry logs if the log level set in the logging module is INFO or below. The threshold can be configured via the sentry_logs_level option.
Additionally, the logging integration will create an error event from all ERROR-level logs. This feature is configurable via the event_level integration option.
INFO and above logs will also be captured as breadcrumbs. Use the level integration option to adjust the threshold.
import logging
import sentry_sdk
sentry_sdk.init(
...,
enable_logs=True,
)
# The following will be captured as Sentry logs:
logging.info("I'm an INFO log")
logging.error("I'm an ERROR log", extra={"bar": 43})
logging.exception("I'm an exception log")
# DEBUG-level logs won't be captured by default
logging.debug("I'm a DEBUG log")
- All of the above logs except for the
DEBUGlevel message will be sent to Sentry as logs. - An error event with the message
"I'm an ERROR log"will be created. "I'm an INFO log"will be attached as a breadcrumb to that event.barwill end up in theextraattributes of that event."I'm an exception log"will send the current exception fromsys.exc_info()with the stack trace to Sentry. If there's no exception, the current stack will be attached.- The debug message
"I'm a DEBUG log"will not be captured by Sentry. See thesentry_logs_leveloption to adjust which levels should be sent to Sentry as logs, and theleveloption to do adjust the level for capturing breadcrumbs.
When sending log records as Sentry logs, any fields provided in the extra dictionary are automatically promoted to top-level attributes on the log entry. This makes them searchable and filterable in the Sentry UI.
import logging
import sentry_sdk
sentry_sdk.init(
# ...
enable_logs=True,
)
logger = logging.getLogger(__name__)
# Extra fields become top-level searchable attributes
logger.error(
"Payment processing failed",
extra={
"user_id": 12345,
"transaction_id": "txn_abc123",
"payment_method": "credit_card",
"amount": 99.99
}
)
In this example, user_id, transaction_id, payment_method, and amount will appear as separate, searchable attributes in the Sentry logs interface, not nested within an extra object. You can filter and query logs using these attributes directly, such as user_id:12345 or payment_method:credit_card.
To change the default behavior of the logging integration, instantiate the integration manually and pass it to Sentry's init function:
import logging
import sentry_sdk
from sentry_sdk.integrations.logging import LoggingIntegration
# The SDK will honor the level set by the logging library, which is WARNING by default.
# If we want to capture records with lower severity, we need to configure
# the logger level first.
logging.basicConfig(level=logging.INFO)
sentry_sdk.init(
# ...
integrations=[
LoggingIntegration(
sentry_logs_level=logging.INFO, # Capture INFO and above as logs
level=logging.INFO, # Capture INFO and above as breadcrumbs
event_level=logging.ERROR, # Send ERROR records as events
),
],
)
You can pass the following keyword arguments to LoggingIntegration():
sentry_logs_level(defaultINFO): The Sentry Python SDK will capture records with a level higher than or equal tosentry_logs_levelas Sentry structured logs as long as theenable_logsoption isTrue.Copiedsentry_sdk.init( # ... enable_logs=True, )level(defaultINFO): The Sentry Python SDK will record log records with a level higher than or equal tolevelas breadcrumbs. Inversely, the SDK completely ignores any log record with a level lower than this one. If a value ofNoneoccurs, the SDK won't send log records as breadcrumbs.event_level(defaultERROR): The Sentry Python SDK will report log records with a level higher than or equal toevent_levelas events as long as the logger itself is set to output records of those log levels (see note below). If a value ofNoneoccurs, the SDK won't send log records as events.
Sometimes a logger is extremely noisy and spams you with pointless errors. You can ignore that logger by calling ignore_logger:
from sentry_sdk.integrations.logging import ignore_logger
ignore_logger("a.spammy.logger")
logger = logging.getLogger("a.spammy.logger")
logger.error("hi") # no error sent to sentry
You can also use before-send and before-breadcrumb to ignore only certain messages. See Filtering Events for more information.
Instead of using LoggingIntegration, you can use two regular logging logging.Handler subclasses that the integration exports.
Usually, you don't need this. You can use this together with default_integrations=False if you want to opt into what the Sentry Python SDK captures. However, correctly setting up logging is difficult. Also, an opt-in approach to capture data will miss errors you may not think of on your own.
See the API documentation for more information.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").