OTLP Export

Send the counters and measurements the framework records to an OpenTelemetry collector, as OTLP over HTTP.

It aggregates in this process and sends on an interval rather than sending per event, because a request-per-metric would make the collector's load a copy of the application's. Counters go out with delta temporality, so each send carries what happened since the last one and a collector restart cannot double-count.

Attributes pass through b.observability's redactor before they leave, so a label that picked up a token or an address is scrubbed on the way out rather than at the collector, which is a different trust boundary and often a different company.

The response is read under a size cap, so a collector answering with something large does not become this process's memory.

b.otelExport.create(opts) #

stable0.5.16soc2
{
  endpoint:           string,   // OTLP/HTTP collector URL; required
  serviceName:        string,   // service.name on everything sent; required
  headers:            object,   // sent with each request, for collector auth
  intervalMs:         number,   // send interval; default 15000
  resourceAttributes: object,   // resource-level attributes
  scope:              object,   // instrumentation scope
  httpClient:         object,   // replaces b.httpClient as the transport
}

Open an exporter and answer the handle to feed it. The handle carries recordCounter(name, value, attrs?) for something that only goes up, recordObservation(name, value, attrs?) for a measured value, tapHandler, which is the shape b.observability.setTap takes so the framework's own events are exported without a per-call-site change, flush() to send now, close() to stop the interval and send what is held, and the bufferedCounters and bufferedObservations properties, which read how much is waiting.

endpoint and serviceName are required and refused when empty. headers carries whatever the collector authenticates with. resourceAttributes and scope label everything sent. httpClient replaces the transport, which is what a test drives instead of a socket.

var b = require("@blamejs/core");
var otel = b.otelExport.create({
  endpoint:    "https://collector.example/v1/metrics",
  serviceName: "orders-api",
  headers:     { authorization: "Bearer " + token },
});
b.observability.setTap(otel.tapHandler);
otel.recordCounter("orders.placed", 1, { region: "eu" });
await otel.close();

Last updated 2026-10-12T14:21:56.879Z by seeder.