Documentation
¶
Overview ¶
Package telemetry holds the OpenTelemetry plumbing Nexus's stages share: the tracer, the span attribute keys, how an error is named, and the metric families recorded on a go-utils metrics sink.
Spans go to the global tracer provider, which forge.New installs. Without one they cost a no-op tracer call. Metrics are recorded only on a sink the caller hands over (nexus.WithMetrics), never on otel.Meter: a Forge app installs no global MeterProvider, so nothing recorded there is exported.
Index ¶
Constants ¶
const ( MetricOperationDuration = "gen_ai.client.operation.duration" MetricTokenUsage = "gen_ai.client.token.usage" // #nosec G101 -- a metric name, not a credential MetricFirstChunk = "nexus_stream_time_to_first_chunk_seconds" MetricRequests = "nexus_requests_total" MetricGuardrailBlocks = "nexus_guardrail_blocks_total" MetricCacheLookups = "nexus_cache_lookups_total" MetricUsageInsertErrors = "nexus_usage_insert_errors_total" MetricLimiterErrors = "nexus_limiter_errors_total" MetricUsageUnpriced = "nexus_usage_unpriced_total" )
Metric names. The gen_ai ones are the OpenTelemetry GenAI client metrics. Forge exports names outside its semconv namespaces with its own prefix and no unit suffix, so these scrape as forge_gen_ai_client_operation_duration and forge_gen_ai_client_token_usage. The nexus ones carry their unit in the name and scrape as forge_<name>.
const ( LabelOperation = "gen_ai.operation.name" LabelProvider = "gen_ai.provider.name" LabelModel = "gen_ai.request.model" LabelErrorType = "error.type" LabelTokenType = "gen_ai.token.type" // #nosec G101 -- a label key, not a credential LabelType = "type" LabelOutcome = "outcome" LabelCode = "code" LabelPhase = "phase" LabelGuard = "guard" LabelKind = "kind" LabelResult = "result" // LabelProviderName is the provider's registered name on nexus metrics; // the gen_ai ones use LabelProvider. LabelProviderName = "provider" )
Metric label keys. Forge turns the dots into underscores on the scrape.
const ( GenAIOperationName = attribute.Key("gen_ai.operation.name") GenAIProviderName = attribute.Key("gen_ai.provider.name") GenAIRequestModel = attribute.Key("gen_ai.request.model") GenAIRequestMaxTokens = attribute.Key("gen_ai.request.max_tokens") GenAIRequestTemperature = attribute.Key("gen_ai.request.temperature") GenAIRequestTopP = attribute.Key("gen_ai.request.top_p") GenAIResponseModel = attribute.Key("gen_ai.response.model") GenAIResponseID = attribute.Key("gen_ai.response.id") GenAIResponseFinishReasons = attribute.Key("gen_ai.response.finish_reasons") GenAIUsageInputTokens = attribute.Key("gen_ai.usage.input_tokens") GenAIUsageOutputTokens = attribute.Key("gen_ai.usage.output_tokens") ErrorTypeKey = attribute.Key("error.type") ProviderName = attribute.Key("nexus.provider.name") RequestType = attribute.Key("nexus.request.type") RequestID = attribute.Key("nexus.request.id") TenantID = attribute.Key("nexus.tenant.id") Outcome = attribute.Key("nexus.outcome") RefusalCode = attribute.Key("nexus.refusal.code") CacheHit = attribute.Key("nexus.cache.hit") CacheKind = attribute.Key("nexus.cache.kind") GuardrailPhase = attribute.Key("nexus.guardrail.phase") GuardrailName = attribute.Key("nexus.guardrail.name") GuardrailBlock = attribute.Key("nexus.guardrail.blocked") GuardrailEdited = attribute.Key("nexus.guardrail.modified") UsageOutcome = attribute.Key("nexus.usage.outcome") UsagePricing = attribute.Key("nexus.usage.pricing_status") BatchJobID = attribute.Key("nexus.batch.job.id") BatchItems = attribute.Key("nexus.batch.items") BatchFailed = attribute.Key("nexus.batch.failed") BatchStatus = attribute.Key("nexus.batch.status") )
Span attribute keys. The gen_ai ones follow the OpenTelemetry GenAI semantic conventions; the nexus ones are this module's own.
const ( OperationChat = "chat" OperationEmbeddings = "embeddings" )
GenAI operation names.
const InstrumentationName = "github.com/xraph/nexus"
InstrumentationName is the instrumentation scope on every span Nexus starts.
const OtherModel = "other"
OtherModel stands in for a model name its provider does not list.
Variables ¶
var ( // OperationDurationBuckets are the bounds the GenAI conventions advise // for gen_ai.client.operation.duration, in seconds. OperationDurationBuckets = []float64{0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56, 5.12, 10.24, 20.48, 40.96, 81.92} // TokenUsageBuckets are the bounds the GenAI conventions advise for // gen_ai.client.token.usage, in tokens. TokenUsageBuckets = []float64{1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864} // FirstChunkBuckets span a fast model's first token to a reasoning // model's long think, in seconds. FirstChunkBuckets = []float64{0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60} )
Histogram bounds, in the metric's unit.
Functions ¶
func Detach ¶
Detach returns a fresh context that carries nothing but ctx's span context. Work that has to outlive ctx (storing a usage record, charging tokens, writing a stream to the cache) starts from it: it is not canceled with the request and inherits none of its values, yet its spans still land in the request's trace.
func ErrorType ¶
ErrorType names err for error.type and the exception event: the context error it is, or the Go type of the innermost error in its chain. It never returns the error's text, which can quote a prompt, a key or a provider's reply. A nil err is "".
func Fail ¶
Fail marks span as failed: error.type, an exception event that carries only exception.type, and an error status whose description is that type. It returns the type. The error's text never reaches the span.
func GenAIProvider ¶
GenAIProvider returns gen_ai.provider.name for a Nexus provider name.
Types ¶
type Counter ¶
type Counter struct {
// contains filtered or unexported fields
}
Counter is a counter declared with label keys. A nil *Counter records nothing.
func NewCounter ¶
NewCounter declares a counter on m. A nil m returns nil.
type Histogram ¶
type Histogram struct {
// contains filtered or unexported fields
}
Histogram is a histogram declared with label keys. A nil *Histogram records nothing.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package telemetrytest records the spans and metrics Nexus emits, so a test can assert on them without a Forge app.
|
Package telemetrytest records the spans and metrics Nexus emits, so a test can assert on them without a Forge app. |