openinference

openinference-instrumentation (Go)

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.

Install

go get github.com/Arize-ai/openinference/go/openinference-instrumentation@latest

Requires Go 1.25+.

Suppression

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

Context attribute propagation

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.

Masking sensitive data

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.

Send the trace to Arize AX or Phoenix

This package is exporter-agnostic — it’s pure context/config plumbing. Wire it into your tracer-provider setup of choice: