Troubleshooting
Symptoms first, causes second. Everything here assumes a current SDK:
glassflow-rius 1.1.1 or newer for Python, @glassflow-ai/rius 1.2.0 or
newer for TypeScript. Older releases behave the same on the basics, but some
log lines quoted below were worded differently, and some fixes noted below
need these versions.
No traces are arriving
Check in this order:
-
Is the SDK disabled?
RIUS_DISABLED=1(ortrue/yes/on) silently drops all spans in-process. Also checkdisabled=Truein code. -
Is sampling set low?
RIUS_SAMPLE_RATE=0.1keeps one trace in ten;0keeps none. Sampling decides per whole trace, so a sampled-out trace is completely invisible, not partially. -
Did the process exit before the batch flushed? Batches flush every 5 seconds by default. Short scripts can exit between batches if the interpreter is killed rather than exiting cleanly; call
client.flush()at the end. Serverless invocations should always flush explicitly. Since 0.9.0,flush()returningTrueconfirms delivery, not just an empty queue: it returnsFalsewhen the queue drained but the last export was rejected. -
Endpoint and key. Since 0.9.0 the SDK diagnoses these itself, as warnings on the
rius.*loggers:init()warns immediately when no API key is configured and the SDK would export to the managed platform.- A one-shot background connectivity check at
init()warns when the endpoint rejects your key (HTTP 401/403, checkRIUS_API_KEY) or cannot be reached at all (checkRIUS_ENDPOINT). - The first failed export logs a warning saying traces are not being delivered; repeats log at DEBUG until an export succeeds, and recovery logs at INFO.
If you see none of these, raise your log level; the SDK warns but never raises in your code.
-
Billing or rate limits. The export failure names the HTTP status.
402means billing blocks ingest: check Settings → Plan & usage.429means the workspace is over its plan’s ingest rate: lower the volume with sampling or move to a plan with a higher rate. Both drop spans rather than buffer them; see Retries and failure behavior. -
Configuration still under
GLASSFLOW_*names? From 1.0.0 the Python SDK reads only theRIUS_*environment variables (the TypeScript SDK never read the old names). AGLASSFLOW_API_KEYorGLASSFLOW_ENDPOINTleft in your environment is ignored, so the SDK exports without a key or to the default endpoint, and nothing arrives in your workspace. Rename them; see the configuration reference.
”init() called again” warning
The global OpenTelemetry provider is write-once. A second init() returns
the existing client unchanged and logs this warning. If you genuinely need
to reconfigure, call client.shutdown() first; if you need a parallel
pipeline, use init(set_global=False).
An instrumentation is not producing spans
- The extra (Python) or optional package (TypeScript) must be installed in
the same environment (
pip install "glassflow-rius[openai]", ornpm install @arizeai/openinference-instrumentation-openai). A requested-but-missing integration logs a warning atinit()time. - The instrumented library must be installed too. In Python a missing one
logs a
DependencyConflict, see init() logs a DependencyConflict. - Scoped clients (
set_global=False, orsetGlobal: falsein TypeScript 1.8.0 or later) do not auto-instrument; passinstrumentsexplicitly. - If another OpenTelemetry setup already instrumented the library, the SDK leaves it alone by design; its spans go wherever that setup exports.
- TypeScript, CommonJS apps: require the traced package before
init(). The SDK patches the build of a provider or MCP SDK your process actually uses, so CommonJS and pure-ESM applications both get spans. The one pattern it cannot repair is a CommonJSrequireofopenai,@anthropic-ai/sdk, or@modelcontextprotocol/sdkthat happens only afterinit(): those calls stay untraced even thoughawait client.readylists the integration. Move the require aboveinit(), where applications naturally place it, or trace the affected calls with manual generations. Thelangchainandvercel-aiintegrations do not patch the package and have no ordering rule. - TypeScript, pnpm app on a serverless or file-tracing host: pass
instrumentModules. A deployment that ships only the files your code imports, such as a Vercel function built from a pnpm workspace, can leave out the links the SDK follows to load its optional peers.client.readythen omitsopenaioranthropicand no LLM spans arrive. Since 1.1.0,init()logs a warning when yourpackage.jsonlists the OpenAI or Anthropic instrumentation package but the SDK cannot load it, pointing atinstrumentModules. The warning is best effort: it reads thepackage.jsonin the working directory, and stays silent when that file is not there. Pass the modules you import yourself; see pnpm and serverless deployments. - TypeScript, Vercel AI SDK 5 or 6:
client.readydoes not listvercel-ai. That is expected since 1.2.0: those versions need nothing registered, and their spans arrive from calls withexperimental_telemetry: { isEnabled: true }. See Vercel AI SDK.
init() logs a DependencyConflict
DependencyConflict: requested: "anthropic >= 0.84.0" but found: "None"The extra is installed but the library it instruments is not. Extras carry
the instrumentation only, so glassflow-rius[anthropic] does not install
anthropic. Rius takes no dependency on provider SDKs on purpose: pinning
them would let an observability library dictate the version your model calls
run against.
Install the library alongside the extra, and that integration starts working
on the next init():
pip install "glassflow-rius[anthropic]" anthropicThe message comes from OpenTelemetry’s instrumentation base class, so it
names the version range the instrumentation supports and None for what it
found. Nothing else breaks: tracing continues, and only the integration
whose library is missing stays off. If you meant not to have that library,
drop the extra as well, or list the ones you want with
init(instruments=[...]) so the SDK never tries the others.
Content is missing from spans
capture_content=False(orRIUS_CAPTURE_CONTENT=false) strips prompt/response content at export while keeping metadata. See Privacy controls for exactly which attributes are covered.- A masking callable that raises or returns
Nonedrops the affected attribute entirely, by design (fail closed), with a warning log.
Long agent spans lose their model, tools, or usage
An auto-instrumented agent span that looks complete for the first few turns
and then loses its model, request parameters, tool definitions, system
prompt, token usage, or output has hit OpenTelemetry’s per-span attribute
count limit. init() raises it to 4096, so check whether
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT or OTEL_ATTRIBUTE_COUNT_LIMIT is set in
your environment to something lower: a value you set wins. See
Span attribute limit.
Queries or alerts stopped matching after upgrading to 1.0.0
1.0.0 changed four things a saved search, dashboard filter, or alert can match on:
- Span names. Unnamed
TOOL,AGENT,RETRIEVER,LLM, andEMBEDDINGspans are now named after their operation and target, such asexecute_tool search_orders, instead of after the function. An alert filtered on Step (the span name) needs the new name, or passnameexplicitly to keep the old one. See Span names and identity. - Request parameters.
model_parameterskeys land on their canonicalgen_ai.request.*key, or underrius.request.*when the conventions do not define them. For example,response_formatis nowrius.request.response_format. See Request parameters. - Retrieval operation.
RETRIEVERspans carrygen_ai.operation.nameretrieval, so update filters on the old operation name. - JSON spacing (Python). JSON-valued attributes are written compact,
{"type":"json_object"}rather than{"type": "json_object"}, so a text match on the old spacing stops matching.
Auto-instrumented spans also leave the SDK with the canonical GenAI keys in
place of the llm.* keys the integration’s package writes, so query the canonical ones, for
example gen_ai.usage.input_tokens rather than llm.token_count.prompt.
Token or cost totals look doubled
Upgrade to glassflow-rius 1.1.1 or @glassflow-ai/rius 1.2.0, which count
a model call once when a wrapper such as LangChain, LiteLLM, LlamaIndex, or
the Vercel AI SDK records it too. If totals still look doubled, your setup
is one of the cases in
Still counted twice,
which says which layer to keep.
Values look truncated
Inputs, outputs, messages, tool results, and serialized objects are capped
at 32 KB in both SDKs, with an explicit …(truncated) suffix. This is a
fixed safety limit on attribute size: a multi-megabyte tool result would
otherwise become a multi-megabyte span. The cap applies to the serialized
text, so a large object is cut once it is rendered to JSON.
Spans are dropped under load
The in-memory queue holds 2048 spans by default; overflow is dropped with a
warning. Raise OTEL_BSP_MAX_QUEUE_SIZE, or lower the volume with
sampling. See Reliability for all
batching knobs.
Next steps
- Reliability: the export pipeline these symptoms come from, and every knob on it.
- Installation and configuration: the full configuration reference.