metry

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 11, 2026 License: MIT Imports: 22 Imported by: 0

README

metry

Go OpenTelemetry OpenLLMetry

Universal, zero-boilerplate OpenTelemetry & LLMOps hub for Go AI applications. One line of code to trace them all.


Why metry

  • Zero-Boilerplate Init — Configure Tracer, Meter, and W3C propagators in a single call. No OTel SDK setup boilerplate.
  • 100% Vendor-Agnostic (OTLP First) — Works out of the box with Jaeger, Grafana Tempo, Langfuse, Phoenix, Datadog. Swap the backend by changing one line.
  • OpenLLMetry Semantic Conventions — Built-in typed constants and helpers for token usage, cost, and prompts (gen_ai.system, gen_ai.usage, etc.).
  • Plug-and-Play Middlewares — Ready-made wrappers for net/http and gRPC to create root spans and propagate trace_id.

Architecture

graph LR
  subgraph Libraries
    ragy[ragy]
    flowy[flowy]
    toolsy[toolsy]
    app[your app]
  end

  subgraph metryPkg [metry]
    metryCore[Init / GlobalTracer / GlobalMeter]
    metryGenAI[genai]
    metryHTTP[HTTP middleware]
    metryGRPC[gRPC middleware]
  end

  subgraph Backends
    langfuse[Langfuse]
    jaeger[Jaeger]
    tempo[Grafana Tempo]
  end

  ragy --> metryCore
  flowy --> metryCore
  toolsy --> metryCore
  app --> metryCore
  app --> metryGenAI
  app --> metryHTTP
  app --> metryGRPC
  metryCore --> langfuse
  metryCore --> jaeger
  metryCore --> tempo

Installation

go get github.com/skosovsky/metry

Quick Start

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/skosovsky/metry"
	metryhttp "github.com/skosovsky/metry/middleware/http"
)

func main() {
	ctx := context.Background()

	te, me := metry.OTLPGRPC("localhost:4317", true)
	shutdown, err := metry.Init(ctx, metry.Options{
		ServiceName:    "my-ai-service",
		Environment:    "production",
		TraceExporter:  te,
		MetricExporter: me,
		TraceRatio:     metry.Float64(1.0),
	})
	if err != nil {
		log.Fatal(err)
	}
	defer shutdown(ctx)

	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
	})
	handler := metryhttp.Handler(mux, "HTTP /")
	log.Fatal(http.ListenAndServe(":8080", handler))
}

Semantic Conventions (LLMOps)

Record token usage and cost on the current span so backends like Langfuse or Phoenix can show agent trees and costs. To also emit OTel counters for token usage and cost (e.g. for Grafana), call genai.Init once after metry.Init:

import (
	"log"

	"github.com/skosovsky/metry"
	"github.com/skosovsky/metry/genai"
)

// After metry.Init, enable GenAI metric counters (optional; RecordUsage still sets span attributes without this):
if err := genai.Init(metry.GlobalMeter()); err != nil {
	log.Fatal(err)
}

// Inside your LLM call handler:
ctx, span := metry.GlobalTracer().Start(ctx, "llm-call")
defer span.End()

// After the LLM responds:
genai.RecordUsage(ctx, span, 150, 50, 0.002)  // input tokens, output tokens, cost USD
genai.RecordInteraction(span, "Summarize this", "Here is the summary...")

Spans tagged with gen_ai.usage.* and gen_ai.prompt / gen_ai.completion are recognized by OpenLLMetry-compatible backends for dashboards and agent traces.

Agentic & RAG Tracing

Tag tool calls and cache hits on spans so backends can show tool usage and RAG behavior:

// Before executing a tool (e.g. inside toolsy):
genai.RecordToolCall(span, "search", "call-1", `{"q":"weather"}`)

// After checking semantic cache in RAG layer:
genai.RecordCacheHit(span, true, "pgvector_cache")

// When transitioning workflow steps (e.g. in flowy):
genai.RecordAgentState(span, "cardiologist", "specialist", "step-2")

Streaming & UX Metrics

Record Time To First Token (TTFT) for streaming LLM responses. Requires genai.Init(metry.GlobalMeter()) to be called first:

start := time.Now()
// ... start streaming, receive first token ...
genai.RecordTTFT(ctx, time.Since(start).Seconds())

The gen_ai.client.ttft histogram (unit: seconds) is exported with the rest of your OTel metrics for dashboards and SLOs.

Context Propagation (Baggage)

Propagate key-value metadata (e.g. session_id, patient_id) across HTTP and gRPC boundaries. Keys must be valid W3C baggage identifiers (no spaces or special characters like /).

// At entry point (e.g. after auth):
ctx, err := metry.ContextWithBaggage(ctx, "patient_id", "p-123")
if err != nil {
	// invalid key
}

// Downstream (any service receiving the context):
id := metry.BaggageValue(ctx, "patient_id") // "p-123"

HTTP and gRPC

  • HTTP — Wrap your handler: metryhttp.Handler(mux, "operation-name").
  • gRPC — Use metrygrpc.ServerOptions() when creating the server and metrygrpc.ClientDialOption() when creating the client.

Ecosystem

metry is the central observability layer for the AI stack. It makes libraries such as ragy (RAG), flowy (orchestration), and toolsy (tools) visible in production by providing a single tracer and meter and standard GenAI attributes.

Contributing

Contributions are welcome. Please open an issue or PR.

License

MIT. See LICENSE for details.

Documentation

Overview

Package metry provides a zero-boilerplate OpenTelemetry and LLMOps hub for Go AI applications.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrServiceNameRequired is returned when Init is called with an empty ServiceName.
	ErrServiceNameRequired = errors.New("metry: ServiceName is required")
)

Functions

func BaggageValue

func BaggageValue(ctx context.Context, key string) string

BaggageValue retrieves a value for the given key from the context's baggage. Returns an empty string if the key does not exist.

func Console

func Console() (*TraceExporter, *MetricExporter)

Console returns trace and metric exporters that write to stdout (for local development).

func ContextWithBaggage

func ContextWithBaggage(ctx context.Context, key, value string) (context.Context, error)

ContextWithBaggage injects a key-value pair into the context's baggage. This data will automatically propagate across HTTP and gRPC boundaries.

func Float64

func Float64(v float64) *float64

Float64 returns a pointer to v. Use for Options.TraceRatio to distinguish nil (default 1.0) from explicit 0.0 (disable sampling).

func GlobalMeter

func GlobalMeter() metric.Meter

GlobalMeter returns the global Meter for the library (name "metry"). Call after Init.

func GlobalTracer

func GlobalTracer() trace.Tracer

GlobalTracer returns the global Tracer for the library (name "metry"). Call after Init.

func Init

func Init(ctx context.Context, opts Options) (shutdown func(context.Context) error, err error)

Init configures global OTel providers and returns a shutdown function. Resource includes service.name, service.version, deployment.environment and telemetry.sdk.* attributes (e.g. telemetry.sdk.language=go) for backend dashboards.

func Noop

func Noop() (*TraceExporter, *MetricExporter)

Noop returns trace and metric exporters that drop all data (for disabling telemetry or tests).

func OTLPGRPC

func OTLPGRPC(endpoint string, insecure bool) (*TraceExporter, *MetricExporter)

OTLPGRPC returns trace and metric exporters that send data via OTLP over gRPC. endpoint is the target host:port (e.g. "localhost:4317"). If insecure is true, TLS is disabled.

func OTLPHTTP

func OTLPHTTP(endpoint string, headers map[string]string) (*TraceExporter, *MetricExporter)

OTLPHTTP returns trace and metric exporters that send data via OTLP over HTTP. endpoint is the target host:port (e.g. "localhost:4318"). headers are optional HTTP headers.

Types

type MetricExporter

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

MetricExporter is an opaque type that produces an OTel metric exporter. Create it via OTLPGRPC, OTLPHTTP, Console, Noop, or testutil.

func NewMetricExporterFromExporter

func NewMetricExporterFromExporter(exp metric.Exporter) *MetricExporter

NewMetricExporterFromExporter wraps an existing metric.Exporter as a MetricExporter. Used by testutil and other packages that need to plug in a custom exporter instance.

type Options

type Options struct {
	// ServiceName is the name of the service (required).
	ServiceName string
	// ServiceVersion is the release version (optional).
	ServiceVersion string
	// Environment is the deployment environment, e.g. "production", "staging", "local".
	Environment string

	// TraceExporter exports trace spans. If nil, a no-op exporter is used.
	TraceExporter *TraceExporter
	// MetricExporter exports metrics. If nil, a no-op exporter is used.
	MetricExporter *MetricExporter

	// TraceRatio is the fraction of traces to sample (1.0 = 100%, 0.1 = 10%).
	// If nil, 1.0 is used. Use Float64(0) to disable tracing (0% sampling).
	TraceRatio *float64
}

Options configures the full OTel stack for a service.

type TraceExporter

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

TraceExporter is an opaque type that produces an OTel trace exporter. Create it via OTLPGRPC, OTLPHTTP, Console, Noop, or testutil.

func NewTraceExporterFromSpanExporter

func NewTraceExporterFromSpanExporter(exp sdktrace.SpanExporter) *TraceExporter

NewTraceExporterFromSpanExporter wraps an existing sdktrace.SpanExporter as a TraceExporter. Used by testutil and other packages that need to plug in a custom exporter instance.

Directories

Path Synopsis
Package genai provides OpenLLMetry semantic convention constants and helpers for recording GenAI usage (tokens, cost, prompts) on OTel spans.
Package genai provides OpenLLMetry semantic convention constants and helpers for recording GenAI usage (tokens, cost, prompts) on OTel spans.
middleware
grpc
Package grpc provides gRPC instrumentation for metry: server and client stats handlers that create spans and propagate trace context.
Package grpc provides gRPC instrumentation for metry: server and client stats handlers that create spans and propagate trace context.
http
Package http provides HTTP middleware for metry that creates root spans and propagates trace context.
Package http provides HTTP middleware for metry that creates root spans and propagates trace context.
Package testutil provides in-memory exporters and helpers for testing code that uses metry.
Package testutil provides in-memory exporters and helpers for testing code that uses metry.

Jump to

Keyboard shortcuts

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