Tracklyng — LLM cost tracking & observability. Capture LLM requests via OpenTelemetry GenAI instrumentation with a one-line install and zero call-site changes.
Project description
Tracklyng — prototype
Capture what can be logged from a real LLM request, with a one-line install in the client's app and zero changes to their call site.
How it works
client app tracklyng lib document
----------- -------------- ----------
tracklyng.init() ───────────▶ sets up OpenTelemetry tracer
turns on the GenAI instrumentation
(every provider SDK)
client.models.generate_content(...)
│ (real request still goes straight to the provider)
▼
OpenTelemetry instrumentation captures a span
│
▼
our SpanExporter ─────────────────────────────────────────▶ tracklyng_log.jsonl
(+ token counts and host/location, lifted from the span & resource)
We do not maintain the monkey-patches ourselves — the
opentelemetry-instrumentation-* packages do. tracklyng.init() just stands up
the tracer, points the exporter at the document, and flips the instrumentation
on. They emit the standard gen_ai.* OpenTelemetry semantic conventions, so one
span shape covers every provider. In production the exporter would be OTLP →
Tracklyng's collector instead of a local file.
Run it
Call tracklyng.init() once, before the first LLM request — the rest is the
provider SDK code you already have:
import os
import tracklyng
tracklyng.init() # the entire integration
# ...your existing, unmodified provider call:
from google import genai
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
client.models.generate_content(
model="gemini-3.1-flash-lite",
contents="In one sentence, what is observability for LLM apps?",
)
uv sync
export GEMINI_API_KEY=your-real-key
python your_app.py
cat tracklyng_log.jsonl | python -m json.tool # one captured span
The same tracklyng.init() covers every supported provider: an Azure OpenAI,
Anthropic, Bedrock, or Vertex AI call produces a span with the same gen_ai.*
keys.
Providers
tracklyng.init() switches on one OpenTelemetry instrumentation per LLM SDK we
ship. A client only produces spans for the SDKs they actually use; others are
skipped silently. Adding a provider = adding its instrumentor to
_enable_instrumentors.
| Provider | Instrumentation | Notes |
|---|---|---|
| OpenAI / Azure OpenAI | opentelemetry-instrumentation-openai |
one instrumentor covers both — AzureOpenAI is part of the openai SDK |
| Anthropic / Claude | opentelemetry-instrumentation-anthropic |
also covers Claude via the anthropic SDK's Bedrock client |
| AWS Bedrock | opentelemetry-instrumentation-bedrock |
patches the boto3 bedrock-runtime client |
| Vertex AI | opentelemetry-instrumentation-vertexai |
patches google-cloud-aiplatform |
| Google Gemini | opentelemetry-instrumentation-google-generativeai |
patches the unified google-genai SDK |
All five emit the same
gen_ai.*attributes, so the captured span shape is identical across providers — our exporter reads one set of keys regardless of which provider made the call.
Data captured
Prompt and response content is captured verbatim. Each span carries the full
gen_ai.*payload the instrumentation emits — including user messages, system instructions, and model completions (both the current semantic-convention attributes and event bodies). Nothing is redacted or stripped; the complete record is stored server-side intelemetry_spans.payload.
Because the library runs inside your application, anything your app sends to or receives from an LLM — including PII, PHI, or other regulated data — is part of the captured span. If you operate under GDPR/HIPAA or similar obligations, account for this prompt/response content in your data-processing assessment before enabling Tracklyng. (Earlier prototypes stripped content to metadata only; that behavior was removed — content is now persisted in full.)
Layout
| Path | What |
|---|---|
tracklyng/__init__.py |
exposes tracklyng.init() |
tracklyng/_capture.py |
OTel setup, instrumentor list, span exporter that writes the document |
tests/ |
unit tests for the span-to-record transform and host attributes |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tracklyng-0.1.0.tar.gz.
File metadata
- Download URL: tracklyng-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4208f132da48f6d2c728f3b7fedb3e902637ad64ab875f528a4df31c3925e0b5
|
|
| MD5 |
72f1ebc9632446c9dc064973549675fd
|
|
| BLAKE2b-256 |
367ee3b5fe2dc09c8e276a572d6bec4d766383356e930b555809d6d44f11af27
|
Provenance
The following attestation bundles were made for tracklyng-0.1.0.tar.gz:
Publisher:
publish.yml on loro-app/tracklyng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tracklyng-0.1.0.tar.gz -
Subject digest:
4208f132da48f6d2c728f3b7fedb3e902637ad64ab875f528a4df31c3925e0b5 - Sigstore transparency entry: 1780429311
- Sigstore integration time:
-
Permalink:
loro-app/tracklyng@8c8727125f3cca84aaba5c76a7f8b82aa8ec9624 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/loro-app
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8c8727125f3cca84aaba5c76a7f8b82aa8ec9624 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tracklyng-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tracklyng-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1e3e13eaffacfb2938d8ecacd710e3acc071d73911528eb93a061bd3cb9168a
|
|
| MD5 |
25c6e66b09f13505280cd421fa9e890d
|
|
| BLAKE2b-256 |
8238ce7f1b4287f937d144d70e77db5ed7643032591da57448b210f695fd8fa7
|
Provenance
The following attestation bundles were made for tracklyng-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on loro-app/tracklyng
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tracklyng-0.1.0-py3-none-any.whl -
Subject digest:
c1e3e13eaffacfb2938d8ecacd710e3acc071d73911528eb93a061bd3cb9168a - Sigstore transparency entry: 1780429359
- Sigstore integration time:
-
Permalink:
loro-app/tracklyng@8c8727125f3cca84aaba5c76a7f8b82aa8ec9624 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/loro-app
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8c8727125f3cca84aaba5c76a7f8b82aa8ec9624 -
Trigger Event:
push
-
Statement type: