Help us shape the future of Go! Take the 2026 Go Developer Survey

otelgenai

package
v1.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

README

otelgenai (GenAI instrumentation)

OpenTelemetry GenAI semantic-conventions instrumentation for Genkit Go.

Import path: github.com/firebase/genkit/go/plugins/otelgenai

This plugin maps Genkit actions to the OpenTelemetry GenAI semantic conventions:

  • Model actions become chat <model> client spans carrying gen_ai.* attributes (provider, model, request config, response finish reasons, token usage).
  • Tool actions can optionally become execute_tool <name> spans.
  • Every other Genkit action type becomes a generic span tagged with genkit.action.type so the trace tree stays connected.
  • The two spec metrics gen_ai.client.token.usage and gen_ai.client.operation.duration are emitted per model call.

The application owns the OpenTelemetry SDK: configure your TracerProvider / MeterProvider / LoggerProvider before constructing Genkit. When no SDK is configured, go.opentelemetry.io/otel returns non-recording spans and no-op instruments and the provider is inert.

Usage

import (
	"go.opentelemetry.io/otel"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"

	"github.com/firebase/genkit/go/core/tracing"
	"github.com/firebase/genkit/go/genkit"
	"github.com/firebase/genkit/go/plugins/googlegenai"
	"github.com/firebase/genkit/go/plugins/otelgenai"
)

// 1. The app owns the OTel SDK (point the exporter at your OTLP collector).
otel.SetTracerProvider(sdktrace.NewTracerProvider(/* ... */))

// 2. Route Genkit telemetry through the GenAI provider. It composes with the
//    built-in dev instrumentation that feeds the Developer UI.
tracing.SetInstrumentation(otelgenai.New(&otelgenai.Options{
	ContentCapturingMode: otelgenai.SpanOnly, // default NoContent; may contain PII
}))

// 3. Use Genkit as usual.
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{}))

To also keep Genkit's default genkit:* OpenTelemetry spans, list both providers:

tracing.SetInstrumentation(&tracing.OTelInstrumentation{}, otelgenai.New(nil))

The configuration is process-wide on purpose: Genkit actions can run without a Genkit instance (for example a model obtained directly from a plugin), and those calls are instrumented too.

See go/samples/otel-genai for a runnable example that exports over OTLP.

Google Cloud / Firebase telemetry

Do not combine this provider with the googlecloud or firebase telemetry plugins. Configuring it replaces Genkit's default OpenTelemetry encoding (the genkit:* span attributes) that those plugins read, so their Genkit metrics stop, and their input/output redaction does not cover gen_ai.* content attributes.

What gets recorded

  • gen_ai.request.* params are read from the request config, whether it is Genkit's GenerationCommonConfig or a provider SDK's native type (camelCase and snake_case names are both recognized). A param set to 0 is recorded.
  • A call that fails after the model responded (for example, output schema validation) still records the response: token usage, content, and a gen_ai.response.finish_reasons of error.
  • error.type is the Genkit status name, such as INVALID_ARGUMENT or RESOURCE_EXHAUSTED (INTERNAL when unclassified).
  • Inline media (data: URIs) is captured as a blob part with its decoded size in size_bytes, never the payload. Remote media becomes a uri part. With CaptureActionIO, inline media in model requests/responses is replaced by a marker such as data:image/png;base64,[1834 bytes omitted].
  • In EventOnly / SpanAndEvent modes, the gen_ai.client.inference.operation.details event carries content as structured (map/slice) attributes; span attributes carry it as JSON strings.
  • Telemetry labels (tracing.WithTelemetryLabels) are set as span attributes.

Options

otelgenai.Options:

Option Default Description
ContentCapturingMode NoContent Where spec-shaped message content is recorded (span/event). May contain PII.
CaptureActionIO false Record raw Genkit input/output as genkit.input / genkit.output JSON.
EmitToolSpans false Emit execute_tool spans for tool actions.
DisableMetrics false Turn off the GenAI client metrics (on by default).
ScopeName genkit-genai Instrumentation scope name for the tracer/logger/meter.
TracerProvider / MeterProvider / LoggerProvider global Providers for spans, metrics, and content events.

When ContentCapturingMode is left at its zero value, the env var OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT is consulted (spec enum names: NO_CONTENT, SPAN_ONLY, EVENT_ONLY, SPAN_AND_EVENT).

Documentation

Overview

Package otelgenai provides an OpenTelemetry GenAI semantic-conventions instrumentation for Genkit.

The application owns SDK setup: configure a TracerProvider / MeterProvider / LoggerProvider (e.g. via the OTel SDK) before constructing Genkit. When no provider is configured, go.opentelemetry.io/otel returns non-recording spans and no-op instruments, so this provider is effectively inert.

Wire it up with tracing.SetInstrumentation:

tracing.SetInstrumentation(otelgenai.New(&otelgenai.Options{
	ContentCapturingMode: otelgenai.SpanOnly,
	EmitToolSpans:        true,
}))
g := genkit.Init(ctx, genkit.WithPlugins(&googlegenai.GoogleAI{}))

Configuration is process-wide on purpose: Genkit actions (e.g. a model obtained straight from a plugin) can run without a Genkit instance, and they must be instrumented too.

The provider replaces Genkit's default OpenTelemetry encoding (the genkit:* span attributes) and composes with the built-in dev instrumentation, which feeds the Developer UI on a separate pipeline. Do not combine it with the googlecloud or firebase telemetry plugins: those read the genkit:* attributes (their metrics stop) and their redaction does not cover gen_ai.* content.

See the spec: https://github.com/open-telemetry/semantic-conventions-genai

Index

Constants

View Source
const CaptureContentEnvVar = "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT"

CaptureContentEnvVar is the spec's canonical opt-in env var for capturing message content. It is consulted when Options.ContentCapturingMode is unset.

Variables

This section is empty.

Functions

This section is empty.

Types

type ContentCapturingMode

type ContentCapturingMode string

ContentCapturingMode mirrors the OTel GenAI ContentCapturingMode: where captured message content is recorded.

Content may contain PII and is often large, so the default is NoContent. EventOnly puts structured content on a dedicated log event and is preferred for production; SpanOnly puts it on span attributes as a JSON string (easy to eyeball, but subject to backend attribute/envelope limits), best for development.

const (
	NoContent    ContentCapturingMode = "NO_CONTENT"
	SpanOnly     ContentCapturingMode = "SPAN_ONLY"
	EventOnly    ContentCapturingMode = "EVENT_ONLY"
	SpanAndEvent ContentCapturingMode = "SPAN_AND_EVENT"
)

type Instrumentation

type Instrumentation struct {
	// contains filtered or unexported fields
}

Instrumentation is a tracing.Instrumentation that emits OpenTelemetry telemetry following the OTel GenAI semantic conventions.

func New

func New(opts *Options) *Instrumentation

New builds an Instrumentation from opts. A nil opts uses the defaults. opts is read once, here; changing it afterwards has no effect.

The tracer, meter, and logger are resolved here, once. With the global providers that still picks up an SDK installed later: the OTel globals hand out delegating instruments that switch to the real provider when it is set. Resolving per span instead would take the SDK provider's lock on every span start.

func (*Instrumentation) StartSpan

StartSpan dispatches on the Genkit action type and opens a span encoded with the OTel GenAI conventions. The returned span records the result when Genkit ends it.

type Options

type Options struct {
	// ContentCapturingMode selects where spec-shaped GenAI message content
	// (gen_ai.system_instructions, gen_ai.input.messages, gen_ai.output.messages)
	// is recorded. Content may contain PII, so the default is NoContent. When
	// the zero value is passed, the env var CaptureContentEnvVar is consulted;
	// an explicit value here overrides it.
	ContentCapturingMode ContentCapturingMode

	// CaptureActionIO records raw Genkit action input/output as genkit.input /
	// genkit.output JSON attributes on every span (model, tool, flow, etc.).
	// Independent of ContentCapturingMode. May contain PII, off by default.
	// Inline data: media in model requests and responses is replaced with a
	// size marker; other actions' values (e.g. flow inputs) are recorded as is.
	CaptureActionIO bool

	// EmitToolSpans emits execute_tool spans for tool actions. Off by default.
	EmitToolSpans bool

	// DisableMetrics turns off the spec's GenAI client metrics (token usage,
	// operation duration). Metrics are on by default (the zero value): low
	// cardinality and cheap.
	DisableMetrics bool

	// ScopeName is the instrumentation scope name for the tracer/logger/meter.
	// Defaults to "genkit-genai".
	ScopeName string

	// TracerProvider creates the spans. Nil means the global provider.
	TracerProvider oteltrace.TracerProvider

	// MeterProvider creates the GenAI client metrics. Nil means the global
	// provider.
	MeterProvider metric.MeterProvider

	// LoggerProvider receives the gen_ai.client.inference.operation.details
	// events (EventOnly / SpanAndEvent). Nil means the global provider.
	LoggerProvider otellog.LoggerProvider
}

Options configures an Instrumentation.

Directories

Path Synopsis
internal
genai
Package genai holds the mapping from Genkit data to OpenTelemetry GenAI semantic conventions: attribute names, value vocabularies, message shapes, and the spec's client metrics.
Package genai holds the mapping from Genkit data to OpenTelemetry GenAI semantic conventions: attribute names, value vocabularies, message shapes, and the spec's client metrics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL