VI Platform Services

Telemetry

An application spread across components and processes cannot be understood by reading one process’s output. A single request may pass through a gateway, three components, and two events. Understanding what happened requires the pieces to be connected.

The runtime executes every operation and carries every call, so it is in a position to observe all of it. Telemetry is that observation: logs, traces, and metrics produced by the platform, with the application adding what only it knows.

§Traces

Every operation runs within a span: a record of what ran, how long it took, and whether it failed. Spans that belong to one originating request share a trace.

The runtime creates spans without being asked:

  • a call between components produces a span on each side, and the difference between them is the time spent in transport;
  • publishing an event and handling it produce spans linked through the event, so a trace shows the fan-out from one commit to every receiver;
  • storage commands and outbound HTTP requests are recorded within the operation that made them.

A trace that enters the application from outside is continued, and the gateway returns its identifier with each response. The result is one connected picture of a request across the whole application, without instrumentation in business code.

An operation can add spans of its own around steps worth measuring:

const rate = await context.span('fetch rate', () => lookup(input.currency))

§Sampling

Recording every trace of a busy application is expensive. Whether a trace is recorded is decided once, where the trace begins, and that decision travels with it. A trace is therefore recorded whole or not at all; there are no partial traces missing the components that decided differently.

§Logs

An operation writes structured log entries through the context:

context.logs.info('Order approved', { total: order.total })

The entry is stamped with what the runtime knows: the component and operation that wrote it and the trace it belongs to. Every entry written while serving one request can be retrieved together, across components, even when the trace itself was not sampled.

Severity thresholds are set for the application and can be changed for individual components, so one component can be examined in detail while the rest stay quiet.

§Metrics

Traces describe individual requests. Metrics describe the system in aggregate: how many, how fast, how full.

The runtime records metrics for its own machinery: operations, calls, storage, the broker, the gateway. A component declares the business metrics that matter to it:

# orders/manifest.toa.yaml
telemetry:
  metrics:
    approvals:
      type: counter
      labels:
        channel: [web, app, partner]
context.metrics.approvals.add(1, { channel: input.channel })

Three kinds are available. A counter counts things that happen. A gauge reports a level at a moment. A histogram records a distribution, for values where the tail matters.

Metrics are declared, with the values each label may take, for a reason. The cost of a metric is the number of distinct series it produces, and an undeclared label can multiply that without limit. Declaration makes the cost visible and bounded where the metric is defined.

Metrics are not sampled. Every occurrence is counted, whatever happens to the trace it belongs to.

§Where it goes

Telemetry is exported in a standard, vendor-neutral format to whatever backends the Context names. Logs can also be written to the process’s output. The application’s code does not depend on the choice: the same operations run with telemetry sent to a local console or to a hosted service.

An unavailable backend never slows the application or prevents it from stopping. Telemetry that cannot be delivered is dropped, and the fact is reported once.

§What the application adds

The division of labor follows the rest of the runtime. The platform observes everything it carries out: timing, failures, and the paths between components. The application adds meaning: a log entry saying what was decided, a span around a step it considers significant, a metric for a business quantity.

Business code contains no exporters, no correlation identifiers, and no timing wrappers. What it does contain is the part of observability that is specific to the product.

Search
Search the documentation