Log x-sume-request-id on every Sume call in Python

Capture the x-sume-request-id response header in a requests hook, attach it to each log line with logging.Filter and contextvars, and quote it to support.

5 min readSume
All posts

To make every Sume call traceable, read the x-sume-request-id response header once in a requests response hook and put it on each log line through a logging.Filter that reads a contextvars variable. Sume's errors docs say every response carries the header, and the error body repeats it as request_id, to quote to support.

The Python logging cookbook describes using a filter to add contextual information to records (read 2026-10-04), which is the right seam: your call sites stay clean and every line, including ones from libraries, gets the id.

What does the wiring look like?

The hook runs for every response on the session, including errors, so the failing call is the one you can find later.

import contextvars, logging, os, requests

request_id = contextvars.ContextVar("sume_request_id", default="-")

class SumeId(logging.Filter):
    def filter(self, record):
        record.sume_request_id = request_id.get()
        return True

handler = logging.StreamHandler()
handler.addFilter(SumeId())
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s [%(sume_request_id)s] %(message)s"))
log = logging.getLogger("sume")
log.addHandler(handler)
log.setLevel(logging.INFO)

def remember(resp, *args, **kwargs):
    request_id.set(resp.headers.get("x-sume-request-id", "-"))
    log.info("%s %s -> %s", resp.request.method, resp.request.path_url, resp.status_code)

session = requests.Session()
session.hooks["response"].append(remember)
session.headers["x-api-key"] = os.environ["SUME_API_KEY"]

if __name__ == "__main__":
    session.get("https://api.sume.com/v1/jobs/job_123/status", timeout=30)

Which fields are safe to log?

What to log from a Sume response, from Sume docs read 2026-10-04
FieldWhereLog it?
x-sume-request-idResponse headerYes, on every call
error.code and error.retryableError bodyYes
retry-after and ratelimit-remainingResponse headersYes, as numbers
job id or run idSubmit responseYes, in your own job logs
x-api-keyRequest headerNever
Webhook signing secretYour configNever

Why a contextvar and not a global?

A plain global would be overwritten by whichever thread or task answered last. A ContextVar is isolated per thread and per asyncio task, so concurrent polls log their own ids. If you use httpx rather than requests, the same idea works with an event hook.

What do you do with the id?

  • Include it when you contact support, together with the time and the route.
  • Store it next to the job id when a submit fails, so a retry can be correlated.
  • Keep it out of metric labels; it is unique per call and would create a series for each.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume