runnertelemetry

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package runnertelemetry accepts the metrics and logs a distributed runner ships, and forwards them to the cluster's VictoriaMetrics and VictoriaLogs.

It exists so that neither of those ever has to listen anywhere a runner can reach. Open-source VictoriaMetrics and VictoriaLogs have no authentication of their own, so historically the only thing standing between a runner's network and unauthenticated write access to both was a firewall rule. Runners already hold a certificate from Join and already talk to the coordinator over an authenticated listener, so routing telemetry through that listener lets both stay bound to loopback permanently.

Index

Constants

View Source
const (
	// Audience scopes a telemetry token to this service. A system workload may
	// legitimately call several services, so the token it presents here must
	// name this one; sharing an audience with, say, the registry would make a
	// token minted for one replayable against the other.
	Audience = "miren-telemetry"

	// TokenHeader carries the runner's system workload token.
	//
	// Deliberately not Authorization. On a cloud-registered cluster the RPC
	// listener's authenticator tries the cloud JWT validator first whenever an
	// Authorization header is present, and a validation failure there returns a
	// hard error rather than falling through to the certificate check below it
	// (see pkg/cloudauth/rpc_authenticator.go). A cluster-issued workload token
	// is not a cloud JWT and would fail that validator, so putting it in
	// Authorization would turn an otherwise-valid mTLS request into a 401. A
	// header the authenticator ignores keeps the two credentials independent.
	TokenHeader = "Miren-Workload-Token"

	// MetricsBasePath and LogsBasePath are what a runner points its writers at.
	// Each writer appends its own backend-native suffix, so the bytes on the
	// wire are exactly what VictoriaMetrics and VictoriaLogs already accept and
	// this package never has to understand the payloads.
	MetricsBasePath = "/_telemetry/metrics"
	LogsBasePath    = "/_telemetry/logs"
)

Variables

View Source
var (
	MetricsPattern = http.MethodPost + " " + MetricsBasePath + metricsImportPath
	LogsPattern    = http.MethodPost + " " + LogsBasePath + logsInsertPath
)

MetricsPattern and LogsPattern are the ServeMux patterns these handlers mount on.

They pin an exact path and method rather than proxying everything beneath a prefix. A prefix would hand a runner the rest of both APIs, including reads and VictoriaMetrics' delete-series admin endpoint, which would make scoping the token pointless: the credential would say "may write telemetry" while the route said "may do anything."

View Source
var ErrIssuerUnavailable = errors.New("workload identity issuer unavailable")

ErrIssuerUnavailable means telemetry cannot be shipped because no workload issuer has been wired up yet, or the coordinator has none.

Functions

func LogsURL

func LogsURL(coordinatorAddress string) string

func MetricsURL

func MetricsURL(coordinatorAddress string) string

MetricsURL and LogsURL are what a runner points its writers at. Each writer appends its own backend-native suffix.

func NewLogsHandler

func NewLogsHandler(log *slog.Logger, verifier Verifier, address string) http.Handler

NewLogsHandler forwards accepted batches to VictoriaLogs' JSON-lines insert endpoint. address is the backend's host:port, normally loopback.

func NewMetricsHandler

func NewMetricsHandler(log *slog.Logger, verifier Verifier, address string) http.Handler

NewMetricsHandler forwards accepted batches to VictoriaMetrics' Prometheus import endpoint. address is the backend's host:port, normally loopback.

Types

type Client

type Client struct {
	// HTTP is what the telemetry writers are constructed with.
	HTTP *http.Client
	// contains filtered or unexported fields
}

Client is the HTTP client a runner's telemetry writers send through, paired with the QUIC transport underneath it.

The transport is held rather than left anonymous so it can be closed. The writers only ever need HTTP, but something has to own the QUIC connections, and without a handle on them they stay open until the process exits.

func NewClient

func NewClient(cfg ClientConfig) (*Client, error)

NewClient builds the client a runner's telemetry writers send through: HTTP/3 to the coordinator, authenticated by the runner's certificate, with a scoped workload token on every request.

HTTP/3 is not a preference. The coordinator's authenticated listener is QUIC only, so a plain net/http client cannot reach it at all.

func (*Client) Close

func (c *Client) Close() error

Close tears down the underlying QUIC connections.

type ClientConfig

type ClientConfig struct {
	// ClientCertPEM and ClientKeyPEM are the runner's certificate from Join.
	// The listener requires one, so telemetry rides the same mutual TLS as the
	// rest of the runner's traffic and the token narrows what that identity may
	// do rather than replacing it.
	ClientCertPEM []byte
	ClientKeyPEM  []byte

	// CACertPEM verifies the coordinator.
	CACertPEM []byte

	// TokenSource supplies the system workload token.
	TokenSource TokenSource

	// Timeout bounds a single telemetry request.
	Timeout time.Duration
}

ClientConfig describes how a runner reaches its coordinator's ingest endpoints.

type IssuerTokenSource

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

IssuerTokenSource mints telemetry tokens through a workload issuer, holding each one until shortly before it expires.

Its issuer arrives late on purpose. A runner's telemetry writers are built before the runner connects to the coordinator, but the issuer is a remote one that only exists once that connection is up, so the writers are handed this and the issuer is set behind them. Until that happens Token fails rather than returning something unusable, which surfaces as a telemetry send failure instead of a silent gap.

func NewIssuerTokenSource

func NewIssuerTokenSource() *IssuerTokenSource

func (*IssuerTokenSource) SetIssuer

func (s *IssuerTokenSource) SetIssuer(issuer workloadidentity.TokenIssuer)

SetIssuer supplies the issuer once the runner has one. Passing nil leaves the source unarmed, which is the honest state when the coordinator reports it has no issuer configured.

func (*IssuerTokenSource) Token

func (s *IssuerTokenSource) Token() (string, error)

type TokenSource

type TokenSource interface {
	Token() (string, error)
}

TokenSource supplies the system workload token a telemetry request carries.

type Verifier

type Verifier interface {
	VerifySystemWorkloadToken(token, audience string, workload workloadidentity.SystemWorkload) (*workloadidentity.WorkloadClaims, error)
}

Verifier checks that a presented token really identifies the telemetry writer of a runner in this cluster. It is satisfied by *workloadidentity.Issuer, which verifies in-process against the signing keys it already holds.

Jump to

Keyboard shortcuts

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