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 |
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 tls_llm_observer-0.1.1-py3-none-any.whl.
File metadata
- Download URL: tls_llm_observer-0.1.1-py3-none-any.whl
- Upload date:
- Size: 38.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1eb0a425a930a0e70fd20d28b772f1f3b9cb253d210a241859fc22403b56261
|
|
| MD5 |
af6a5235a2c1e3ce985d27948d5a6bf1
|
|
| BLAKE2b-256 |
d335a0fa599dcd1a07149a05eb1513b95e9f025617f96bc0b0b792aecceb8331
|