Experimental OpenTelemetry Logs Bridge API for JavaScript providing TypeScript interfaces and no-op implementations for log backend integration.
npx @tessl/cli install tessl/npm-opentelemetry--api-logs@0.204.0OpenTelemetry API Logs is an experimental JavaScript/TypeScript library that provides the Logs Bridge API for OpenTelemetry. It enables logging library authors to build log appenders that bridge between existing logging libraries and the OpenTelemetry log data model. The package includes TypeScript interfaces, enums, no-op implementations, and proxy implementations for creating log backends that integrate with the OpenTelemetry ecosystem.
npm install @opentelemetry/api-logsimport {
logs,
Logger,
LoggerProvider,
LogRecord,
SeverityNumber,
NOOP_LOGGER,
NOOP_LOGGER_PROVIDER,
AnyValue,
AnyValueMap
} from "@opentelemetry/api-logs";For CommonJS:
const {
logs,
Logger,
LoggerProvider,
LogRecord,
SeverityNumber,
NOOP_LOGGER,
NOOP_LOGGER_PROVIDER,
AnyValue,
AnyValueMap
} = require("@opentelemetry/api-logs");import { logs, SeverityNumber } from "@opentelemetry/api-logs";
// Get the global logger provider
const provider = logs.getLoggerProvider();
// Create a logger
const logger = logs.getLogger("my-logger", "1.0.0");
// Create and emit a log record
logger.emit({
timestamp: Date.now() * 1000000, // nanoseconds
severityNumber: SeverityNumber.INFO,
severityText: "INFO",
body: "This is a log message",
attributes: {
"service.name": "my-service",
"custom.attribute": "value"
}
});The OpenTelemetry API Logs follows a layered architecture:
LogsAPI class manages global logger provider registration and provides access to loggersLoggerProvider interface creates and manages Logger instances with versioning and options supportLogger interface defines the core emit() method for log appenders to send log recordsProxyLogger and ProxyLoggerProvider enable lazy initialization and delegation to real implementationsCentral API for managing global logger providers and obtaining logger instances.
/**
* Global logs API singleton instance
*/
const logs: LogsAPI;
class LogsAPI {
/** Get the singleton LogsAPI instance */
static getInstance(): LogsAPI;
/** Set the global logger provider */
setGlobalLoggerProvider(provider: LoggerProvider): LoggerProvider;
/** Get the current global logger provider */
getLoggerProvider(): LoggerProvider;
/** Get a logger from the global provider */
getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
/** Remove the global logger provider */
disable(): void;
}Registry interface for creating and managing named loggers with versioning support.
interface LoggerProvider {
/**
* Returns a Logger, creating one if one with the given name, version, and
* options is not already created
*/
getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
}
interface LoggerOptions {
/** The schemaUrl of the tracer or instrumentation library */
schemaUrl?: string;
/** The instrumentation scope attributes to associate with emitted telemetry */
scopeAttributes?: Attributes;
/** Specifies whether the Trace Context should automatically be passed on to the LogRecords */
includeTraceContext?: boolean;
}Core interface that log appenders implement to emit log records.
interface Logger {
/**
* Emit a log record. This method should only be used by log appenders.
*/
emit(logRecord: LogRecord): void;
}Complete structure for representing log records with all OpenTelemetry log attributes.
interface LogRecord {
/** The unique identifier for the log record */
eventName?: string;
/** The time when the log record occurred as UNIX Epoch time in nanoseconds */
timestamp?: TimeInput;
/** Time when the event was observed by the collection system */
observedTimestamp?: TimeInput;
/** Numerical value of the severity */
severityNumber?: SeverityNumber;
/** The severity text */
severityText?: string;
/** A value containing the body of the log record */
body?: LogBody;
/** Attributes that define the log record */
attributes?: LogAttributes;
/** The Context associated with the LogRecord */
context?: Context;
}
type LogBody = AnyValue;
type LogAttributes = AnyValueMap;Standardized severity number enumeration following OpenTelemetry specification.
enum SeverityNumber {
UNSPECIFIED = 0,
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
}Type system for representing flexible log data including scalars, arrays, maps, and binary data.
type AnyValue =
| AnyValueScalar
| Uint8Array
| AnyValueArray
| AnyValueMap
| null
| undefined;
type AnyValueScalar = string | number | boolean;
type AnyValueArray = Array<AnyValue>;
interface AnyValueMap {
[attributeKey: string]: AnyValue;
}Types imported from @opentelemetry/api that are used in the API signatures.
// From @opentelemetry/api
interface Context {
// Context interface for associating log records with trace context
}
type TimeInput = number | Date;
interface Attributes {
[attributeKey: string]: AttributeValue | undefined;
}
type AttributeValue =
| string
| number
| boolean
| Array<null | undefined | string>
| Array<null | undefined | number>
| Array<null | undefined | boolean>;Safe fallback implementations for when no real logger provider is configured.
class NoopLogger implements Logger {
/** No-operation emit method */
emit(_logRecord: LogRecord): void;
}
class NoopLoggerProvider implements LoggerProvider {
/** Returns a NoopLogger instance */
getLogger(
_name: string,
_version?: string,
_options?: LoggerOptions
): Logger;
}
/** Singleton no-op logger instance */
const NOOP_LOGGER: NoopLogger;
/** Singleton no-op logger provider instance */
const NOOP_LOGGER_PROVIDER: NoopLoggerProvider;Proxy implementations that delegate to real implementations when available, falling back to no-ops.
class ProxyLogger implements Logger {
readonly name: string;
readonly version?: string;
readonly options?: LoggerOptions;
constructor(
provider: LoggerDelegator,
name: string,
version?: string,
options?: LoggerOptions
);
/** Emit a log record via delegate or no-op */
emit(logRecord: LogRecord): void;
}
class ProxyLoggerProvider implements LoggerProvider {
/** Get logger from delegate or create proxy */
getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
}
interface LoggerDelegator {
_getDelegateLogger(
name: string,
version?: string,
options?: LoggerOptions
): Logger | undefined;
}import { logs, LoggerProvider, Logger, LogRecord } from "@opentelemetry/api-logs";
// Custom logger provider implementation
class MyLoggerProvider implements LoggerProvider {
getLogger(name: string, version?: string): Logger {
return new MyLogger(name, version);
}
}
class MyLogger implements Logger {
constructor(private name: string, private version?: string) {}
emit(logRecord: LogRecord): void {
console.log(`[${this.name}${this.version ? `@${this.version}` : ''}]`, logRecord);
}
}
// Register the provider globally
logs.setGlobalLoggerProvider(new MyLoggerProvider());import { logs, SeverityNumber, LogRecord } from "@opentelemetry/api-logs";
class ConsoleLogAppender {
private logger = logs.getLogger("console-appender", "1.0.0");
logInfo(message: string, attributes?: Record<string, any>): void {
const logRecord: LogRecord = {
timestamp: Date.now() * 1000000, // Convert to nanoseconds
severityNumber: SeverityNumber.INFO,
severityText: "INFO",
body: message,
attributes: attributes || {}
};
this.logger.emit(logRecord);
}
logError(error: Error, attributes?: Record<string, any>): void {
const logRecord: LogRecord = {
timestamp: Date.now() * 1000000,
severityNumber: SeverityNumber.ERROR,
severityText: "ERROR",
body: error.message,
attributes: {
"error.name": error.name,
"error.stack": error.stack,
...attributes || {}
}
};
this.logger.emit(logRecord);
}
}
// Usage
const appender = new ConsoleLogAppender();
appender.logInfo("Application started", { "service.name": "my-app" });
appender.logError(new Error("Something went wrong"), { "user.id": "123" });import { logs, SeverityNumber, AnyValue } from "@opentelemetry/api-logs";
const logger = logs.getLogger("structured-logger");
// Log with complex structured data
const complexData: AnyValue = {
user: {
id: 123,
name: "Alice",
preferences: ["email", "sms"]
},
metrics: {
response_time: 234.5,
success: true
},
tags: ["auth", "api", "v2"]
};
logger.emit({
timestamp: Date.now() * 1000000,
severityNumber: SeverityNumber.INFO,
body: complexData,
attributes: {
"http.method": "POST",
"http.status_code": 200
}
});import { logs } from "@opentelemetry/api-logs";
// Check current provider
const currentProvider = logs.getLoggerProvider();
console.log("Current provider:", currentProvider);
// Set up a new provider
const myProvider = new MyLoggerProvider();
logs.setGlobalLoggerProvider(myProvider);
// Later, clean up
logs.disable(); // Removes global provider, falls back to no-op