diff --git a/experimental/packages/api-logs/README.md b/experimental/packages/api-logs/README.md index 57d40a32116..e2073cbdfec 100644 --- a/experimental/packages/api-logs/README.md +++ b/experimental/packages/api-logs/README.md @@ -36,13 +36,15 @@ api.logs.setGlobalLoggerProvider(loggerProvider); /* returns loggerProvider (no-op if a working provider has not been initialized) */ api.logs.getLoggerProvider(); /* returns a logger from the registered global logger provider (no-op if a working provider has not been initialized) */ -const logger = api.logs.getLogger(name, version); +const logger = api.logs.getLogger(name, version, { + eventDomain: "event-domain", +}); // logging an event in an instrumentation library -logger.emitEvent({ name: 'event-name', domain: 'event-domain' }); +logger.getLogEvent("event-name", { body: "this is a body" }).emit(); // logging an event in a log appender -logger.emitLogRecord({ severityNumber: 1, body: 'log data' }); +logger.getLogRecord({ body: "this is a body", severityNumber: SeverityNumber.INFO, severityText: "INFO" }).emit(); ``` ## Useful links diff --git a/experimental/packages/api-logs/src/NoopLogRecord.ts b/experimental/packages/api-logs/src/NoopLogRecord.ts new file mode 100644 index 00000000000..66a694d27e4 --- /dev/null +++ b/experimental/packages/api-logs/src/NoopLogRecord.ts @@ -0,0 +1,31 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Attributes, AttributeValue } from "@opentelemetry/api"; + +import type { LogRecord } from "./types/LogRecord"; + +export class NoopLogRecord implements LogRecord { + setAttribute(_key: string, _value?: AttributeValue): LogRecord { + return this; + } + + setAttributes(_attributes: Attributes): LogRecord { + return this; + } + + emit(): void {} +} diff --git a/experimental/packages/api-logs/src/NoopLogger.ts b/experimental/packages/api-logs/src/NoopLogger.ts index 3f2227154c1..bf0b9edc83e 100644 --- a/experimental/packages/api-logs/src/NoopLogger.ts +++ b/experimental/packages/api-logs/src/NoopLogger.ts @@ -14,11 +14,16 @@ * limitations under the License. */ -import { Logger } from './types/Logger'; -import { LogEvent } from './types/LogEvent'; -import { LogRecord } from './types/LogRecord'; +import type { Logger } from "./types/Logger"; +import type { LogRecord } from "./types/LogRecord"; +import { NoopLogRecord } from "./NoopLogRecord"; export class NoopLogger implements Logger { - emitLogRecord(_logRecord: LogRecord): void {} - emitEvent(_event: LogEvent): void {} + getLogRecord(): LogRecord { + return new NoopLogRecord(); + } + + getLogEvent(_eventName: string): LogRecord { + return new NoopLogRecord(); + } } diff --git a/experimental/packages/api-logs/src/NoopLoggerProvider.ts b/experimental/packages/api-logs/src/NoopLoggerProvider.ts index 5c69e5a7bd0..bc270f8c2d3 100644 --- a/experimental/packages/api-logs/src/NoopLoggerProvider.ts +++ b/experimental/packages/api-logs/src/NoopLoggerProvider.ts @@ -14,13 +14,13 @@ * limitations under the License. */ -import { LoggerProvider } from './types/LoggerProvider'; -import { Logger } from './types/Logger'; -import { LoggerOptions } from './types/LoggerOptions'; -import { NoopLogger } from './NoopLogger'; +import type { LoggerProvider } from "./types/LoggerProvider"; +import type { Logger } from "./types/Logger"; +import type { LoggerOptions } from "./types/LoggerOptions"; +import { NoopLogger } from "./NoopLogger"; export class NoopLoggerProvider implements LoggerProvider { - getLogger(_name: string, _version?: string | undefined, _options?: LoggerOptions | undefined): Logger { + getLogger(_name: string, _version?: string, _options?: LoggerOptions): Logger { return new NoopLogger(); } } diff --git a/experimental/packages/api-logs/src/api/logs.ts b/experimental/packages/api-logs/src/api/logs.ts index 0f9388648ad..8a318737747 100644 --- a/experimental/packages/api-logs/src/api/logs.ts +++ b/experimental/packages/api-logs/src/api/logs.ts @@ -14,16 +14,16 @@ * limitations under the License. */ +import type { LoggerProvider } from "../types/LoggerProvider"; +import type { Logger } from "../types/Logger"; +import type { LoggerOptions } from "../types/LoggerOptions"; import { API_BACKWARDS_COMPATIBILITY_VERSION, GLOBAL_LOGS_API_KEY, _global, - makeGetter -} from '../internal/global-utils'; -import { LoggerProvider } from '../types/LoggerProvider'; -import { NOOP_LOGGER_PROVIDER } from '../NoopLoggerProvider'; -import { Logger } from '../types/Logger'; -import { LoggerOptions } from '../types/LoggerOptions'; + makeGetter, +} from "../internal/global-utils"; +import { NOOP_LOGGER_PROVIDER } from "../NoopLoggerProvider"; export class LogsAPI { private static _instance?: LogsAPI; diff --git a/experimental/packages/api-logs/src/index.ts b/experimental/packages/api-logs/src/index.ts index cf22a2e5eb5..ce158ba323a 100644 --- a/experimental/packages/api-logs/src/index.ts +++ b/experimental/packages/api-logs/src/index.ts @@ -17,7 +17,6 @@ export * from './types/Logger'; export * from './types/LoggerProvider'; export * from './types/LogRecord'; -export * from './types/LogEvent'; export * from './types/LoggerOptions'; import { LogsAPI } from './api/logs'; diff --git a/experimental/packages/api-logs/src/internal/global-utils.ts b/experimental/packages/api-logs/src/internal/global-utils.ts index 705139aedaf..5239517e7d6 100644 --- a/experimental/packages/api-logs/src/internal/global-utils.ts +++ b/experimental/packages/api-logs/src/internal/global-utils.ts @@ -14,12 +14,10 @@ * limitations under the License. */ -import { LoggerProvider } from '../types/LoggerProvider'; -import { _globalThis } from '../platform'; +import type { LoggerProvider } from "../types/LoggerProvider"; +import { _globalThis } from "../platform"; -export const GLOBAL_LOGS_API_KEY = Symbol.for( - 'io.opentelemetry.js.api.logs' -); +export const GLOBAL_LOGS_API_KEY = Symbol.for("io.opentelemetry.js.api.logs"); type Get = (version: number) => T; type OtelGlobal = Partial<{ diff --git a/experimental/packages/api-logs/src/types/LogEvent.ts b/experimental/packages/api-logs/src/types/LogEvent.ts deleted file mode 100644 index 7b37572c6c2..00000000000 --- a/experimental/packages/api-logs/src/types/LogEvent.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Attributes } from '@opentelemetry/api'; - -export interface LogEvent { - /** - * The time when the event occurred as UNIX Epoch time in nanoseconds. - */ - timestamp?: number; - - /** - * The name of the event. - */ - name: string; - - /** - * The domain the event belongs to. - */ - domain?: string; - - /** - * Additional attributes that describe the event. - */ - attributes?: Attributes; - - /** - * 8 least significant bits are the trace flags as defined in W3C Trace Context specification. - */ - traceFlags?: number; - - /** - * A unique identifier for a trace. - */ - traceId?: string; - - /** - * A unique identifier for a span within a trace. - */ - spanId?: string; -} diff --git a/experimental/packages/api-logs/src/types/LogRecord.ts b/experimental/packages/api-logs/src/types/LogRecord.ts index 132900c54ab..b8ce438699d 100644 --- a/experimental/packages/api-logs/src/types/LogRecord.ts +++ b/experimental/packages/api-logs/src/types/LogRecord.ts @@ -14,46 +14,48 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api'; +import type { Attributes, AttributeValue } from "@opentelemetry/api"; + +export 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, +} export interface LogRecord { - /** - * The time when the log record occurred as UNIX Epoch time in nanoseconds. - */ - timestamp?: number; - - /** - * Numerical value of the severity. - */ - severityNumber?: number; - - /** - * The severity text. - */ - severityText?: string; - - /** - * A value containing the body of the log record. - */ - body?: string; - - /** - * Attributes that define the log record. - */ - attributes?: Attributes; - - /** - * 8 least significant bits are the trace flags as defined in W3C Trace Context specification. - */ - traceFlags?: number; - - /** - * A unique identifier for a trace. - */ - traceId?: string; - - /** - * A unique identifier for a span within a trace. - */ - spanId?: string; + /** + * Sets attributes. If the {@link LoggerOptions} previously contained a mapping for any of the + * keys, the old values are replaced by the specified values. + */ + setAttribute(key: string, value?: AttributeValue): LogRecord; + setAttributes(attributes: Attributes): LogRecord; + + /** + * Emit the log record. + */ + emit(): void; } + +export type LogEvent = LogRecord; diff --git a/experimental/packages/api-logs/src/types/Logger.ts b/experimental/packages/api-logs/src/types/Logger.ts index b30f3aff93e..574d8cd74ee 100644 --- a/experimental/packages/api-logs/src/types/Logger.ts +++ b/experimental/packages/api-logs/src/types/Logger.ts @@ -14,21 +14,56 @@ * limitations under the License. */ -import { LogRecord } from './LogRecord'; -import { LogEvent } from './LogEvent'; +import type { Attributes, SpanContext, TimeInput } from "@opentelemetry/api"; + +import type { LogEvent, LogRecord, SeverityNumber } from "./LogRecord"; + +export interface LogRecordOptions { + /** + * The time when the log record occurred as UNIX Epoch time in nanoseconds. + */ + timestamp?: TimeInput; + + /** + * Numerical value of the severity. + */ + severityNumber?: SeverityNumber; + + /** + * The severity text. + */ + severityText?: string; + + /** + * A value containing the body of the log record. + */ + body?: string; + + /** + * Attributes that define the log record. + */ + attributes?: Attributes; + + /** + * The trace context. + */ + context?: SpanContext; +} export interface Logger { /** - * Emit a log record. This method should only be used by log appenders. + * Get a log record. This method should only be used by log appenders. * - * @param logRecord + * @param options */ - emitLogRecord(logRecord: LogRecord): void; + getLogRecord(options?: LogRecordOptions): LogRecord; /** - * Emit an event. This method should only be used by instrumentations emitting events. + * Get an event. This method should only be used by instrumentations emitting events. * - * @param event + * @param eventName the event name, which acts as a classifier for events. Within a particular event domain, + * event name defines a particular class or type of event. + * @param options */ - emitEvent(event: LogEvent): void; + getLogEvent(eventName: string, options?: LogRecordOptions): LogEvent; } diff --git a/experimental/packages/api-logs/src/types/LoggerOptions.ts b/experimental/packages/api-logs/src/types/LoggerOptions.ts index 9b2fe06fc86..a753c337973 100644 --- a/experimental/packages/api-logs/src/types/LoggerOptions.ts +++ b/experimental/packages/api-logs/src/types/LoggerOptions.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { Attributes } from '@opentelemetry/api'; +import type { Attributes } from "@opentelemetry/api"; export interface LoggerOptions { /** diff --git a/experimental/packages/api-logs/src/types/LoggerProvider.ts b/experimental/packages/api-logs/src/types/LoggerProvider.ts index e79aa1ce09e..ba81e788947 100644 --- a/experimental/packages/api-logs/src/types/LoggerProvider.ts +++ b/experimental/packages/api-logs/src/types/LoggerProvider.ts @@ -14,14 +14,14 @@ * limitations under the License. */ -import { Logger } from './Logger'; -import { LoggerOptions } from './LoggerOptions'; +import type { Logger } from "./Logger"; +import type { LoggerOptions } from "./LoggerOptions"; /** * A registry for creating named {@link Logger}s. */ export interface LoggerProvider { - /** + /** * Returns a Logger, creating one if one with the given name, version, and * schemaUrl pair is not already created. * diff --git a/experimental/packages/api-logs/test/api/api.test.ts b/experimental/packages/api-logs/test/api/api.test.ts index 3548e081844..2f8fd29d47e 100644 --- a/experimental/packages/api-logs/test/api/api.test.ts +++ b/experimental/packages/api-logs/test/api/api.test.ts @@ -14,32 +14,34 @@ * limitations under the License. */ -import * as assert from 'assert'; -import { Logger, logs } from '../../src'; -import { NoopLogger } from '../../src/NoopLogger'; -import { NoopLoggerProvider } from '../../src/NoopLoggerProvider'; +import * as assert from "assert"; -describe('API', () => { +import type { Logger } from "../../src"; +import { logs } from "../../src"; +import { NoopLogger } from "../../src/NoopLogger"; +import { NoopLoggerProvider } from "../../src/NoopLoggerProvider"; + +describe("API", () => { const dummyLogger = new NoopLogger(); - it('should expose a logger provider via getLoggerProvider', () => { + it("should expose a logger provider via getLoggerProvider", () => { const provider = logs.getLoggerProvider(); assert.ok(provider); - assert.strictEqual(typeof provider, 'object'); + assert.strictEqual(typeof provider, "object"); }); - describe('GlobalLoggerProvider', () => { + describe("GlobalLoggerProvider", () => { beforeEach(() => { logs.disable(); }); - it('should use the global logger provider', () => { + it("should use the global logger provider", () => { logs.setGlobalLoggerProvider(new TestLoggerProvider()); - const logger = logs.getLoggerProvider().getLogger('name'); + const logger = logs.getLoggerProvider().getLogger("name"); assert.deepStrictEqual(logger, dummyLogger); }); - it('should not allow overriding global provider if already set', () => { + it("should not allow overriding global provider if already set", () => { const provider1 = new TestLoggerProvider(); const provider2 = new TestLoggerProvider(); logs.setGlobalLoggerProvider(provider1); @@ -49,14 +51,14 @@ describe('API', () => { }); }); - describe('getLogger', () => { + describe("getLogger", () => { beforeEach(() => { logs.disable(); }); - it('should return a logger instance from global provider', () => { + it("should return a logger instance from global provider", () => { logs.setGlobalLoggerProvider(new TestLoggerProvider()); - const logger = logs.getLogger('myLogger'); + const logger = logs.getLogger("myLogger"); assert.deepStrictEqual(logger, dummyLogger); }); }); diff --git a/experimental/packages/api-logs/test/noop-implementations/noop-log-record.test.ts b/experimental/packages/api-logs/test/noop-implementations/noop-log-record.test.ts new file mode 100644 index 00000000000..5365d470b4f --- /dev/null +++ b/experimental/packages/api-logs/test/noop-implementations/noop-log-record.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright The OpenTelemetry Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as assert from "assert"; + +import { NoopLoggerProvider } from "../../src/NoopLoggerProvider"; +import { NoopLogRecord } from "../../src/NoopLogRecord"; + +describe("NoopLogRecord", () => { + const logger = new NoopLoggerProvider().getLogger("test-noop"); + const logRecord = logger.getLogRecord({}); + + it("constructor should not crash", () => { + assert(logRecord instanceof NoopLogRecord); + }); + + it("calling setAttribute should not crash", () => { + logRecord.setAttribute("attribute.name", "test attribute name"); + }); + + it("calling setAttributes should not crash", () => { + logRecord.setAttributes({ + "attribute.name": "test attribute name", + "attribute.age": 18, + }); + }); + + it("calling emit should not crash", () => { + logRecord.emit(); + }); +}); diff --git a/experimental/packages/api-logs/test/noop-implementations/noop-logger.test.ts b/experimental/packages/api-logs/test/noop-implementations/noop-logger.test.ts index 6360e7b7dd1..be9c2cb6ad3 100644 --- a/experimental/packages/api-logs/test/noop-implementations/noop-logger.test.ts +++ b/experimental/packages/api-logs/test/noop-implementations/noop-logger.test.ts @@ -14,23 +14,24 @@ * limitations under the License. */ -import * as assert from 'assert'; -import { NoopLogger } from '../../src/NoopLogger'; -import { NoopLoggerProvider } from '../../src/NoopLoggerProvider'; +import * as assert from "assert"; -describe('NoopLogger', () => { - it('constructor should not crash', () => { - const logger = new NoopLoggerProvider().getLogger('test-noop'); +import { NoopLogger } from "../../src/NoopLogger"; +import { NoopLoggerProvider } from "../../src/NoopLoggerProvider"; + +describe("NoopLogger", () => { + it("constructor should not crash", () => { + const logger = new NoopLoggerProvider().getLogger("test-noop"); assert(logger instanceof NoopLogger); }); - it('calling emitEvent should not crash', () => { - const logger = new NoopLoggerProvider().getLogger('test-noop'); - logger.emitEvent({ name: 'event-name', domain: 'event-domain' }); + it("calling getLogEvent should not crash", () => { + const logger = new NoopLoggerProvider().getLogger("test-noop"); + logger.getLogEvent("event-name", { severityNumber: 1, body: "log body" }); }); - it('calling emitLogRecord should not crash', () => { - const logger = new NoopLoggerProvider().getLogger('test-noop'); - logger.emitLogRecord({ severityNumber: 1, body: 'log body' }); + it("calling getLogRecord should not crash", () => { + const logger = new NoopLoggerProvider().getLogger("test-noop"); + logger.getLogRecord({ severityNumber: 1, body: "log body" }); }); });