Add additional details to a Sentry error using Python SDK

There are many situations where I know an error will occur and want to pass additional data to Sentry. I still want the exception to get raised (so the rest of my code stops) and I only want one error in sentry.

For example, let's say I'm making an HTTP call and, in the event that the HTTP call fails, I want an error including the response text sent to Sentry:

import requests

resp = requests.post(url, json=payload)
if resp.ok:
    return resp.json()
try:
    text = resp.json()
except json.JSONDecodeError:
    text = resp.text
# TODO: add `text` to Sentry error
resp.raise_for_status()

How do I do this using the Sentry Python SDK?

Rejected solutions:

  • Sentry's logging: this results in two errors in sentry (one for the log statement and one for the raised exception)
  • capture_expection: this results in two errors in sentry (one for the captured exception and one for the raised exception)
  • Adding extra details to the exception message: this breaks Sentry's error grouping because each error has a unique name

Solution 1:

Large or Unpredictable Data: set_context

If you need to send a lot of data or you don't know the contents of your data, the function you are looking for is Sentry's set_context. You want to call this function right before your exception gets raised. Note that context objects are limited in size to 8kb.

Note: you should only call set_context in a situation where an exception will definitely get raised, or else the extra information you set may get added to other (irrelevant) errors in Sentry.

For example:

import requests
import sentry_sdk

resp = requests.post(url, json=payload)
if resp.ok:
    return resp.json()
try:
    text = resp.json()
except json.JSONDecodeError:
    text = resp.text
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
sentry_sdk.set_context("Payload", {"text": text})
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
resp.raise_for_status()

This attaches it as additional data to your Sentry error, listed just after the breadcrumbs:

Sentry Screenshot

Small, Predictable Data: set_tag

If your data is small and predictable (such as the HTTP status code), you can use sentry's set_tag. It's best to do this within a push_scope block so that the tag is just set for the area of your code that may go wrong. Note that tags keys are limited to 32 characters and tag values are limited in size to 200 characters.

Tags show up at the top of the view of a sentry error.

For example:

import requests
from sentry_sdk import push_scope

resp = requests.post(url, json=payload)
if resp.ok:
    return resp.json()
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
with push_scope() as scope:
    sentry_sdk.set_tag("status", resp.status_code)
    resp.raise_for_status()
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^