Skip to main content

spareparts-sdk

Drop-in OpenTelemetry tracing for OpenAI, Anthropic, and Gemini LLM calls, captured locally and optionally exported to Spare Parts Core.

import spareparts_sdk as spareparts

spareparts.init(service_name="mechanic-assistant")

with spareparts.workflow("diagnose"):
    response = client.messages.create(...)

Install with the providers you use:

pip install 'spareparts-sdk[anthropic]'   # or [openai], [gemini], [all]

Tracing

After init(), any instrumented provider call in this process is traced and written to a local SQLite file (./.spareparts/traces.db by default). Each span row carries the model, provider, prompt/completion content, input/output/cache token counts, cost, latency, status, and any exception type and message.

init() takes:

argument default what it does
project_id None Tags every span for later filtering.
sample_rate 1.0 Head sampling ratio. Parent-based, so a sampled trace keeps all its child spans.
capture_content True False strips prompts/completions and keeps only metadata.
redact None Callable applied to every prompt/completion string before export.
max_content_chars 24000 Per-field cap; longer values get a …[truncated] marker.
service_name "llm-app" Logical service name on every span.
environment "production" Deployment environment on every span.
local_dir ".spareparts" Directory holding traces.db.
endpoint None Core base URL for authenticated remote span export.
api_key None Workspace API key or lease-bound runner token; never persisted.
attributes None Stable attribution fields added to every emitted span.

project_id, environment, service_name, and local_dir resolve the same way: explicit kwarg > env var (SPAREPARTS_PROJECT, SPAREPARTS_ENV, SPAREPARTS_SERVICE_NAME, SPAREPARTS_LOCAL_DIR) > a repo-root spareparts.toml's [capture] table > the default above.

# spareparts.toml
[capture]
project = "sparepartslabs/spareparts"
service_name = "spareparts-api"
environment = "production"
local_dir = ".spareparts"

Remote export

Pass endpoint and api_key together to send the same canonical spans to Core. Failed batches stay pending in memory; call flush() before completing a short-lived job so it can retry or fail the job instead of losing telemetry. Span IDs make retries idempotent.

spareparts.init(endpoint="https://api.example", api_key=token, capture_content=False)
# run model work
if not spareparts.flush():
    raise RuntimeError("telemetry was not accepted")

Workflow tracking

workflow(name) opens a named parent span. Every LLM call made inside becomes a child of it, so a trace's root span name identifies the feature the calls belong to, which is what makes per-feature cost and latency grouping possible. It works as a context manager or as a decorator on sync and async functions:

@spareparts.workflow("mechanic-assistant")
async def _ai_reply(message: str) -> str:
    response = await client.messages.create(...)
    return response.content[0].text

An exception raised inside a workflow propagates unchanged; the span is marked error and keeps the exception type and message.

Reading traces

traces.db is plain SQLite with a single spans table:

sqlite3 .spareparts/traces.db \
  "SELECT started_at, name, model, input_tokens, output_tokens, cost, latency_ms
     FROM spans ORDER BY started_at DESC LIMIT 20;"

Group a run's cost by feature via the root span:

SELECT root.name, COUNT(*) AS calls, ROUND(SUM(child.cost), 4) AS cost_usd
  FROM spans child
  JOIN spans root ON root.span_id = child.parent_span_id
 GROUP BY root.name
 ORDER BY cost_usd DESC;

The schema is the contract with anything that reads the file, so it changes only as a public interface would.

Tests

pip install -e '.[dev]'
pytest

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spareparts_sdk-0.2.0.tar.gz (64.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spareparts_sdk-0.2.0-py3-none-any.whl (16.9 kB view details)

Uploaded Python 3

File details

Details for the file spareparts_sdk-0.2.0.tar.gz.

File metadata

  • Download URL: spareparts_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 64.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for spareparts_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 265b991b0709a19a5d9026ea763e6dee870186b03c234ff3331f917bddf0f1c0
MD5 1ac14e9d228a7275ba4ab187788a2c58
BLAKE2b-256 cb22441df30a2d61df01fd3ab9ab2bcf2bfaafd4a4aee84a5bc5b71086f432b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for spareparts_sdk-0.2.0.tar.gz:

Publisher: publish.yml on sparepartslabs/spareparts-sdk-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spareparts_sdk-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: spareparts_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 16.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for spareparts_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e35f5637d7775fcdd94469523db5843d23f76e835f1b5befd111459a18cf5d6d
MD5 0ca666971378f4a1941eb1135aa837cf
BLAKE2b-256 86cc195bb0599f3302aa0812c51ca3353e21b0c89d0829795cf014ea9a1c1b1d

See more details on using hashes here.

Provenance

The following attestation bundles were made for spareparts_sdk-0.2.0-py3-none-any.whl:

Publisher: publish.yml on sparepartslabs/spareparts-sdk-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page