Documentation
¶
Overview ¶
Package telemetry is ynf's side of ynr's OpenTelemetry contract (ADR-011; ynr ADR-002, 003, 004 and 006). It sets up the official SDK once at process start, writes where the contract says, names everything from the registry in telemetry/registry, and never changes what ynf prints or how it exits: its errors are swallowed and counted.
Index ¶
- Constants
- Variables
- func Call[V any](ctx context.Context, t *T, system, operation string, ...) (V, error)
- func Command(ctx context.Context, c *exec.Cmd)
- func Environ(ctx context.Context, environ []string) []string
- func Finish(span trace.Span, outcome string, attrs ...attribute.KeyValue)
- func FromEnviron(ctx context.Context, environ []string) context.Context
- func FromHeaders(ctx context.Context, h http.Header) context.Context
- func Handle(host, login string) string
- func IDs(span trace.Span) (traceID, spanID string)
- func Inject(ctx context.Context, env map[string]string)
- func Intake(ctx context.Context) (trace.SpanContext, bool)
- func LaptopSpool(env map[string]string) string
- func LinkTo(traceID, spanID string) (trace.Link, bool)
- func Result(err error) string
- func Scrub(s string) string
- func Status(outcome string) codes.Code
- func Swallowed() int64
- func Tee(primary slog.Handler, t *T) slog.Handler
- func Transport(next http.RoundTripper) http.RoundTripper
- func WithIntake(ctx context.Context, span trace.Span) context.Context
- type Choice
- type Mode
- type Options
- type Settings
- type T
- func (t *T) Active() bool
- func (t *T) Choice() Choice
- func (t *T) Context(ctx context.Context) context.Context
- func (t *T) Event(ctx context.Context, name string, attrs ...attribute.KeyValue)
- func (t *T) LeaseExpired(ctx context.Context, lane string)
- func (t *T) RunFinished(ctx context.Context, outcome, lane, model string, u Usage)
- func (t *T) Shutdown(ctx context.Context)
- func (t *T) Tracer() trace.Tracer
- type Usage
Constants ¶
const ( // The work item's store key (ADR-002). Never on a metric. AttrItemKey = "ynf.item.key" // The step's id, which names its side effects (ADR-005). Never on a metric. AttrStepID = "ynf.step.id" // The run's id, the step id and the run's number within the step. Never on a metric. AttrRunID = "ynf.run.id" // The lane's id: where the lane is defined, host first, then its name, or the lane's own explicit id. ynr stamps it on a run's records from ynf's run manifest, on ynf's behalf. AttrLane = "ynf.lane" // The harness the run actually used, so a repository that overrides a lane shows as a variant of the same factory. ynr stamps it from ynf's run manifest, on ynf's behalf. AttrLaneHarness = "ynf.lane.harness" // The focus the run actually used. ynr stamps it from ynf's run manifest, on ynf's behalf. AttrLaneFocus = "ynf.lane.focus" // The SHA-256 of the lane's normalised form, recorded with every decision (ADR-006). AttrPolicyHash = "ynf.policy.hash" // The epoch of the lease the step holds (ADR-005). AttrLeaseEpoch = "ynf.lease.epoch" // The repository the work's code goes to, in ynf's host-first form. AttrRepo = "ynf.repo" // The state the decision left the item in (ADR-006). AttrItemState = "ynf.item.state" // The kind of action a decision asked for (ADR-006). AttrAction = "ynf.action" // ynf's own outcome for a unit of work, which also sets the span's status. AttrOutcome = "ynf.outcome" // What ynf did with a CloudEvent it received. AttrIntakeResult = "ynf.intake.result" // The other system a call went to. AttrCallSystem = "ynf.call.system" // What the call did, such as pull_request or push. Never a name or text from the system. AttrCallOperation = "ynf.call.operation" // Which tokens a count is of. AttrTokenType = "ynf.token.type" // What kind of actor the handle in user.name names. AttrActorKind = "ynf.actor.kind" // Whether a lane control paused the lane (true) or resumed it (false). AttrPaused = "ynf.paused" AttrCloudeventsEventID = "cloudevents.event_id" AttrCloudeventsEventSource = "cloudevents.event_source" AttrCloudeventsEventSubject = "cloudevents.event_subject" AttrCloudeventsEventType = "cloudevents.event_type" AttrGenAiResponseModel = "gen_ai.response.model" AttrVcsRepositoryURLFull = "vcs.repository.url.full" )
Attribute names: ynf's own, then the OpenTelemetry attributes it uses.
const ( // One step on one item (ADR-001), the root of the step's trace. SpanStep = "ynf.step" // Taking the item's lease. SpanClaim = "ynf.claim" // Reading the facts a decision needs from the ticket and the forge. SpanProbe = "ynf.probe" // The decider reading the item, the facts and the lane, and what it chose. SpanDecide = "ynf.decide" // One action a decision asked for. SpanAct = "ynf.act" // One run of a lane's runner on a worktree. SpanRun = "ynf.run" // A CloudEvent ynf received, recorded so a step can link to it (ynr ADR-003). SpanIntake = "ynf.intake" // A call out to another system: a forge, a tracker, git, ynm, docker or an executor. SpanCall = "ynf.call" // A person pausing or resuming a lane. SpanLaneControl = "ynf.lane.control" )
Span names.
const ( // A step began. A start with no matching span is how a crash shows. EventStepStarted = "ynf.step.started" // A run began. EventRunStarted = "ynf.run.started" // The decider chose. Its reasoning is in ynf's store, never in telemetry. EventDecisionMade = "ynf.decision.made" // A CloudEvent ynf received, written once inside its ynf.intake span: the one-way mirror of the control plane into telemetry. Nothing in ynf reads telemetry. EventIntakeReceived = "ynf.intake.received" )
Event names.
const ( // Runs, by outcome, lane and model. MetricRunCount = "ynf.run.count" // Tokens runs used, by model and kind, as the runner reports them. MetricRunTokens = "ynf.run.tokens" // What runs cost, by model, as the runner reports it. ynf never prices tokens itself. MetricRunCost = "ynf.run.cost" // Leases found expired when a step claimed the item, so a holder died or stalled. MetricLeaseExpired = "ynf.lease.expired" )
Metric names.
const ( // A run: the lane's sensors passed. OutcomeConverged = "converged" // A run: a cap ended it. OutcomeBudget = "budget" // A run: it stopped making progress. OutcomeStuck = "stuck" // A run: it changed what it must not. OutcomeTamper = "tamper" // A run: the operator's setup refused or broke it. OutcomeOperatorError = "operator_error" // A run: ynf or the runner failed. OutcomeError = "error" // A run: it was stopped. OutcomeAborted = "aborted" // A step: it ran to the point the item waits. OutcomeCompleted = "completed" // A step, phase or call: it ended in an error. OutcomeFailed = "failed" // A step: its lease was lost, so it stopped. OutcomeLost = "lost" // A step or claim: another instance holds the item. OutcomeHeld = "held" // A claim: the lease was taken. OutcomeClaimed = "claimed" // A phase or call: it succeeded. OutcomeOk = "ok" // An intake: the event was taken in. OutcomeAccepted = "accepted" // An intake: the event had been received before. OutcomeDeduplicated = "deduplicated" // An intake: the event was refused. OutcomeRejected = "rejected" )
Values of ynf.outcome.
const ( // The event was taken in. IntakeResultAccepted = "accepted" // The event had been received before. IntakeResultDeduplicated = "deduplicated" // The event was refused. IntakeResultRejected = "rejected" )
Values of ynf.intake.result.
const ( // A forge, such as GitHub. CallSystemForge = "forge" // A tracker. CallSystemTracker = "tracker" // Git, on the host. CallSystemGit = "git" // ynm, ynf's memory. CallSystemYnm = "ynm" // Docker, where an agent image is made. CallSystemDocker = "docker" // The executor that runs a lane's command. CallSystemExecutor = "executor" // ynh, where it builds an agent image. CallSystemYnh = "ynh" )
Values of ynf.call.system.
const ( // Input tokens. TokenTypeInput = "input" // Output tokens. TokenTypeOutput = "output" // Tokens read from a cache. TokenTypeCacheRead = "cache_read" )
Values of ynf.token.type.
const ( // A person. ActorKindHuman = "human" // Another automation. ActorKindBot = "bot" // ynf itself. ActorKindYnf = "ynf" )
Values of ynf.actor.kind.
const Service = "ynf"
Service is the name ynf's records carry as service.name, which with the version identifies its registry (ynr ADR-007).
Variables ¶
var CardinalityLimits = map[string]int{
"gen_ai.response.model": 50,
"ynf.lane": 100,
"ynf.outcome": 20,
"ynf.token.type": 3,
}
CardinalityLimits is the most distinct values each metric attribute may take, from the registry's ynr.cardinality annotations.
Functions ¶
func Call ¶
func Call[V any](ctx context.Context, t *T, system, operation string, fn func(context.Context) (V, error), benign ...error) (V, error)
Call spans a call out to another system (ynr ADR-006, rule 6): a child span of the work that made it, with the system and the operation, and an outcome from err. An error in benign, such as a not-found that is an answer, is a success. The error's text never reaches the span.
func Command ¶
Command gives a process ynf is about to start the trace context of ctx in its environment (ynr ADR-006, rule 4), keeping the environment it would have had. It does nothing when ctx carries no trace, so with telemetry off and no parent the process inherits exactly as before.
func Environ ¶
Environ is environ with the trace context of ctx set, replacing any the parent gave, for a process ynf starts. It returns environ unchanged when ctx carries no trace.
func Finish ¶
Finish ends a unit of work's span with ynf's own outcome as an attribute and the span's status set from it (ynr ADR-006, rule 11). A failure carries the outcome as its status description, never an error's text, which could hold content.
func FromEnviron ¶
FromEnviron joins the trace a parent gave this process: TRACEPARENT and TRACESTATE in environ. With none, ctx is returned as it is, and the first span starts a trace.
func FromHeaders ¶
FromHeaders joins the trace a client sent in W3C trace-context headers, for a request ynf serves (ynr ADR-006, rule 3).
func Handle ¶
Handle is a person as telemetry names them: the handle they have in the system where they acted, qualified by that system's host, such as github.com/octocat. It is "" for a login that is empty or looks like an email address or a name with spaces, since those are never exported.
func IDs ¶
IDs are the trace and span ids of span, as lowercase hex, to keep on an item so a later step can link to it from another process. A span nobody records, such as a no-op provider's, has none: what it carries is its parent's.
func Inject ¶
Inject sets TRACEPARENT and, when there is one, TRACESTATE in env from the span in ctx, for a process ynf starts (ynr ADR-006, rule 4). It leaves env alone when ctx carries no trace.
func Intake ¶
func Intake(ctx context.Context) (trace.SpanContext, bool)
Intake is the span context WithIntake noted in ctx.
func LaptopSpool ¶
LaptopSpool is the laptop's default spool folder: $XDG_STATE_HOME/ynr/spool/local, with ~/.local/state when XDG_STATE_HOME is not set to an absolute path. It is "" when there is no home to resolve.
func LinkTo ¶
LinkTo is a span link to the span with these ids, or false when they are not a span's.
func Status ¶
Status is the span status an outcome gives. A step another instance holds is neither a success nor an error, so it is left unset.
func Swallowed ¶
func Swallowed() int64
Swallowed is how many errors the SDK raised that ynf did not show.
func Tee ¶
Tee sends every record to primary, as it would go anyway, and a copy to ynf's OpenTelemetry logs. What primary writes is byte for byte what it wrote without the copy: the copy is made after it and its errors are not returned. It sends the copy only for records primary would write, so the level people chose applies to both. With no telemetry to write to, it returns primary itself.
func Transport ¶
func Transport(next http.RoundTripper) http.RoundTripper
Transport is an http.RoundTripper that sends the W3C trace-context headers of the request's context. It is for calls to the eyelock tools (ynh, ynm, ynf, ynr), as ynr ADR-006 rule 4 has it: trace context goes only to the processes ynf spawns and to those tools, never to third parties such as forges, trackers or model APIs. Today ynf uses it for its calls to ynm.
Types ¶
type Choice ¶
Choice is where telemetry goes, and for a spool, which folder.
func Choose ¶
Choose picks where to write, in the contract's order (ynr ADR-006, rule 1): the operator's OTEL_EXPORTER_OTLP_* if any is set; otherwise the spool, if YNR_SPOOL names a folder or the laptop default, $XDG_STATE_HOME/ynr/spool/local (XDG's default is ~/.local/state), exists; otherwise nothing. When ynf writes to the spool itself it writes into the folder named, not a subfolder of it. environ is the environment, as os.Environ gives it.
func ChooseWith ¶
ChooseWith is Choose with ynf's own configuration. With a spool root configured and the collector on, ynf writes to the spool whatever the operator set; with a root and no collector the operator's endpoint still wins, as the contract says, and otherwise the root's factory/ folder is where ynf writes, ahead of YNR_SPOOL and the laptop default.
type Mode ¶
type Mode string
Mode is where telemetry goes.
const ( ModeOTLP Mode = "otlp" // the operator's OTEL_EXPORTER_OTLP_*, over the network ModeSpool Mode = "spool" // OTLP JSON lines in a spool folder, which ynr serve reads ModeNone Mode = "none" // the SDK's no-op providers: nothing is written )
The modes, in the order Choose tries them (ynr ADR-004).
type Options ¶
type Options struct {
// Version is service.version: ynf's own.
Version string
// Environ is the environment the choice and the resource are read from; default os.Environ.
Environ []string
// Watch is for a long-lived process, such as serve: when no spool was found it looks again
// once a minute, so one that starts after ynf is still found.
Watch bool
// WatchEvery is how often Watch looks; default a minute.
WatchEvery time.Duration
// Spool is ynf's own configuration of where it writes: the spool root, and the collector.
Spool Settings
// FlushTimeout bounds the flush at exit; default 2 seconds.
FlushTimeout time.Duration
}
Options configures Setup.
type Settings ¶
type Settings struct {
// Root is the spool root. When it is set, ynf writes its own telemetry to factory/ under it.
Root string
// Collector is true when ynf starts ynr serve for the job. The spool then wins over the
// operator's OTEL_EXPORTER_OTLP_*, which ynr serve ships to instead (ynr ADR-004).
Collector bool
}
Settings are ynf's own configuration of where it writes (ADR-009): the spool root, and whether the collector is on.
type T ¶
type T struct {
// contains filtered or unexported fields
}
T is a process's telemetry. Every method is safe on a nil T, which writes nothing.
func Setup ¶
Setup sets up telemetry once, at process start, choosing where to write by Choose. Call Shutdown at exit.
func (*T) Active ¶
Active reports whether telemetry is being written, or may be soon: the spans, calls and copies of log records are worth making. When it is not, ynf does exactly what it did before.
func (*T) Context ¶
Context joins the trace this process was given, in TRACEPARENT and TRACESTATE (ynr ADR-006, rule 3). With none, ctx is returned as it is and the first span starts a trace.
func (*T) Event ¶
Event writes an event: a log record with an event name, correlated to the span in ctx, so it is inside that span's unit of work. The attributes are names from the registry.
func (*T) LeaseExpired ¶
LeaseExpired counts a lease found expired when a step claimed its item: its holder died or stalled.
func (*T) RunFinished ¶
RunFinished counts a finished run: by outcome, lane and model, with what it spent by model. The attributes are the low-cardinality ones the registry names, never an item key or a run id.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Command gen writes internal/telemetry/names.go from telemetry/registry, ynf's Weaver registry.
|
Command gen writes internal/telemetry/names.go from telemetry/registry, ynf's Weaver registry. |
|
Package registry reads ynf's telemetry registry (telemetry/registry), an OpenTelemetry Weaver registry, and writes the Go constants generated from it.
|
Package registry reads ynf's telemetry registry (telemetry/registry), an OpenTelemetry Weaver registry, and writes the Go constants generated from it. |
|
Package spooltest reads a spool folder back, for tests that prove what ynf wrote: the OTLP JSON lines of every file in it, parsed into spans, events, log records and metric points.
|
Package spooltest reads a spool folder back, for tests that prove what ynf wrote: the OTLP JSON lines of every file in it, parsed into spans, events, log records and metric points. |