TLS LLM Observer Python SDK
OpenTelemetry-first tracing for manual instrumentation, decorators, and OpenAI clients. The first release exports traces only through OTLP/HTTP protobuf.
Install
Install the core tracing SDK and OpenTelemetry dependencies:
pip install tls-llm-observer
Install the OpenAI integration together with openai, packaging, and wrapt:
pip install "tls-llm-observer[openai]"
The default endpoint is http://localhost:4318/v1/traces. Configure it with
TLS_TRACE_OTEL_ENDPOINT or the standard OTEL_EXPORTER_OTLP_TRACES_ENDPOINT.
Applications configure tracing through TraceConfig; externally supplied providers or
exporters are not accepted.
Manual instrumentation
from tls_llm_observer import TraceClient, trace
client = TraceClient()
with client.start_as_current_span("answer-question") as span:
span.update(input={"question": "Why is the sky blue?"})
span.update(output={"answer": "Rayleigh scattering"})
@trace(client=client)
def normalize(value: str) -> str:
return value.strip().lower()
client.flush()
client.shutdown()
span.update(input=...) and span.update(output=...) write
gen_ai.input.messages and gen_ai.output.messages. The supplied value is stored
directly using the SDK's normal OpenTelemetry attribute conversion; values that do
not match the GenAI message schemas are not wrapped or reshaped.
start_span() does not replace the current context. Use start_as_current_span() when
new operations should automatically become children. Span names, kinds, attributes, and
parenting remain user-controlled.
from opentelemetry.trace import SpanKind
from tls_llm_observer import TraceClient, propagate_attributes
client = TraceClient()
with propagate_attributes(session_id="session-1", conversation_id="conversation-1"):
with client.start_as_current_span("request", kind=SpanKind.SERVER):
child = client.start_span("background-work")
child.update(output={"ok": True}).end()
The context manager also supports async with.
Use the tool-specific helpers for actual tool execution. They create an
execute_tool {name} INTERNAL Span and set the required GenAI semantic
attributes at Span creation time:
with client.start_as_current_tool_span(
"get_weather",
tool_call_id="call_123",
arguments={"city": "Beijing"},
) as span:
result = {"temperature": 28}
span.set_tool_result(result)
@trace(span_type="tool") applies the same execute-tool defaults and records
captured function arguments/results on gen_ai.tool.call.arguments and
gen_ai.tool.call.result.
Decorator and streams
@trace supports sync/async functions, generators, async generators, and Starlette-style
responses with a body_iterator. Streaming spans end on exhaustion or explicit close.
from tls_llm_observer import trace
@trace(name="token-stream")
def tokens():
yield "hello"
yield " world"
OpenAI
OpenAI is an optional dependency:
from tls_llm_observer import TraceClient
from tls_llm_observer.openai import OpenAI
client = TraceClient()
openai_client = OpenAI(trace_client=client)
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
The integration supports chat completions, completions, responses, embeddings, structured
parse, synchronous and asynchronous calls, and streams. OpenAI, AsyncOpenAI,
AzureOpenAI, and AsyncAzureOpenAI use the supplied TraceClient; clients created from
the exported official openai module use the process default TraceClient.
Native openai.Stream and openai.AsyncStream objects keep their original type and
identity. Streaming spans end on exhaustion, explicit close, context manager exit,
cancellation, or iteration error.
Tracing-only keyword arguments are removed before the provider call:
response = openai_client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
trace_name="welcome-message",
trace_attributes={"tenant.id": "example"},
capture_content=False,
)
Successful non-streaming raw responses retain their original response type. Raw streaming
response APIs are not traced. Set TLS_TRACE_OPENAI_SKIP_RAW_RESPONSES=true to skip all
raw-response calls. uninstrument_openai(client) disables tracing for one client;
uninstrument_openai() disables the OpenAI integration globally.
OpenAI Assistants are intentionally not instrumented.
Environment variables
| Variable | Purpose |
|---|---|
TLS_TRACE_ENABLED |
Enable or disable tracing |
TLS_TRACE_SAMPLE_RATE |
Parent-based trace ratio, from 0.0 to 1.0 |
TLS_TRACE_CAPTURE_CONTENT |
Capture decorator/OpenAI input and output |
TLS_TRACE_OPENAI_SKIP_RAW_RESPONSES |
Do not trace OpenAI raw-response APIs |
TLS_TRACE_OTEL_ENDPOINT |
OTLP HTTP traces endpoint |
TLS_TRACE_OTEL_HEADERS |
Comma-separated key=value headers |
TLS_TRACE_OTEL_TRACE_TOPIC_ID / TLS_TRACE_TOPIC_ID |
TLS Trace Topic ID |
TLS_TRACE_OTEL_REGION / TLS_REGION |
TLS region |
TLS_TRACE_OTEL_AK / TLS_AK |
TLS access key |
TLS_TRACE_OTEL_SK / TLS_SK |
TLS secret key |
TLS_TRACE_OTEL_SECURITY_TOKEN / TLS_SECURITY_TOKEN |
Optional TLS STS token |
TLS_TRACE_OTEL_API_KEY / TLS_API_KEY |
TLS API Key alternative to AK/SK |
TLS_TRACE_OTEL_COMPRESSION |
none, gzip, or deflate |
TLS_TRACE_MAX_QUEUE_SIZE |
BatchSpanProcessor queue capacity |
TLS_TRACE_MAX_EXPORT_BATCH_SIZE |
Maximum spans per OTLP batch |
TLS_TRACE_SCHEDULE_DELAY_MS |
Batch scheduling delay |
Metadata
Release files for tls-llm-observer 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tls_llm_observer-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for tls_llm_observer-0.1.1-py3-none-any.whl |
Release files / tls_llm_observer-0.1.1-py3-none-any.whl
| Download URL | tls_llm_observer-0.1.1-py3-none-any.whl |
|---|---|
| Size | 38.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b1eb0a425a930a0e70fd20d28b772f1f3b9cb253d210a241859fc22403b56261
|
|
BLAKE2b-256 checksum How to use checksums |
d335a0fa599dcd1a07149a05eb1513b95e9f025617f96bc0b0b792aecceb8331
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.0
|
Security for tls-llm-observer 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.