0
# OpenTelemetry API Logs
1
2
OpenTelemetry 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.
3
4
## Package Information
5
6
- **Package Name**: @opentelemetry/api-logs
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @opentelemetry/api-logs`
10
11
## Core Imports
12
13
```typescript
14
import {
15
logs,
16
Logger,
17
LoggerProvider,
18
LogRecord,
19
SeverityNumber,
20
NOOP_LOGGER,
21
NOOP_LOGGER_PROVIDER,
22
AnyValue,
23
AnyValueMap
24
} from "@opentelemetry/api-logs";
25
```
26
27
For CommonJS:
28
29
```javascript
30
const {
31
logs,
32
Logger,
33
LoggerProvider,
34
LogRecord,
35
SeverityNumber,
36
NOOP_LOGGER,
37
NOOP_LOGGER_PROVIDER,
38
AnyValue,
39
AnyValueMap
40
} = require("@opentelemetry/api-logs");
41
```
42
43
## Basic Usage
44
45
```typescript
46
import { logs, SeverityNumber } from "@opentelemetry/api-logs";
47
48
// Get the global logger provider
49
const provider = logs.getLoggerProvider();
50
51
// Create a logger
52
const logger = logs.getLogger("my-logger", "1.0.0");
53
54
// Create and emit a log record
55
logger.emit({
56
timestamp: Date.now() * 1000000, // nanoseconds
57
severityNumber: SeverityNumber.INFO,
58
severityText: "INFO",
59
body: "This is a log message",
60
attributes: {
61
"service.name": "my-service",
62
"custom.attribute": "value"
63
}
64
});
65
```
66
67
## Architecture
68
69
The OpenTelemetry API Logs follows a layered architecture:
70
71
- **Global API Management**: Singleton `LogsAPI` class manages global logger provider registration and provides access to loggers
72
- **Provider Pattern**: `LoggerProvider` interface creates and manages `Logger` instances with versioning and options support
73
- **Bridge Interface**: `Logger` interface defines the core `emit()` method for log appenders to send log records
74
- **Proxy Pattern**: `ProxyLogger` and `ProxyLoggerProvider` enable lazy initialization and delegation to real implementations
75
- **Type Safety**: Complete TypeScript definitions for log records, severity levels, and flexible value types
76
- **No-op Fallbacks**: Safe fallback implementations when no real logger provider is registered
77
78
## Capabilities
79
80
### Global Logger Management
81
82
Central API for managing global logger providers and obtaining logger instances.
83
84
```typescript { .api }
85
/**
86
* Global logs API singleton instance
87
*/
88
const logs: LogsAPI;
89
90
class LogsAPI {
91
/** Get the singleton LogsAPI instance */
92
static getInstance(): LogsAPI;
93
94
/** Set the global logger provider */
95
setGlobalLoggerProvider(provider: LoggerProvider): LoggerProvider;
96
97
/** Get the current global logger provider */
98
getLoggerProvider(): LoggerProvider;
99
100
/** Get a logger from the global provider */
101
getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
102
103
/** Remove the global logger provider */
104
disable(): void;
105
}
106
```
107
108
### Logger Provider Interface
109
110
Registry interface for creating and managing named loggers with versioning support.
111
112
```typescript { .api }
113
interface LoggerProvider {
114
/**
115
* Returns a Logger, creating one if one with the given name, version, and
116
* options is not already created
117
*/
118
getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
119
}
120
121
interface LoggerOptions {
122
/** The schemaUrl of the tracer or instrumentation library */
123
schemaUrl?: string;
124
/** The instrumentation scope attributes to associate with emitted telemetry */
125
scopeAttributes?: Attributes;
126
/** Specifies whether the Trace Context should automatically be passed on to the LogRecords */
127
includeTraceContext?: boolean;
128
}
129
```
130
131
### Logger Interface
132
133
Core interface that log appenders implement to emit log records.
134
135
```typescript { .api }
136
interface Logger {
137
/**
138
* Emit a log record. This method should only be used by log appenders.
139
*/
140
emit(logRecord: LogRecord): void;
141
}
142
```
143
144
### Log Record Structure
145
146
Complete structure for representing log records with all OpenTelemetry log attributes.
147
148
```typescript { .api }
149
interface LogRecord {
150
/** The unique identifier for the log record */
151
eventName?: string;
152
/** The time when the log record occurred as UNIX Epoch time in nanoseconds */
153
timestamp?: TimeInput;
154
/** Time when the event was observed by the collection system */
155
observedTimestamp?: TimeInput;
156
/** Numerical value of the severity */
157
severityNumber?: SeverityNumber;
158
/** The severity text */
159
severityText?: string;
160
/** A value containing the body of the log record */
161
body?: LogBody;
162
/** Attributes that define the log record */
163
attributes?: LogAttributes;
164
/** The Context associated with the LogRecord */
165
context?: Context;
166
}
167
168
type LogBody = AnyValue;
169
type LogAttributes = AnyValueMap;
170
```
171
172
### Severity Levels
173
174
Standardized severity number enumeration following OpenTelemetry specification.
175
176
```typescript { .api }
177
enum SeverityNumber {
178
UNSPECIFIED = 0,
179
TRACE = 1,
180
TRACE2 = 2,
181
TRACE3 = 3,
182
TRACE4 = 4,
183
DEBUG = 5,
184
DEBUG2 = 6,
185
DEBUG3 = 7,
186
DEBUG4 = 8,
187
INFO = 9,
188
INFO2 = 10,
189
INFO3 = 11,
190
INFO4 = 12,
191
WARN = 13,
192
WARN2 = 14,
193
WARN3 = 15,
194
WARN4 = 16,
195
ERROR = 17,
196
ERROR2 = 18,
197
ERROR3 = 19,
198
ERROR4 = 20,
199
FATAL = 21,
200
FATAL2 = 22,
201
FATAL3 = 23,
202
FATAL4 = 24
203
}
204
```
205
206
### Flexible Value Types
207
208
Type system for representing flexible log data including scalars, arrays, maps, and binary data.
209
210
```typescript { .api }
211
type AnyValue =
212
| AnyValueScalar
213
| Uint8Array
214
| AnyValueArray
215
| AnyValueMap
216
| null
217
| undefined;
218
219
type AnyValueScalar = string | number | boolean;
220
221
type AnyValueArray = Array<AnyValue>;
222
223
interface AnyValueMap {
224
[attributeKey: string]: AnyValue;
225
}
226
```
227
228
### External Dependencies
229
230
Types imported from @opentelemetry/api that are used in the API signatures.
231
232
```typescript { .api }
233
// From @opentelemetry/api
234
interface Context {
235
// Context interface for associating log records with trace context
236
}
237
238
type TimeInput = number | Date;
239
240
interface Attributes {
241
[attributeKey: string]: AttributeValue | undefined;
242
}
243
244
type AttributeValue =
245
| string
246
| number
247
| boolean
248
| Array<null | undefined | string>
249
| Array<null | undefined | number>
250
| Array<null | undefined | boolean>;
251
```
252
253
### No-op Implementations
254
255
Safe fallback implementations for when no real logger provider is configured.
256
257
```typescript { .api }
258
class NoopLogger implements Logger {
259
/** No-operation emit method */
260
emit(_logRecord: LogRecord): void;
261
}
262
263
class NoopLoggerProvider implements LoggerProvider {
264
/** Returns a NoopLogger instance */
265
getLogger(
266
_name: string,
267
_version?: string,
268
_options?: LoggerOptions
269
): Logger;
270
}
271
272
/** Singleton no-op logger instance */
273
const NOOP_LOGGER: NoopLogger;
274
275
/** Singleton no-op logger provider instance */
276
const NOOP_LOGGER_PROVIDER: NoopLoggerProvider;
277
```
278
279
### Proxy Implementations
280
281
Proxy implementations that delegate to real implementations when available, falling back to no-ops.
282
283
```typescript { .api }
284
class ProxyLogger implements Logger {
285
readonly name: string;
286
readonly version?: string;
287
readonly options?: LoggerOptions;
288
289
constructor(
290
provider: LoggerDelegator,
291
name: string,
292
version?: string,
293
options?: LoggerOptions
294
);
295
296
/** Emit a log record via delegate or no-op */
297
emit(logRecord: LogRecord): void;
298
}
299
300
class ProxyLoggerProvider implements LoggerProvider {
301
/** Get logger from delegate or create proxy */
302
getLogger(name: string, version?: string, options?: LoggerOptions): Logger;
303
}
304
305
interface LoggerDelegator {
306
_getDelegateLogger(
307
name: string,
308
version?: string,
309
options?: LoggerOptions
310
): Logger | undefined;
311
}
312
```
313
314
## Usage Examples
315
316
### Setting Up a Logger Provider
317
318
```typescript
319
import { logs, LoggerProvider, Logger, LogRecord } from "@opentelemetry/api-logs";
320
321
// Custom logger provider implementation
322
class MyLoggerProvider implements LoggerProvider {
323
getLogger(name: string, version?: string): Logger {
324
return new MyLogger(name, version);
325
}
326
}
327
328
class MyLogger implements Logger {
329
constructor(private name: string, private version?: string) {}
330
331
emit(logRecord: LogRecord): void {
332
console.log(`[${this.name}${this.version ? `@${this.version}` : ''}]`, logRecord);
333
}
334
}
335
336
// Register the provider globally
337
logs.setGlobalLoggerProvider(new MyLoggerProvider());
338
```
339
340
### Creating Log Appenders
341
342
```typescript
343
import { logs, SeverityNumber, LogRecord } from "@opentelemetry/api-logs";
344
345
class ConsoleLogAppender {
346
private logger = logs.getLogger("console-appender", "1.0.0");
347
348
logInfo(message: string, attributes?: Record<string, any>): void {
349
const logRecord: LogRecord = {
350
timestamp: Date.now() * 1000000, // Convert to nanoseconds
351
severityNumber: SeverityNumber.INFO,
352
severityText: "INFO",
353
body: message,
354
attributes: attributes || {}
355
};
356
357
this.logger.emit(logRecord);
358
}
359
360
logError(error: Error, attributes?: Record<string, any>): void {
361
const logRecord: LogRecord = {
362
timestamp: Date.now() * 1000000,
363
severityNumber: SeverityNumber.ERROR,
364
severityText: "ERROR",
365
body: error.message,
366
attributes: {
367
"error.name": error.name,
368
"error.stack": error.stack,
369
...attributes || {}
370
}
371
};
372
373
this.logger.emit(logRecord);
374
}
375
}
376
377
// Usage
378
const appender = new ConsoleLogAppender();
379
appender.logInfo("Application started", { "service.name": "my-app" });
380
appender.logError(new Error("Something went wrong"), { "user.id": "123" });
381
```
382
383
### Working with Complex Log Bodies
384
385
```typescript
386
import { logs, SeverityNumber, AnyValue } from "@opentelemetry/api-logs";
387
388
const logger = logs.getLogger("structured-logger");
389
390
// Log with complex structured data
391
const complexData: AnyValue = {
392
user: {
393
id: 123,
394
name: "Alice",
395
preferences: ["email", "sms"]
396
},
397
metrics: {
398
response_time: 234.5,
399
success: true
400
},
401
tags: ["auth", "api", "v2"]
402
};
403
404
logger.emit({
405
timestamp: Date.now() * 1000000,
406
severityNumber: SeverityNumber.INFO,
407
body: complexData,
408
attributes: {
409
"http.method": "POST",
410
"http.status_code": 200
411
}
412
});
413
```
414
415
### Logger Provider Lifecycle Management
416
417
```typescript
418
import { logs } from "@opentelemetry/api-logs";
419
420
// Check current provider
421
const currentProvider = logs.getLoggerProvider();
422
console.log("Current provider:", currentProvider);
423
424
// Set up a new provider
425
const myProvider = new MyLoggerProvider();
426
logs.setGlobalLoggerProvider(myProvider);
427
428
// Later, clean up
429
logs.disable(); // Removes global provider, falls back to no-op
430
```