Customer-facing config layer for the OpenInference Go instrumentors. Provides suppression, context attribute propagation, and PII / sensitive-data masking. Mirrors the Python openinference-instrumentation package.
go get github.com/Arize-ai/openinference/go/openinference-instrumentation@latest
Requires Go 1.25+.
Skip OpenInference instrumentation for any LLM call descended from the returned context. Useful for evaluator / grader code that itself calls an LLM but should not appear in the customer’s product trace:
import "github.com/Arize-ai/openinference/go/openinference-instrumentation"
suppressedCtx := instrumentation.WithSuppression(ctx)
_, _ = evalClient.CreateChatCompletion(suppressedCtx, req) // no span emitted
OTel span attributes do NOT inherit from parent to child — a customer setting session.id on a CHAIN span does NOT cause child LLM spans to carry it. These helpers stash the values on the context.Context (via unexported keys, not OTel baggage, so they never leave the process via a baggage propagator); the provider instrumentors (openinference-instrumentation-openai-go, openinference-instrumentation-anthropic-sdk-go) read them back and auto-apply them to every LLM span descended from the context:
ctx = instrumentation.WithSession(ctx, "session-abc")
ctx = instrumentation.WithUser(ctx, "user-xyz")
ctx = instrumentation.WithMetadata(ctx, `{"team":"platform"}`)
ctx = instrumentation.WithTags(ctx, "prod", "canary") // []string, matches the spec
resp, _ := client.CreateChatCompletion(ctx, req)
// span carries session.id, user.id, metadata, tag.tags
For manual spans you author yourself, call instrumentation.ApplyContextAttributes(ctx, span) right after tracer.Start.
TraceConfig controls which OpenInference attributes the provider instrumentors emit. Configurable via env vars (the canonical OpenInference convention) or programmatically:
export OPENINFERENCE_HIDE_INPUTS=true
export OPENINFERENCE_HIDE_OUTPUTS=true
Or in code:
import "github.com/Arize-ai/openinference/go/openinference-instrumentation"
cfg := instrumentation.TraceConfig{
HideInputs: true, // drops input.value AND llm.input_messages.* AND llm.tools.*
HideOutputs: true, // drops output.value AND llm.output_messages.*
}
// Pass to the provider instrumentor:
// openaiotel.NewTransport(..., openaiotel.WithTraceConfig(cfg))
// anthropicotel.Middleware(..., anthropicotel.WithTraceConfig(cfg))
Full env-var table:
| Env var | What it does |
|---|---|
OPENINFERENCE_HIDE_INPUTS |
Strongest input-side flag. Replaces input.value with __REDACTED__ AND drops llm.input_messages.* AND drops llm.tools.*. |
OPENINFERENCE_HIDE_OUTPUTS |
Strongest output-side flag. Replaces output.value with __REDACTED__ AND drops llm.output_messages.*. |
OPENINFERENCE_HIDE_INPUT_MESSAGES |
Drops llm.input_messages.*; input.value still set. |
OPENINFERENCE_HIDE_OUTPUT_MESSAGES |
Drops llm.output_messages.*; output.value still set. |
OPENINFERENCE_HIDE_INPUT_TEXT / _OUTPUT_TEXT |
Keeps message structure (role, indices), redacts only .content with __REDACTED__. |
OPENINFERENCE_HIDE_LLM_INVOCATION_PARAMETERS |
Omits llm.invocation_parameters. |
OPENINFERENCE_HIDE_LLM_TOOLS |
Omits the llm.tools.* advertised-tools list. (Implied by HIDE_INPUTS.) |
Top-level values (input.value / output.value) are replaced with the __REDACTED__ sentinel rather than omitted, so downstream consumers can distinguish “hidden” from “never recorded”. Structural attribute families are dropped wholesale — the wire-format keys do not appear on the span at all. Token counts, model name, llm.finish_reason, and timing are never affected. Matches Python TraceConfig.mask behavior exactly.
This package is exporter-agnostic — it’s pure context/config plumbing. Wire it into your tracer-provider setup of choice:
arize-otel-go for the one-line OTLP/HTTP setup to otlp.arize.com.http://localhost:6006/v1/traces by default).