Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions shared/otel-core/Tests/Unit/src/sdk/OTelLogger.Tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { setContextSpanContext } from "../../../../src/otel/api/trace/utils";
import { createLogger } from "../../../../src/otel/sdk/OTelLogger";
import { createResolvedPromise } from "@nevware21/ts-async";
import { IOTelApi, IOTelConfig } from "../../../../src";
import { IOTelResource, OTelRawResourceAttribute } from "../../../../src/interfaces/otel/resources/IOTelResource";
import { IOTelAttributes } from "../../../../src/interfaces/otel/IOTelAttributes";
import { IOTelWebSdkConfig } from "../../../../src/interfaces/otel/config/IOTelWebSdkConfig";

// W3C trace flags constant for sampled traces
const eW3CTraceFlags_Sampled = 1;
Expand Down Expand Up @@ -38,9 +41,7 @@ export class OTelLoggerTests extends AITestClass {

private setup() {
const logProcessor = this._createMockProcessor();
const provider = createLoggerProvider({
processors: [logProcessor]
});
const provider = createLoggerProvider(this._cfg([logProcessor]));
const logger = provider.getLogger("test name", "test version", {
schemaUrl: "test schema url"
}) as LoggerWithScope;
Expand All @@ -53,7 +54,7 @@ export class OTelLoggerTests extends AITestClass {
name: "Logger: factory returns logger instance",
test: () => {
const logProcessor = this._createMockProcessor();
const provider = createLoggerProvider({ processors: [logProcessor] });
const provider = createLoggerProvider(this._cfg([logProcessor]));
const sharedState = provider._sharedState;
const scope: IOTelInstrumentationScope = {
name: "test name",
Expand Down Expand Up @@ -151,4 +152,17 @@ export class OTelLoggerTests extends AITestClass {
shutdown: () => createResolvedPromise(undefined)
};
}

private _cfg(processors: IOTelLogRecordProcessor[]): IOTelWebSdkConfig {
const resource: IOTelResource = {
attributes: {} as IOTelAttributes,
merge: () => resource,
getRawAttributes: () => [] as OTelRawResourceAttribute[]
};
return {
resource: resource,
errorHandlers: {},
logProcessors: processors
} as IOTelWebSdkConfig;
}
}
88 changes: 59 additions & 29 deletions shared/otel-core/Tests/Unit/src/sdk/OTelLoggerProvider.Tests.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import { IOTelSdkLogRecord } from "../../../../src/interfaces/otel/logs/IOTelSdk
import { createLoggerProvider } from "../../../../src/otel/sdk/OTelLoggerProvider";
import { createMultiLogRecordProcessor } from "../../../../src/otel/sdk/OTelMultiLogRecordProcessor";
import { loadDefaultConfig } from "../../../../src/otel/sdk/config";
import { IOTelWebSdkConfig } from "../../../../src/interfaces/otel/config/IOTelWebSdkConfig";
import { IOTelResource, OTelRawResourceAttribute } from "../../../../src/interfaces/otel/resources/IOTelResource";
import { IOTelAttributes } from "../../../../src/interfaces/otel/IOTelAttributes";

class TestProcessor implements IOTelLogRecordProcessor {
public logRecords: IOTelSdkLogRecord[] = [];
Expand Down Expand Up @@ -46,6 +49,23 @@ const setup = (processors?: IOTelLogRecordProcessor[]) => {
return { multiProcessor, forceFlushTimeoutMillis };
};

function _testResource(): IOTelResource {
const resource: IOTelResource = {
attributes: {} as IOTelAttributes,
merge: () => resource,
getRawAttributes: () => [] as OTelRawResourceAttribute[]
};
return resource;
}

function _cfg(processors: IOTelLogRecordProcessor[]): IOTelWebSdkConfig {
return {
resource: _testResource(),
errorHandlers: {},
logProcessors: processors
} as IOTelWebSdkConfig;
}

export class OTelMultiLogRecordProcessorTests extends AITestClass {
public testInitialize() {
super.testInitialize();
Expand All @@ -70,7 +90,7 @@ export class OTelMultiLogRecordProcessorTests extends AITestClass {
name: "MultiLogRecordProcessor: onEmit - should no-op when no processors registered",
test: () => {
const { multiProcessor } = setup();
const provider = createLoggerProvider({ processors: [multiProcessor] });
const provider = createLoggerProvider(_cfg([multiProcessor]));
const logger = provider.getLogger("default");
logger.emit({ body: "message" });
Assert.ok(true, "Emit should not throw when no processors registered");
Expand All @@ -82,7 +102,7 @@ export class OTelMultiLogRecordProcessorTests extends AITestClass {
test: () => {
const processor = new TestProcessor();
const { multiProcessor } = setup([processor]);
const provider = createLoggerProvider({ processors: [multiProcessor] });
const provider = createLoggerProvider(_cfg([multiProcessor]));
const logger = provider.getLogger("default");
Assert.equal(processor.logRecords.length, 0, "Processor should start with no records");
logger.emit({ body: "one" });
Expand All @@ -96,7 +116,7 @@ export class OTelMultiLogRecordProcessorTests extends AITestClass {
const processor1 = new TestProcessor();
const processor2 = new TestProcessor();
const { multiProcessor } = setup([processor1, processor2]);
const provider = createLoggerProvider({ processors: [multiProcessor] });
const provider = createLoggerProvider(_cfg([multiProcessor]));
const logger = provider.getLogger("default");

Assert.equal(processor1.logRecords.length, 0, "Processor1 should start empty");
Expand Down Expand Up @@ -208,7 +228,7 @@ export class OTelMultiLogRecordProcessorTests extends AITestClass {
const processor1 = new TestProcessor();
const processor2 = new TestProcessor();
const { multiProcessor } = setup([processor1, processor2]);
const provider = createLoggerProvider({ processors: [multiProcessor] });
const provider = createLoggerProvider(_cfg([multiProcessor]));
const logger = provider.getLogger("default");

logger.emit({ body: "one" });
Expand Down
7 changes: 3 additions & 4 deletions shared/otel-core/planning/IMPLEMENTATION_PLAN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OTel Web SDK Implementation Plan

**Last Updated**: February 2026
**Last Updated**: March 2026
**Reference**: [CONTEXT.md](../CONTEXT.md)

---
Expand Down Expand Up @@ -77,7 +77,7 @@

## Implementation Phases

### Phase 0: CONTEXT.md Compliance Fixes (Prerequisite)
### Phase 0: CONTEXT.md Compliance Fixes (Prerequisite) ✅ Complete

Fix existing implementations to comply with CONTEXT.md before building new features.

Expand All @@ -90,10 +90,9 @@ Fix existing implementations to comply with CONTEXT.md before building new featu
| `createResource` | Add shutdown/cleanup method |
| All | Add `IUnloadHook` management with `.rm()` calls during shutdown |
| All | Add comprehensive TypeDoc documentation |

**Deliverable**: All existing implementations pass CONTEXT.md validation checklist.

### Phase 1: SDK Foundation (Critical)
### Phase 1: SDK Foundation (Critical) ✅ Complete

| Component | Location | Description |
|-----------|----------|-------------|
Expand Down
4 changes: 3 additions & 1 deletion shared/otel-core/src/ext/ValueSanitizer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { arrForEach, arrIncludes, arrIndexOf, getLength, isNullOrUndefined, isString, objCreate, objForEachKey } from "@nevware21/ts-utils";
import {
arrForEach, arrIncludes, arrIndexOf, getLength, isNullOrUndefined, isString, objCreate, objForEachKey
} from "@nevware21/ts-utils";
import { STR_EMPTY } from "../constants/InternalConstants";
import { FieldValueSanitizerType } from "../enums/ext/Enums";
import {
Expand Down
6 changes: 5 additions & 1 deletion shared/otel-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ export { IOTelSpanOptions } from "./interfaces/otel/trace/IOTelSpanOptions";
export { createOTelTraceState, isOTelTraceState } from "./otel/api/trace/traceState";
export { createSpan } from "./otel/api/trace/span";
export { createTraceProvider } from "./otel/api/trace/traceProvider";
export { createTracerProvider } from "./otel/api/trace/tracerProvider";
export { ITracerProviderConfig } from "./interfaces/otel/trace/ITracerProviderConfig";
export { isSpanContext, wrapDistributedTrace, createOTelSpanContext } from "./otel/api/trace/spanContext";
export {
createNonRecordingSpan, deleteContextSpan, getContextSpan, setContextSpan, setContextSpanContext, getContextActiveSpanContext, isSpanContextValid,
Expand Down Expand Up @@ -200,6 +202,7 @@ export { IOTelWebSdkConfig } from "./interfaces/otel/config/IOTelWebSdkConfig";
export { createContextManager } from "./otel/api/context/contextManager";
export { createContext } from "./otel/api/context/context";
export { IOTelContextManager } from "./interfaces/otel/context/IOTelContextManager";
export { IContextManagerConfig } from "./interfaces/otel/context/IContextManagerConfig";
export { IOTelContext } from "./interfaces/otel/context/IOTelContext";

// OpenTelemetry Resources
Expand Down Expand Up @@ -235,7 +238,7 @@ export {

// OpenTelemetry Error Handlers
export {
handleAttribError, handleSpanError, handleDebug, handleWarn, handleError, handleNotImplemented
OTelErrorHandlerSource, handleAttribError, handleSpanError, handleDebug, handleWarn, handleError, handleNotImplemented
} from "./internal/handleErrors";

// OpenTelemetry Error Classes
Expand All @@ -253,6 +256,7 @@ export { IOTelSdkLogRecord } from "./interfaces/otel/logs/IOTelSdkLogRecord";
export { IOTelLoggerProvider } from "./interfaces/otel/logs/IOTelLoggerProvider";
export { IOTelLoggerOptions } from "./interfaces/otel/logs/IOTelLoggerOptions";
export { IOTelLoggerProviderSharedState } from "./interfaces/otel/logs/IOTelLoggerProviderSharedState";
export { IOTelLoggerProviderConfig } from "./interfaces/otel/logs/IOTelLoggerProviderConfig";
export { IOTelLogRecordLimits } from "./interfaces/otel/logs/IOTelLogRecordLimits";

// SDK Logs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

import { IOTelContextManager } from "../context/IOTelContextManager";
import { IOTelLogRecordLimits } from "../logs/IOTelLogRecordLimits";
import { IOTelLogRecordProcessor } from "../logs/IOTelLogRecordProcessor";
import { IOTelResource } from "../resources/IOTelResource";
import { IOTelIdGenerator } from "../trace/IOTelIdGenerator";
Expand Down Expand Up @@ -98,6 +99,17 @@ export interface IOTelWebSdkConfig {
*/
logProcessors?: IOTelLogRecordProcessor[];

/**
* How long the forceFlush can run before it is cancelled.
* The default value is 30000ms.
*/
forceFlushTimeoutMillis?: number;

/**
* Log record limits controlling attribute counts and value lengths.
*/
logRecordLimits?: IOTelLogRecordLimits;

// TODO: Phase 2 - Uncomment when IOTelSpanProcessor is implemented
// /**
// * Span processors for the trace pipeline.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { IOTelContext } from "./IOTelContext";

/**
* Configuration interface for creating a context manager.
*
* @remarks
* Error handlers are inherited from the SDK/core config (IOTelConfig/IOTelWebSdkConfig)
* to avoid duplicating them in each component config.
*
* @since 4.0.0
*/
export interface IContextManagerConfig {
/**
* The parent / root context to use if there is no active context.
*/
parentContext?: IOTelContext;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,32 @@ import { IOTelResource } from "../resources/IOTelResource";
import { IOTelLogRecordLimits } from "./IOTelLogRecordLimits";
import { IOTelLogRecordProcessor } from "./IOTelLogRecordProcessor";

/**
* Configuration interface for the OpenTelemetry LoggerProvider.
* Provides all configuration options required for LoggerProvider initialization.
*
* @remarks
* - The `resource` property is required
* - Error handlers are inherited from the SDK/core config (IOTelWebSdkConfig)
* - Config is used directly — never copied with spread operator
* - Supports dynamic configuration via `onConfigChange` callbacks
*
* @since 3.4.0
*/
export interface IOTelLoggerProviderConfig {
/** Resource associated with trace telemetry */
resource?: IOTelResource;
/**
* Resource information for telemetry source identification.
* Provides attributes that describe the entity producing telemetry.
*/
resource: IOTelResource;

/**
* How long the forceFlush can run before it is cancelled.
* The default value is 30000ms
*/
forceFlushTimeoutMillis?: number;

/** Log Record Limits*/
/** Log Record Limits */
logRecordLimits?: IOTelLogRecordLimits;

/** Log Record Processors */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ export interface IOTelLoggerProviderSharedState {
/**
* Resource describing the entity producing telemetry.
*/
readonly resource: IOTelResource;
resource: IOTelResource;
/**
* Timeout applied when forcing processors to flush.
*/
readonly forceFlushTimeoutMillis: number;
forceFlushTimeoutMillis: number;
/**
* Limits applied to log records created by the provider.
*/
readonly logRecordLimits: Required<IOTelLogRecordLimits>;
logRecordLimits: Required<IOTelLogRecordLimits>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,12 @@ export interface IOTelResource {
merge(other: IOTelResource | null): IOTelResource;

getRawAttributes(): OTelRawResourceAttribute[];

/**
* Releases internal resources and clears cached attribute containers.
* After shutdown, the resource should not be used.
*
* @since 4.0.0
*/
shutdown?(): void;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import { ITraceHost } from "../../ai/ITraceProvider";

/**
* Configuration interface for creating a TracerProvider.
*
* @remarks
* The TracerProvider manages Tracer instances and delegates span creation
* to the configured trace host.
* Error handlers are inherited from the host's config (host.config.errorHandlers).
*
* @since 4.0.0
*/
export interface ITracerProviderConfig {
/**
* The trace host that provides span creation and context management.
*
* @see {@link ITraceHost}
*/
host: ITraceHost;
}
Loading
Loading