js/opentelemetry/logs

js/opentelemetry/logs.ts

fino:opentelemetry/logs - logger providers, loggers, severities, and log records.

This module contains the public log signal API. Use it to emit structured log records, build records incrementally, override logger providers for scoped execution, and describe logs consumed by SDK processors and exporters.

The default severity is INFO with severity number 9. Emitted records capture active trace context when available. SDK processors may apply attribute count and value length limits before export; logger emission keeps explicit record fields intact.

import { LogRecordBuilder, SeverityNumber, getLoggerProvider } from 'fino:opentelemetry/logs';

const logger = getLoggerProvider().getLogger('orders');
logger.emitRecord(
  new LogRecordBuilder()
    .setSeverity('WARN', SeverityNumber.WARN)
    .setTextBody('slow order path'),
);

See OpenTelemetry logs: https://opentelemetry.io/docs/concepts/signals/logs/

Classes

class LogRecordBuilder {

Fluent builder that assembles a LogRecord field by field before emission.

Every setter mutates the in-progress record and returns this, so calls chain. The builder starts with an empty attribute map and no other fields; nothing is filled with defaults here — defaults are applied later when a Logger emits the built record. Use this when a log needs more than a body and attributes, such as an event name, a category, an explicit dropped-attribute count, or a trace context detached from the ambient one. Call build to snapshot the record, or hand the builder straight to Logger.emitRecord.

import { LogRecordBuilder, SeverityNumber, getLoggerProvider } from 'internal:opentelemetry/logs';

const record = new LogRecordBuilder()
  .setTextBody('cache miss')
  .setSeverity('WARN', SeverityNumber.WARN)
  .setAttributes({ key: 'user:7', region: 'us-east' })
  .setEventName('cache.miss')
  .build();

getLoggerProvider().getLogger('cache').emitRecord(record);

Constructors

constructor()

Creates an empty builder with an empty attribute map and no other fields set.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const builder = new LogRecordBuilder();

Methods

setBody(body: unknown): this

Sets the record body to any value, unchanged.

Use this when the body may be a string, number, boolean, or structured object and you do not want coercion; setTextBody and setJsonBody are intent-revealing variants.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setBody({ event: 'ping', ok: true });
setTextBody(body: string): this

Sets the record body to the string form of the given value.

The value is passed through String(), so non-string inputs are stringified. Use this for human-readable log messages.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setTextBody('user signed in');
setJsonBody(body: unknown): this

Sets the record body to a structured value, unchanged.

Behaves like setBody but signals intent that the body is structured JSON data rather than a text message.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setJsonBody({ orderId: 'ord_1', items: 3 });
setSeverity(severityText: string, severityNumber?: number): this

Sets the severity text and, optionally, the severity number.

When severityNumber is omitted the number field is cleared, letting the emitting logger apply its default (SeverityNumber.INFO). Passing an explicit number pins it. The text is stored as given, so callers control casing.

import { LogRecordBuilder, SeverityNumber } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setSeverity('ERROR', SeverityNumber.ERROR);
setAttribute(key: string, value: unknown): this

Sets a single attribute by key, replacing any previous value for that key.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setAttribute('http.status_code', 503);
setAttributes(attributes: Attributes): this

Merges a map of attributes into the record, overwriting duplicate keys.

A nullish argument is treated as an empty map. Existing attributes not present in the argument are kept.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setAttributes({ region: 'eu', shard: 4 });
setEventName(name: string): this

Sets the event name that identifies this record as a named event.

The value is coerced to a string. Event names typically follow a dotted namespace such as user.login.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setEventName('user.login');
setCategory(name: string): this

Sets the category name used to group related records.

The value is coerced to a string.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setCategory('auth');
setDroppedAttributesCount(count: number): this

Records how many attributes were dropped before this record was built.

The count is coerced with Number() and any non-numeric or NaN value becomes 0. Set this when you have already trimmed attributes upstream and want the loss reflected in the exported record.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setDroppedAttributesCount(3);
setContext(context: TraceContext | null | undefined): this

Attaches an explicit trace context, or clears it when given nullish/empty context.

Each of trace id, span id, trace flags, and baggage is set when present on the given context and deleted otherwise, so passing null or an empty object removes any previously set correlation fields. Use this to correlate a record with a specific span rather than the ambient one the logger would capture.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const b = new LogRecordBuilder().setContext({
  traceId: '5b8aa5a2d2c872e8321cf37308d69df2',
  spanId: '051581bf3cb55c13',
  traceFlags: 1,
});
build(): LogRecord

Snapshots the accumulated record into a plain LogRecord.

The returned record is a shallow copy with its own copied attribute map, so further mutation of the builder does not affect it. Only fields that were explicitly set are present; defaults are applied later at emission. The builder can be reused after build.

import { LogRecordBuilder } from 'internal:opentelemetry/logs';

const record = new LogRecordBuilder().setTextBody('done').build();

class Logger {

Emitter of log records for one instrumentation scope.

A logger holds its owning provider and normalized scope, and offers two ways to produce records: the convenience methods (debug/info/warn/error and the general emit), which take a body plus attributes; and emitRecord, which accepts a fully or partially built LogRecord for cases that need event names, categories, or an explicit timestamp. Both paths fill missing defaults, stamp the logger's scope and the provider's resource, and capture the active trace context so logs written inside a span are correlated with it.

Every record is published on the scope's severity-phase topics and on the shared otel:log:record topic. Construct loggers through LoggerProvider.getLogger rather than directly.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

const logger = getLoggerProvider().getLogger('worker');
logger.debug('job dequeued', { jobId: 'j-9' });
logger.error('job failed', { jobId: 'j-9', attempt: 3 });

Constructors

constructor(provider: LoggerProvider, scope: ScopeInfo)

Binds a logger to its provider and scope and prepares the shared record topic.

Called by LoggerProvider.getLogger; application code does not invoke this directly.

import { LoggerProvider } from 'internal:opentelemetry/logs';

const logger = new LoggerProvider().getLogger('scope.name');

Getters

get scope(): ScopeInfo

A defensive copy of this logger's instrumentation scope.

The returned object is safe to mutate; its attributes are also copied, so changes to it never affect records this logger emits.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

const logger = getLoggerProvider().getLogger('cache', '1.0.0');
const { name, version } = logger.scope;

Methods

emit(body: unknown, options: { severityText?: string; severityNumber?: number; attributes?: Attributes; } = {}): void

Emits a log record from a body and options, filling defaults and trace context.

The body may be any value — a string message or a structured object. When omitted, severityText defaults to 'INFO' and severityNumber to SeverityNumber.INFO. The timestamp is set to now, the logger's scope and the provider's resource are attached, and any active trace context (trace id, span id, trace flags, baggage) is captured. The record is published on the phase topic derived from the lowercased severityText (or 'emit' when none is given) and on the shared record topic.

import { getLoggerProvider, SeverityNumber } from 'internal:opentelemetry/logs';

const logger = getLoggerProvider().getLogger('auth');
logger.emit('token refreshed', {
  severityText: 'INFO',
  severityNumber: SeverityNumber.INFO,
  attributes: { 'user.id': 'u_7' },
});
emitRecord(builder: LogRecordBuilder | Partial<LogRecord>): void

Emits a pre-built or partial log record, preserving its explicit fields.

Accepts either a LogRecordBuilder (which is built first) or a partial LogRecord. Explicit fields on the record win; only missing ones are filled: schema version, severity text/number (default 'INFO' / SeverityNumber.INFO), timestamp, resource. The logger's scope always replaces any scope on the input. Trace correlation fields (trace id, span id, trace flags, baggage) fall back to the active trace context when not already set on the record. Optional fields (body, observedTimeUnixNano, eventName, categoryName, flags, droppedAttributesCount) are carried through only when present. The publish phase is the lowercased final severityText.

import { getLoggerProvider, LogRecordBuilder } from 'internal:opentelemetry/logs';

const logger = getLoggerProvider().getLogger('checkout');
logger.emitRecord(
  new LogRecordBuilder()
    .setEventName('order.placed')
    .setJsonBody({ orderId: 'ord_9', total: 42.5 })
    .setSeverity('INFO'),
);
debug(body: unknown, attributes: Attributes = {}): void

Emits a record at DEBUG severity (severity number 5).

Shorthand for emit with severityText: 'DEBUG'.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

getLoggerProvider().getLogger('db').debug('query executed', { rows: 12 });
info(body: unknown, attributes: Attributes = {}): void

Emits a record at INFO severity (severity number 9).

Shorthand for emit with severityText: 'INFO'.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

getLoggerProvider().getLogger('http').info('request handled', { status: 200 });
warn(body: unknown, attributes: Attributes = {}): void

Emits a record at WARN severity (severity number 13).

Shorthand for emit with severityText: 'WARN'.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

getLoggerProvider().getLogger('pool').warn('connection retry', { attempt: 2 });
error(body: unknown, attributes: Attributes = {}): void

Emits a record at ERROR severity (severity number 17).

Shorthand for emit with severityText: 'ERROR'.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

getLoggerProvider().getLogger('api').error('unhandled exception', { code: 'E_IO' });

class LoggerProvider extends BaseProvider {

Factory for Logger instances, carrying the resource that stamps every record they emit.

Extends BaseProvider, so a provider is constructed with a resource (or plain attributes) that identifies the emitting service; every logger it hands out attaches that resource to its records. A single provider is typically shared across a whole application and installed as the active provider via setLoggerProvider or runWithLoggerProvider.

import { LoggerProvider } from 'internal:opentelemetry/logs';
import { Resource } from 'internal:opentelemetry/common';

const provider = new LoggerProvider({ resource: new Resource({ 'service.name': 'api' }) });
const logger = provider.getLogger('api/http');
logger.info('server started');

Methods

getLogger(name: string, version?: string, options?: { schemaUrl?: string | null; attributes?: Attributes; droppedAttributesCount?: number; }): Logger

Returns a Logger bound to a named instrumentation scope.

The name is required and identifies the library or subsystem producing the logs; it drives the scoped topic names records are published on. The optional version and options (schema URL, scope attributes, dropped-attribute count) further qualify the scope. The scope is normalized before use, which trims the name and throws a TypeError if it is empty or whitespace-only.

import { LoggerProvider } from 'internal:opentelemetry/logs';

const provider = new LoggerProvider();
const logger = provider.getLogger('billing', '2.0.0', {
  schemaUrl: 'https://opentelemetry.io/schemas/1.31.0',
  attributes: { team: 'payments' },
});

Enums

enum SeverityNumber { TRACE = 1, TRACE2 = 2, TRACE3 = 3, TRACE4 = 4, DEBUG = 5, DEBUG2 = 6, DEBUG3 = 7, DEBUG4 = 8, INFO = 9, INFO2 = 10, INFO3 = 11, INFO4 = 12, WARN = 13, WARN2 = 14, WARN3 = 15, WARN4 = 16, ERROR = 17, ERROR2 = 18, ERROR3 = 19, ERROR4 = 20, FATAL = 21, FATAL2 = 22, FATAL3 = 23, FATAL4 = 24 }

Numeric severity levels from the OpenTelemetry log data model.

Each of the six named ranges (TRACE, DEBUG, INFO, WARN, ERROR, FATAL) spans four numeric values, from the base level to three increasingly urgent sub-levels, giving the 124 contiguous range the spec defines. Higher numbers are more severe. These values populate the severityNumber field of a LogRecord and pair with the free-form severityText; the number is what backends sort and threshold on, so prefer passing a member of this enum over a raw integer.

import { LogRecordBuilder, SeverityNumber } from 'internal:opentelemetry/logs';

const record = new LogRecordBuilder()
  .setSeverity('ERROR', SeverityNumber.ERROR)
  .setTextBody('payment declined')
  .build();

Functions

function applyLogLimits(log: LogRecord, limits: { attributeCountLimit?: number; attributeValueLengthLimit?: number; } = {}): LogRecord

Returns a log record with attribute count and value-length limits applied.

When neither limit is finite the original record is returned unchanged, so this is cheap to call unconditionally. Otherwise attributes beyond attributeCountLimit are dropped and string values longer than attributeValueLengthLimit are truncated; any newly dropped attributes are added to the record's droppedAttributesCount. Kept separate from logger emission so SDK processors can enforce limits at export time without changing what loggers produce.

import { applyLogLimits, LogRecordBuilder } from 'internal:opentelemetry/logs';

const record = new LogRecordBuilder()
  .setAttributes({ a: 1, b: 2, c: 'a very long string value' })
  .build();

const limited = applyLogLimits(record, {
  attributeCountLimit: 2,
  attributeValueLengthLimit: 8,
});

function getLoggerProvider(): LoggerProvider

Returns the active LoggerProvider for the current async context.

Resolves to the provider installed by an enclosing runWithLoggerProvider call if one is on the async-context stack; otherwise the process-wide default (set by setLoggerProvider, or the built-in provider at startup). This is the entry point most code uses to obtain a logger.

import { getLoggerProvider } from 'internal:opentelemetry/logs';

const logger = getLoggerProvider().getLogger('app');

function runWithLoggerProvider<R>(provider: LoggerProvider, fn: () => R): R

Runs a function with a scoped LoggerProvider visible to getLoggerProvider.

Installs provider in the async-context slot for the duration of fn, including across await boundaries, then restores the previous value. Returns whatever fn returns (its promise, if async). Use this to give a request, test, or child scope its own provider without mutating the global default.

import { LoggerProvider, runWithLoggerProvider, getLoggerProvider } from 'internal:opentelemetry/logs';

const scoped = new LoggerProvider();
await runWithLoggerProvider(scoped, async () => {
  getLoggerProvider().getLogger('req').info('handling request');
});

function runWithoutLoggerProvider<R>(fn: () => R): R

Runs a function with any scoped logger provider suppressed.

Clears the async-context slot for the duration of fn, so getLoggerProvider falls back to the process-wide default even when called inside an enclosing runWithLoggerProvider scope. Returns whatever fn returns.

import { runWithoutLoggerProvider, getLoggerProvider } from 'internal:opentelemetry/logs';

runWithoutLoggerProvider(() => {
  getLoggerProvider().getLogger('bootstrap').info('using default provider');
});

function setLoggerProvider(provider: LoggerProvider): void

Replaces the process-wide default LoggerProvider.

Affects every subsequent getLoggerProvider call that is not inside a runWithLoggerProvider scope. Typically called once at startup by the SDK after building a provider with the desired resource. To override a provider only for a bounded region, prefer runWithLoggerProvider.

import { LoggerProvider, setLoggerProvider } from 'internal:opentelemetry/logs';
import { Resource } from 'internal:opentelemetry/common';

setLoggerProvider(new LoggerProvider({ resource: new Resource({ 'service.name': 'api' }) }));

Interfaces

interface LogRecord {

The serialized shape of a single log record in the OpenTelemetry data model.

body holds the log payload (string or structured value). severityNumber is the numeric OTel severity (1–24) and severityText its label. When a log is emitted inside an active span the traceId/spanId/traceFlags are stamped for correlation, and baggage captures the active baggage. eventName marks the record as a semantic event rather than a free-form message.

import type { LogRecord } from 'internal:opentelemetry/common';

const log: LogRecord = {
  body: 'checkout completed',
  severityNumber: 9,
  severityText: 'INFO',
};

Properties

schemaVersion?: number

schemaVersion property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['schemaVersion'];
body?: unknown

body property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['body'];
severityText?: string

severityText property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['severityText'];
severityNumber?: number

severityNumber property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['severityNumber'];
timeUnixNano?: number

timeUnixNano property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['timeUnixNano'];
observedTimeUnixNano?: number

observedTimeUnixNano property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['observedTimeUnixNano'];
attributes?: Attributes

attributes property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['attributes'];
droppedAttributesCount?: number

droppedAttributesCount property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['droppedAttributesCount'];
scope?: ScopeInfo

scope property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['scope'];
resource?: Resource

resource property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['resource'];
traceId?: string

traceId property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['traceId'];
spanId?: string

spanId property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['spanId'];
traceFlags?: number

traceFlags property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['traceFlags'];
baggage?: Baggage | null

baggage property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['baggage'];
eventName?: string

eventName property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['eventName'];
categoryName?: string

categoryName property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['categoryName'];
flags?: number

flags property on LogRecord.

Omitted optional values default to undefined; required values are expected from the producer before the record is exported or published. Consumers should tolerate missing optional fields in telemetry payloads.

let value: LogRecord['flags'];