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 1–24 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'];