Files
o11y/platform.go
zeekayandHanzo Dev cae99adb44 The relay reads the operation zip served
An op learns its address from zip.OpOf and zip.AddressOf, so the claim table,
the five declaring verbs and the address bookkeeping are gone. A host that
declares one of these addresses itself now gets a Build conflict from zip.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-17 15:02:30 -07:00

935 lines
35 KiB
Go

package o11y
// The PLATFORM face of the o11y product — instant queries, dashboard
// variables, product events, usage, the dependency graph, version/health,
// disks, first-user registration, retention and apdex settings, licenses,
// global config, feature flags, org stats, filter suggestions, k8s onboarding,
// metric metadata, span percentiles and query-filter analysis — as TYPED ops.
//
// These twenty-three routes reached traffic only through the /v1/o11y/*
// delegation wildcard, and a route behind a wildcard is in no document: no SDK
// method, no CLI command, no agent tool, no reference page. Typing them is
// what puts the operations in the document and therefore in every projection
// built from it.
//
// THE WIRE DOES NOT MOVE, the same way logs.go's nine reads and telemetry.go's
// five sentry reads do not move it: each op hands the call to the SAME runtime
// handler the wildcard delegates to, through the ONE shared seam relay (relay.go)
// — so identity resolution, the org gate, the role check (OpenAccess, ViewAccess
// and AdminAccess exactly as the mux tree declares them), the audit record and
// the success envelope are all still the runtime's, executed in the order they
// always were. What is new here is the TYPE — the In a caller may send and the
// Out they get back — and the prose that goes with it. This face is /v1/o11y,
// the same root as logs, and every face shares the one seam in relay.go
// rather than minting its own: one seam, not one per face.
//
// Registered ahead of the wildcard, and specific-beats-wildcard is what the
// router does regardless of registration order, so these paths dispatch here
// and every other path under the prefix still reaches the runtime untouched.
//
// The three service probes of this prefix — healthz, readyz, livez — are NOT
// here: they already dispatch natively through health.go's probe group, whose
// fall-through-when-unset behavior is load-bearing (health_test.go pins it),
// and a second registration of the same literals would only shadow it.
import (
"context"
"encoding/json"
"net/url"
"time"
"github.com/zap-proto/zip"
)
// mountPlatform registers the typed platform ops on the native router, in the
// order the mux tree declares them (routes_misc.go, routes_settings.go,
// routes_licenses.go, then the o11yapiserver singletons). It registers on the
// SAME o11yRoot group logs.go mounts on, ahead of the delegation wildcard.
func mountPlatform(app *zip.App) {
g := app.Group(o11yRoot)
// routes_misc.go
g.Get("/query", promQuery)
g.Post("/variables/query", dashboardVars)
g.Post("/event", event)
g.Get("/usage", usage)
g.Post("/dependency_graph", dependencyGraph)
g.Get("/version", version)
g.Get("/health", health)
g.Get("/disks", disks)
g.Post("/span_percentile", spanPercentile)
g.Post("/query_filter/analyze", analyzeQueryFilter)
g.Get("/filter_suggestions", filterSuggestions)
g.Get("/infra_onboarding/k8s/status", k8sOnboarding)
g.Get("/metric/metric_metadata", legacyMetricMetadata)
// routes_settings.go
g.Post("/settings/ttl", setRetention)
g.Get("/settings/ttl", retention)
g.Post("/settings/apdex", setApdex)
g.Get("/settings/apdex", apdex)
// routes_licenses.go
g.Get("/licenses", licenses)
g.Get("/licenses/active", activateLicense)
// o11yapiserver: global.go, flagger.go, statsreporter.go
g.Get("/global/config", globalConfig)
g.Get("/features", features)
g.Get("/stats", orgStats)
}
// ── the operations ────────────────────────────────────────────────────────────
// promQuery evaluates one instant PromQL query against the org's metrics and
// returns the result at a single point in time.
//
// The result is polymorphic by PromQL's own contract — a matrix, vector,
// scalar or string, discriminated by resultType — so it is carried verbatim
// rather than forced into one of its shapes.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func promQuery(ctx context.Context, in *O11yPromQueryIn) (*O11yPromQueryOut, error) {
out := new(O11yPromQueryOut)
return out, relay(ctx, query(
"query", in.Query,
"time", in.Time,
"stats", in.Stats,
"timeout", in.Timeout,
), nil, out)
}
// dashboardVars evaluates a dashboard variable query and returns the values the
// variable may take.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func dashboardVars(ctx context.Context, in *O11yDashboardVarsIn) (*O11yDashboardVarsOut, error) {
out := new(O11yDashboardVarsOut)
return out, relay(ctx, nil, in, out)
}
// event records one product-analytics event for the signed-in user — a track
// event with a name and free-form attributes.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func event(ctx context.Context, in *O11yEventIn) (*O11yMessage, error) {
out := new(O11yMessage)
return out, relay(ctx, nil, in, out)
}
// usage returns ingestion usage counts bucketed over the requested window,
// optionally narrowed to one service.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func usage(ctx context.Context, in *O11yUsageIn) (*O11yUsageList, error) {
out := new(O11yUsageList)
return out, relay(ctx, query(
"start", in.Start,
"end", in.End,
"step", in.Step,
"service", in.Service,
), nil, out)
}
// dependencyGraph returns the service dependency graph over the requested
// window: every parent→child edge observed, with call and error rates and
// latency percentiles per edge.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func dependencyGraph(ctx context.Context, in *O11yDependencyGraphIn) (*O11yDependencyList, error) {
out := new(O11yDependencyList)
return out, relay(ctx, nil, in, out)
}
// version reports the running build: its version, whether an enterprise
// edition is present ("N" in this build), and whether first-user setup has
// completed.
//
// Open by design; the runtime's own gate is OpenAccess.
func version(ctx context.Context, _ *struct{}) (*O11yVersionOut, error) {
out := new(O11yVersionOut)
return out, relay(ctx, nil, nil, out)
}
// health reports service health. With live set, the datastore connection is
// checked too and an unhealthy store refuses with 503.
//
// Open by design; the runtime's own gate is OpenAccess.
func health(ctx context.Context, in *O11yHealthIn) (*O11yHealthOut, error) {
out := new(O11yHealthOut)
p := url.Values{}
if in.Live {
// The runtime tests presence, not value.
p.Set("live", "true")
}
return out, relay(ctx, p, nil, out)
}
// disks lists the storage disks the datastore reports, with their names and
// types.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func disks(ctx context.Context, _ *struct{}) (*O11yDiskList, error) {
out := new(O11yDiskList)
return out, relay(ctx, nil, nil, out)
}
// spanPercentile places one span's duration among its peers: the p50/p90/p99
// durations of like spans, and the percentile the given duration lands at.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func spanPercentile(ctx context.Context, in *O11ySpanPercentileIn) (*O11ySpanPercentileOut, error) {
out := new(O11ySpanPercentileOut)
return out, relay(ctx, nil, in, out)
}
// analyzeQueryFilter analyzes a query and extracts the metric names it reads
// and the columns it groups by.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func analyzeQueryFilter(ctx context.Context, in *O11yAnalyzeIn) (*O11yAnalyzeOut, error) {
out := new(O11yAnalyzeOut)
return out, relay(ctx, nil, in, out)
}
// filterSuggestions suggests attribute keys and example filter queries for the
// query builder, seeded by what the org's own telemetry carries. Only the logs
// data source is supported today.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func filterSuggestions(ctx context.Context, in *O11yFilterSuggestionsIn) (*O11yFilterSuggestionsOut, error) {
out := new(O11yFilterSuggestionsOut)
return out, relay(ctx, query(
"dataSource", in.DataSource,
"searchText", in.SearchText,
"existingFilter", in.ExistingFilter,
"attributesLimit", in.AttributesLimit,
"examplesLimit", in.ExamplesLimit,
), nil, out)
}
// k8sOnboarding reports how far Kubernetes infra onboarding has progressed:
// which metric families have arrived and, per pod, which required metadata
// labels are present.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func k8sOnboarding(ctx context.Context, _ *struct{}) (*O11yOnboardingOut, error) {
out := new(O11yOnboardingOut)
return out, relay(ctx, nil, nil, out)
}
// legacyMetricMetadata serves the OLDER /metric/metric_metadata route. It is
// NOT the same op as metrics.go's metricMetadata (/metrics/metadata): different
// path, different input (this one also scopes by service). Two slices named one
// Go function for two routes; the route is the identity, so the name follows it.
// Renamed rather than merged — collapsing them would silently drop the service
// scope this one accepts.
// It returns one metric's metadata — its type, unit, description,
// temporality, monotonicity and histogram buckets — optionally scoped to the
// metric as one service reports it.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func legacyMetricMetadata(ctx context.Context, in *O11yMetricMetadataIn) (*O11yMetricMetadataOut, error) {
out := new(O11yMetricMetadataOut)
return out, relay(ctx, query(
"metricName", in.MetricName,
"serviceName", in.ServiceName,
), nil, out)
}
// setRetention sets the org's retention policy for one signal: the default TTL
// in days, ordered per-label retention rules, and optional cold-storage
// settings.
//
// Admin only, as the mux tree has always gated it (AdminAccess); the runtime's
// own gate enforces it.
func setRetention(ctx context.Context, in *O11yRetentionSetIn) (*O11yRetentionSetOut, error) {
out := new(O11yRetentionSetOut)
return out, relay(ctx, nil, in, out)
}
// retention returns the org's current retention policy: default TTL, custom
// per-label rules, and cold-storage settings where configured.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func retention(ctx context.Context, _ *struct{}) (*O11yRetentionOut, error) {
out := new(O11yRetentionOut)
return out, relay(ctx, nil, nil, out)
}
// setApdex sets one service's apdex threshold and the status codes excluded
// from its score.
//
// Admin only, as the mux tree has always gated it (AdminAccess); the runtime's
// own gate enforces it.
func setApdex(ctx context.Context, in *O11yApdexSetIn) (*O11yApdexSetOut, error) {
out := new(O11yApdexSetOut)
return out, relay(ctx, nil, in, out)
}
// apdex returns apdex settings for the named services.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func apdex(ctx context.Context, in *O11yApdexIn) (*O11yApdexOut, error) {
out := new(O11yApdexOut)
return out, relay(ctx, query(
"services", in.Services,
), nil, out)
}
// licenses lists the org's licenses. This build has no enterprise edition, so
// the list is intentionally empty.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func licenses(ctx context.Context, _ *struct{}) (*O11yLicensesOut, error) {
out := new(O11yLicensesOut)
return out, relay(ctx, nil, nil, out)
}
// activateLicense activates the enterprise license. This build has no
// enterprise edition, so the licensing provider refuses it as unsupported.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func activateLicense(ctx context.Context, _ *struct{}) (*O11yLicenseActiveOut, error) {
out := new(O11yLicenseActiveOut)
return out, relay(ctx, nil, nil, out)
}
// globalConfig returns the deployment's global configuration: its public
// endpoints and which identity providers are enabled. Open by design — the
// sign-in page reads it before anyone is signed in.
//
// Open by design; the runtime's own gate is OpenAccess.
func globalConfig(ctx context.Context, _ *struct{}) (*O11yGlobalConfigOut, error) {
out := new(O11yGlobalConfigOut)
return out, relay(ctx, nil, nil, out)
}
// features returns the supported feature flags and their resolved values for
// the caller's org.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func features(ctx context.Context, _ *struct{}) (*O11yFeaturesOut, error) {
out := new(O11yFeaturesOut)
return out, relay(ctx, nil, nil, out)
}
// orgStats returns the collected usage statistics for the caller's org, as the
// stats reporter aggregates them — a map whose keys are the reporter's own
// counter names.
//
// Callers need the viewer role; the runtime's own gate enforces it.
func orgStats(ctx context.Context, _ *struct{}) (*O11yOrgStatsOut, error) {
out := new(O11yOrgStatsOut)
return out, relay(ctx, nil, nil, out)
}
// ── inputs ────────────────────────────────────────────────────────────────────
//
// Every type here carries the O11y qualifier because these names enter a
// fleet-wide document, where one name may have exactly one shape. An operation
// that takes no input takes *struct{}, as logs.go's do.
// O11yPromQueryIn is one instant PromQL query.
type O11yPromQueryIn struct {
// Query is the PromQL expression to evaluate. Required.
Query string `json:"query" validate:"required"`
// Time is the evaluation timestamp — epoch seconds or RFC3339. Empty
// evaluates at now.
Time string `json:"time,omitempty"`
// Stats set to any non-empty value includes query statistics in the answer.
Stats string `json:"stats,omitempty"`
// Timeout caps evaluation time, as a duration in seconds.
Timeout string `json:"timeout,omitempty"`
}
// O11yDashboardVarsIn is one dashboard variable query.
type O11yDashboardVarsIn struct {
// Query is the variable query to evaluate. Required.
Query string `json:"query" validate:"required"`
// Variables are the current values of the other dashboard variables, for
// queries that reference them.
Variables map[string]any `json:"variables,omitempty"`
}
// O11yEventIn is one product-analytics event.
type O11yEventIn struct {
// EventType is the kind of event — track, identify or group. Required.
EventType string `json:"eventType" validate:"required"`
// EventName names the event; required for track events.
EventName string `json:"eventName,omitempty"`
// Attributes are free-form event properties.
Attributes map[string]any `json:"attributes,omitempty"`
// RateLimited marks an event the reporting client rate-limited.
RateLimited bool `json:"rateLimited,omitempty"`
}
// O11yUsageIn selects a usage window.
type O11yUsageIn struct {
// Start is the window start, as epoch nanoseconds. Required.
Start string `json:"start" validate:"required"`
// End is the window end, as epoch nanoseconds. Required.
End string `json:"end" validate:"required"`
// Step is the bucket width in seconds. The runtime requires it.
Step int `json:"step,omitempty"`
// Service narrows usage to one service. Empty covers all.
Service string `json:"service,omitempty"`
}
// O11yDependencyGraphIn selects the window the dependency graph is computed
// over.
type O11yDependencyGraphIn struct {
// Start is the window start, as epoch nanoseconds. Required.
Start string `json:"start" validate:"required"`
// End is the window end, as epoch nanoseconds. Required.
End string `json:"end" validate:"required"`
// Tags narrow the graph to spans matching every condition.
Tags []O11yTagFilter `json:"tags,omitempty"`
}
// O11yTagFilter is one span-tag condition.
type O11yTagFilter struct {
// Key is the tag to test.
Key string `json:"key"`
// TagType says which kind of value the tag holds: string, number or bool.
TagType string `json:"tagType"`
// StringValues are the values matched when the tag holds strings.
StringValues []string `json:"stringValues,omitempty"`
// BoolValues are the values matched when the tag holds booleans.
BoolValues []bool `json:"boolValues,omitempty"`
// NumberValues are the values matched when the tag holds numbers.
NumberValues []float64 `json:"numberValues,omitempty"`
// Operator is the comparison to apply — in, not_in, equals, contains and
// the other operators the trace filter grammar names.
Operator string `json:"operator"`
}
// O11yHealthIn selects how deep the health check goes.
type O11yHealthIn struct {
// Live also checks the datastore connection; an unreachable store refuses
// with 503.
Live bool `json:"live,omitempty"`
}
// O11ySpanPercentileIn names one span and the peer group to place it in.
type O11ySpanPercentileIn struct {
// SpanDuration is the span's duration in nanoseconds.
SpanDuration int64 `json:"spanDuration"`
// Name is the span name whose peers are compared. Required.
Name string `json:"name" validate:"required"`
// ServiceName is the service the span belongs to. Required.
ServiceName string `json:"serviceName" validate:"required"`
// ResourceAttributes narrow the peer group to spans carrying them all.
ResourceAttributes map[string]string `json:"resourceAttributes,omitempty"`
// Start is the window start, as epoch nanoseconds.
Start uint64 `json:"start"`
// End is the window end, as epoch nanoseconds.
End uint64 `json:"end"`
}
// O11yAnalyzeIn is one query to analyze.
type O11yAnalyzeIn struct {
// Query is the query text. Required.
Query string `json:"query" validate:"required"`
// QueryType says which language the query is in — promql or the datastore's
// SQL dialect. Required.
QueryType string `json:"queryType" validate:"required"`
}
// O11yFilterSuggestionsIn seeds the suggestion engine.
type O11yFilterSuggestionsIn struct {
// DataSource is the signal suggestions are drawn from; only logs is
// supported today. Required.
DataSource string `json:"dataSource" validate:"required"`
// SearchText narrows attribute suggestions to keys containing it.
SearchText string `json:"searchText,omitempty"`
// ExistingFilter is the current filter set, JSON base64url-encoded, so
// example queries build on it rather than repeat it.
ExistingFilter string `json:"existingFilter,omitempty"`
// AttributesLimit caps how many attribute keys come back.
AttributesLimit int `json:"attributesLimit,omitempty"`
// ExamplesLimit caps how many example queries come back.
ExamplesLimit int `json:"examplesLimit,omitempty"`
}
// O11yMetricMetadataIn names the metric to read.
type O11yMetricMetadataIn struct {
// MetricName is the metric to read.
MetricName string `json:"metricName"`
// ServiceName scopes the metadata to the metric as one service reports it.
ServiceName string `json:"serviceName,omitempty"`
}
// O11yRetentionSetIn is one signal's retention policy.
type O11yRetentionSetIn struct {
// Type is the signal the policy applies to — traces, metrics or logs.
Type string `json:"type"`
// DefaultTTLDays is the retention for data no rule matches, in days.
DefaultTTLDays int `json:"defaultTTLDays"`
// TTLConditions are ordered per-label rules; the first matching rule wins.
TTLConditions []O11yRetentionRule `json:"ttlConditions,omitempty"`
// ColdStorageVolume names the volume aged data moves to, when set.
ColdStorageVolume string `json:"coldStorageVolume,omitempty"`
// ColdStorageDurationDays is how old data must be before it moves, in days.
ColdStorageDurationDays int64 `json:"coldStorageDurationDays,omitempty"`
}
// O11yApdexSetIn is one service's apdex settings.
type O11yApdexSetIn struct {
// ServiceName is the service the threshold applies to.
ServiceName string `json:"serviceName"`
// Threshold is the satisfied-response time in seconds.
Threshold float64 `json:"threshold"`
// ExcludeStatusCodes are status codes excluded from the score, comma
// separated.
ExcludeStatusCodes string `json:"excludeStatusCodes"`
}
// O11yApdexIn names the services to read.
type O11yApdexIn struct {
// Services are the service names, comma separated.
Services string `json:"services,omitempty"`
}
// ── outputs ───────────────────────────────────────────────────────────────────
//
// Each Out is the runtime's answer NAMED, field for field, tag for tag —
// including the envelope the route has always answered with. Two envelopes
// exist on this face and each Out mirrors the one its route uses: the reads
// that answer {"status":"success","data":…} say so, the reads that answer the
// payload bare say that instead. The data field carries omitempty exactly where
// the runtime's render.Success does, so an empty answer renders to the same
// bytes on both sides. Nothing embeds, because the schema builder walks
// reflected fields and cannot name an embedded one; runtime types that embed
// (User, the global config) are written FLAT here in their exact wire order.
// O11yMessage is an acknowledgment: the message the runtime answered with.
type O11yMessage struct {
// Data is the acknowledgment message.
Data string `json:"data"`
}
// O11yPromQueryOut is an instant query result.
type O11yPromQueryOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the evaluation result.
Data O11yPromResult `json:"data"`
}
// O11yPromResult is a PromQL evaluation result.
type O11yPromResult struct {
// ResultType discriminates Result: matrix, vector, scalar or string.
ResultType string `json:"resultType"`
// Result is the result in PromQL's own wire shape for ResultType, carried
// verbatim.
Result json.RawMessage `json:"result"`
// Stats holds query statistics when the caller asked for them.
Stats json.RawMessage `json:"stats,omitempty"`
}
// O11yDashboardVarsOut is a dashboard variable's value set.
type O11yDashboardVarsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the values.
Data O11yDashboardVarValues `json:"data"`
}
// O11yDashboardVarValues are the values a dashboard variable may take.
type O11yDashboardVarValues struct {
// VariableValues are the values, in the order the query produced them.
VariableValues []any `json:"variableValues"`
}
// O11yUsageList is ingestion usage, one item per bucket, oldest first.
type O11yUsageList []O11yUsageItem
// O11yUsageItem is one usage bucket.
type O11yUsageItem struct {
// Time is the bucket start.
Time time.Time `json:"time,omitempty"`
// Timestamp is the bucket start, as epoch nanoseconds.
Timestamp uint64 `json:"timestamp"`
// Count is how many spans were ingested in the bucket.
Count uint64 `json:"count"`
}
// O11yDependencyList is the service dependency graph, one item per edge.
type O11yDependencyList []O11yDependency
// O11yDependency is one parent→child edge of the service graph.
type O11yDependency struct {
// Parent is the calling service.
Parent string `json:"parent"`
// Child is the called service.
Child string `json:"child"`
// CallCount is how many calls crossed the edge in the window.
CallCount uint64 `json:"callCount"`
// CallRate is calls per second.
CallRate float64 `json:"callRate"`
// ErrorRate is the percentage of calls that erred.
ErrorRate float64 `json:"errorRate"`
// P99 is the 99th-percentile call duration, in nanoseconds.
P99 float64 `json:"p99"`
// P95 is the 95th-percentile call duration, in nanoseconds.
P95 float64 `json:"p95"`
// P90 is the 90th-percentile call duration, in nanoseconds.
P90 float64 `json:"p90"`
// P75 is the 75th-percentile call duration, in nanoseconds.
P75 float64 `json:"p75"`
// P50 is the median call duration, in nanoseconds.
P50 float64 `json:"p50"`
}
// O11yVersionOut is the running build.
type O11yVersionOut struct {
// Version is the build version.
Version string `json:"version"`
// EE says whether an enterprise edition is present; "N" in this build.
EE string `json:"ee"`
// SetupCompleted says whether the first user has been created.
SetupCompleted bool `json:"setupCompleted"`
}
// O11yHealthOut is the health verdict.
type O11yHealthOut struct {
// Status is "ok".
Status string `json:"status"`
}
// O11yDiskList is the datastore's disks.
type O11yDiskList []O11yDisk
// O11yDisk is one storage disk.
type O11yDisk struct {
// Name is the disk's name.
Name string `json:"name,omitempty"`
// Type is the disk's type, e.g. local or s3.
Type string `json:"type,omitempty"`
}
// O11ySpanPercentileOut is a span's percentile placement.
type O11ySpanPercentileOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the placement.
Data O11ySpanPercentile `json:"data"`
}
// O11ySpanPercentile places one span among its peers.
type O11ySpanPercentile struct {
// Percentiles are the peer group's duration percentiles.
Percentiles O11yPercentiles `json:"percentiles"`
// Position is where the given duration lands.
Position O11yPercentilePosition `json:"position"`
}
// O11yPercentiles are duration percentiles, in nanoseconds.
type O11yPercentiles struct {
// P50 is the median.
P50 float64 `json:"p50"`
// P90 is the 90th percentile.
P90 float64 `json:"p90"`
// P99 is the 99th percentile.
P99 float64 `json:"p99"`
}
// O11yPercentilePosition is one duration's rank among its peers.
type O11yPercentilePosition struct {
// Percentile is the percentile the duration lands at.
Percentile float64 `json:"percentile"`
// Description says the same in words.
Description string `json:"description"`
}
// O11yAnalyzeOut is a query analysis.
type O11yAnalyzeOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the analysis.
Data O11yQueryFilterAnalysis `json:"data"`
}
// O11yQueryFilterAnalysis is what a query reads and groups by.
type O11yQueryFilterAnalysis struct {
// MetricNames are the metrics the query reads.
MetricNames []string `json:"metricNames"`
// Groups are the columns the query groups by.
Groups []O11yColumnInfo `json:"groups"`
}
// O11yColumnInfo is one grouping column.
type O11yColumnInfo struct {
// Name is the column's name.
Name string `json:"columnName"`
// Alias is the column's alias in the query, when it has one.
Alias string `json:"columnAlias"`
}
// O11yFilterSuggestionsOut is the query builder's suggestions.
type O11yFilterSuggestionsOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds the suggestions.
Data O11yFilterSuggestions `json:"data"`
}
// O11yFilterSuggestions are attribute keys worth filtering on and example
// queries built from them.
type O11yFilterSuggestions struct {
// Attributes are the suggested attribute keys.
Attributes []O11yAttributeKey `json:"attributes"`
// ExampleQueries are ready-to-run filter sets.
ExampleQueries []O11yFilterSet `json:"example_queries"`
}
// O11yAttributeKey is one telemetry attribute.
type O11yAttributeKey struct {
// Key is the attribute's name.
Key string `json:"key"`
// DataType is the attribute's value type — string, int64, float64 or bool.
DataType string `json:"dataType"`
// Type says where the attribute lives: tag or resource.
Type string `json:"type"`
// IsColumn marks an attribute materialized as its own column.
IsColumn bool `json:"isColumn"`
// IsJSON marks an attribute extracted from a JSON body.
IsJSON bool `json:"isJSON"`
}
// O11yFilterSet is one filter: conditions combined with one operator.
type O11yFilterSet struct {
// Operator combines the items — AND or OR.
Operator string `json:"op,omitempty"`
// Items are the conditions.
Items []O11yFilterItem `json:"items"`
}
// O11yFilterItem is one filter condition.
type O11yFilterItem struct {
// Key is the attribute tested.
Key O11yAttributeKey `json:"key"`
// Value is what it is tested against; its type follows the attribute's.
Value any `json:"value"`
// Operator is the comparison, e.g. =, !=, in, contains.
Operator string `json:"op"`
}
// O11yOnboardingOut is Kubernetes onboarding progress.
type O11yOnboardingOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the progress report.
Data O11yK8sOnboarding `json:"data"`
}
// O11yK8sOnboarding says which infra metric families have arrived.
type O11yK8sOnboarding struct {
// DidSendPodMetrics says whether pod metrics have arrived.
DidSendPodMetrics bool `json:"didSendPodMetrics"`
// DidSendNodeMetrics says whether node metrics have arrived.
DidSendNodeMetrics bool `json:"didSendNodeMetrics"`
// DidSendClusterMetrics says whether cluster metrics have arrived.
DidSendClusterMetrics bool `json:"didSendClusterMetrics"`
// IsSendingOptionalPodMetrics says whether optional pod metrics are
// flowing.
IsSendingOptionalPodMetrics bool `json:"isSendingOptionalPodMetrics"`
// IsSendingRequiredMetadata reports, per pod, which required metadata
// labels are present.
IsSendingRequiredMetadata []O11yPodOnboarding `json:"isSendingRequiredMetadata"`
}
// O11yPodOnboarding is one pod's metadata completeness.
type O11yPodOnboarding struct {
// ClusterName is the pod's cluster.
ClusterName string `json:"clusterName"`
// NodeName is the pod's node.
NodeName string `json:"nodeName"`
// NamespaceName is the pod's namespace.
NamespaceName string `json:"namespaceName"`
// PodName is the pod.
PodName string `json:"podName"`
// HasClusterName says whether the cluster label is present.
HasClusterName bool `json:"hasClusterName"`
// HasNodeName says whether the node label is present.
HasNodeName bool `json:"hasNodeName"`
// HasNamespaceName says whether the namespace label is present.
HasNamespaceName bool `json:"hasNamespaceName"`
// HasDeploymentName says whether the deployment label is present.
HasDeploymentName bool `json:"hasDeploymentName"`
// HasStatefulsetName says whether the statefulset label is present.
HasStatefulsetName bool `json:"hasStatefulsetName"`
// HasDaemonsetName says whether the daemonset label is present.
HasDaemonsetName bool `json:"hasDaemonsetName"`
// HasCronjobName says whether the cronjob label is present.
HasCronjobName bool `json:"hasCronjobName"`
// HasJobName says whether the job label is present.
HasJobName bool `json:"hasJobName"`
}
// O11yRetentionSetOut acknowledges a retention change.
type O11yRetentionSetOut struct {
// Message says what was done.
Message string `json:"message"`
}
// O11yRetentionOut is the org's retention policy.
type O11yRetentionOut struct {
// Version is the policy format version.
Version string `json:"version"`
// Status is the last TTL operation's state.
Status string `json:"status"`
// ExpectedLogsTTLHours is the pending logs TTL, in hours.
ExpectedLogsTTLHours int `json:"expected_logs_ttl_duration_hrs,omitempty"`
// ExpectedLogsMoveTTLHours is the pending logs cold-storage move TTL, in
// hours.
ExpectedLogsMoveTTLHours int `json:"expected_logs_move_ttl_duration_hrs,omitempty"`
// DefaultTTLDays is the retention for data no rule matches, in days.
DefaultTTLDays int `json:"default_ttl_days,omitempty"`
// TTLConditions are the ordered per-label rules; the first match wins.
TTLConditions []O11yRetentionRule `json:"ttl_conditions,omitempty"`
// ColdStorageVolume names the volume aged data moves to.
ColdStorageVolume string `json:"cold_storage_volume,omitempty"`
// ColdStorageTTLDays is how old data must be before it moves, in days.
ColdStorageTTLDays int `json:"cold_storage_ttl_days,omitempty"`
}
// O11yRetentionRule is one per-label retention rule.
type O11yRetentionRule struct {
// Conditions all have to hold for the rule to match.
Conditions []O11yRetentionMatch `json:"conditions"`
// TTLDays is the retention applied when it does, in days.
TTLDays int `json:"ttlDays"`
}
// O11yRetentionMatch is one label condition of a retention rule.
type O11yRetentionMatch struct {
// Key is the label to test.
Key string `json:"key"`
// Values are the label values the rule matches.
Values []string `json:"values"`
}
// O11yApdexSetOut acknowledges an apdex change.
type O11yApdexSetOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the acknowledgment.
Data O11yMessage `json:"data"`
}
// O11yApdexOut is the requested services' apdex settings.
type O11yApdexOut struct {
// Status is "success".
Status string `json:"status"`
// Data holds one settings row per service.
Data []O11yApdexSettings `json:"data,omitempty"`
}
// O11yApdexSettings is one service's apdex settings.
type O11yApdexSettings struct {
// ID is the settings row's id.
ID string `json:"id"`
// OrgID is the org the settings belong to.
OrgID string `json:"orgId"`
// ServiceName is the service.
ServiceName string `json:"serviceName"`
// Threshold is the satisfied-response time in seconds.
Threshold float64 `json:"threshold"`
// ExcludeStatusCodes are status codes excluded from the score, comma
// separated.
ExcludeStatusCodes string `json:"excludeStatusCodes"`
}
// O11yLicensesOut is the org's licenses — empty in this build, which has no
// enterprise edition.
type O11yLicensesOut struct {
// Status is "success".
Status string `json:"status"`
// Data are the licenses.
Data []any `json:"data,omitempty"`
}
// O11yLicenseActiveOut is the activated license, in the licensing provider's
// own shape.
type O11yLicenseActiveOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the license.
Data any `json:"data,omitempty"`
}
// O11yGlobalConfigOut is the deployment's global configuration.
type O11yGlobalConfigOut struct {
// Status is "success".
Status string `json:"status"`
// Data is the configuration.
Data O11yGlobalConfig `json:"data"`
}
// O11yGlobalConfig is the deployment's endpoints and identity providers, in
// the runtime's own wire order.
type O11yGlobalConfig struct {
// ExternalURL is the deployment's public URL.
ExternalURL string `json:"external_url"`
// IngestionURL is where telemetry is sent.
IngestionURL string `json:"ingestion_url"`
// MCPURL is the MCP endpoint, when one is exposed.
MCPURL *string `json:"mcp_url"`
// AIAssistantURL is the AI assistant endpoint, when one is exposed.
AIAssistantURL *string `json:"ai_assistant_url"`
// IdentN says which identity providers are enabled.
IdentN O11yIdentN `json:"identN"`
}
// O11yIdentN is the identity provider switchboard.
type O11yIdentN struct {
// Tokenizer is the token-based provider.
Tokenizer O11yToggle `json:"tokenizer"`
// APIKey is the API-key provider.
APIKey O11yToggle `json:"apikey"`
// Impersonation is the impersonation provider.
Impersonation O11yToggle `json:"impersonation"`
}
// O11yToggle is one on/off switch.
type O11yToggle struct {
// Enabled says whether the feature is on.
Enabled bool `json:"enabled"`
}
// O11yFeaturesOut is the supported feature flags.
type O11yFeaturesOut struct {
// Status is "success".
Status string `json:"status"`
// Data are the features.
Data []O11yFeature `json:"data,omitempty"`
}
// O11yFeature is one feature flag.
type O11yFeature struct {
// Name is the flag's name.
Name string `json:"name"`
// Kind is the flag's value kind, e.g. boolean.
Kind string `json:"kind"`
// Stage is the flag's lifecycle stage, e.g. stable.
Stage string `json:"stage"`
// Description says what the flag gates.
Description string `json:"description"`
// DefaultVariant is the variant used when nothing overrides it.
DefaultVariant string `json:"defaultVariant"`
// Variants are the flag's possible values, by variant name.
Variants map[string]any `json:"variants"`
// ResolvedValue is the value resolved for the caller's org.
ResolvedValue any `json:"resolvedValue"`
}
// O11yOrgStatsOut is the org's collected usage statistics.
type O11yOrgStatsOut struct {
// Status is "success".
Status string `json:"status"`
// Data are the statistics, keyed by the reporter's own counter names.
Data map[string]any `json:"data,omitempty"`
}