What the logging layer gives you
Logging is a small, dependency-light layer with a handful of distinct jobs. Each has its own section below — start with whichever capability you need.
Every helper on this page imports from the package root:
Zero setup
Logs rotate daily and are kept for 14 days by default. Change this with
configure_logging(backup_count=...).The log file is not anonymized at rest — it keeps full detail so you can debug locally, and it never contains slide images, tile pixels, or omics values, only pipeline metadata (paths, IDs, error codes, tracebacks). Anonymization of that metadata is applied only when you export a support bundle or query
/diagnostics (see Support bundles).Log destinations
Default log format
Every line is a single JSON object:Emit your own log entries
Wrap your own pipeline functions to get the same one-record-per-failure behavior withlog_failures, or emit a one-off structured event with log_event — both write to the log file that’s already active, no configure_logging call required (see Zero setup). In every example below, run_slide is your function and inference is a client you built earlier (for example inference = Inference(...) or model = Backbone(...)) — swap in your own call:
log_failures looks like:
log_event call above writes:
log_event also accepts error_code= — which auto-attaches the matching remediation — and exc_info=exc to record a caught exception’s traceback on the line.
Group related log lines
Bind correlation fields once and every log line emitted inside the block is tagged with them automatically — so all lines for a run, a slide, or a request share atrace_id/slide_id you can filter on. Fields whose value is None are ignored, and the previous context is restored on exit (even on error):
new_trace_id() returns a 26-character, time-sortable ID. bind_context accepts any field name — trace_id, run_id, slide_id, and stage are the ones the SDK’s own pipeline sets and surface in the format table above, but you can bind your own (for example batch_id) the same way.
Read your logs back in Python
Read the log file without parsing JSON yourself. Both readers anonymize by default — passanonymize=False for full local detail:
dict with the fields shown in Default log format. read_recent_logs tails the active file only; read_usage_records spans the active file and all its rotations, so it is the full request history rather than a recent tail.
Customize logging
Callconfigure_logging to override any default — for a custom path, console output, level, or retention:
console=True, matching events also print a compact, human-readable line to stderr instead of the JSON payload above — for example the slide_skipped event from the manual log_event call:
Set the rotation period and retention with
when and backup_count. Rotated files are suffixed with their UTC date (bioptimus.log.2026-06-24), so each maps cleanly to a support window:
file_handler_factory. The SDK still owns the path, the JSON format, and correlation-context injection:
Can I change the log format?
The on-disk format is structured JSON by design — it is the contract the readers, support bundles, and a server’s/diagnostics all parse — so there is no format parameter. For human-readable output, pass console=True (shown above).
To emit SDK logs in your own format to your own destination, attach your own handler. SDK records propagate up Python’s logging hierarchy, so a handler on the bioptimus logger (or the root logger) receives every event:
Redact sensitive fields at rest
By default the log file keeps full detail so you can debug locally, and PII is redacted only when you export — when you build a support bundle or query a server’s/diagnostics. To redact the on-disk file itself, turn on redaction at rest:
- Identifier and path fields (
slide_id,patient_id,wsi_id,slide_path,output_dir, …) are replaced by a stable hash — the same value keeps the same pseudonym, so “which slide failed” still correlates across every line. - Free text — any path,
s3:///file://URI, or slide file name embedded in a message or traceback under a field the policy doesn’t recognize — is redacted outright instead; the user name in a home-directory path is masked.
anonymize reference.
Redaction is stable pseudonymization for support triage, not encryption. Review what a bundle contains before sharing logs outside your environment.
Handle errors in your code
Every failure the SDK raises is aBioptimusError carrying a machine-readable code, structured context, and an actionable remediation. Catch the base class to handle any SDK failure and read those fields directly:
except handlers keep working. Each typed error subclasses the built-in it replaces, so code that already catches the standard exception is unaffected:
BioptimusImportError names the exact extra to install, so a missing optional dependency is self-explanatory:
Error codes
EveryBioptimusError carries a stable, hyphen-delimited code such as BIO-WSI-002, grouped by domain:
Each code has a fixed remediation string, the same one attached to its
error_code field above and surfaced by verify_endpoint’s failure reports. The full list of codes and remediations is in the API reference.
