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) #
{
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();