diff --git a/package.json b/package.json index 33ce6eb0..9ded4eb6 100644 --- a/package.json +++ b/package.json @@ -58,12 +58,12 @@ }, "./loader": { "import": { - "types": "./dist/esm/loader.d.ts", - "default": "./dist/esm/loader.js" + "types": "./dist/esm/azureMonitor/loader.d.ts", + "default": "./dist/esm/azureMonitor/loader.js" }, "require": { - "types": "./dist/commonjs/loader.d.ts", - "default": "./dist/commonjs/loader.js" + "types": "./dist/commonjs/azureMonitor/loader.d.ts", + "default": "./dist/commonjs/azureMonitor/loader.js" } } }, diff --git a/src/distro/distro.ts b/src/distro/distro.ts index 818f68cc..d5f0df8f 100644 --- a/src/distro/distro.ts +++ b/src/distro/distro.ts @@ -6,8 +6,15 @@ import { logs } from "@opentelemetry/api-logs"; import type { NodeSDKConfiguration } from "@opentelemetry/sdk-node"; import { NodeSDK } from "@opentelemetry/sdk-node"; import type { MetricReader, ViewOptions } from "@opentelemetry/sdk-metrics"; -import { type SpanProcessor, BatchSpanProcessor } from "@opentelemetry/sdk-trace-base"; +import { + type SpanProcessor, + BatchSpanProcessor, + SimpleSpanProcessor, + ConsoleSpanExporter, +} from "@opentelemetry/sdk-trace-base"; import type { LogRecordProcessor } from "@opentelemetry/sdk-logs"; +import { SimpleLogRecordProcessor, ConsoleLogRecordExporter } from "@opentelemetry/sdk-logs"; +import { ConsoleMetricExporter, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics"; import type { Instrumentation } from "@opentelemetry/instrumentation"; import { InternalConfig } from "../shared/config.js"; @@ -136,6 +143,25 @@ export function useMicrosoftOpenTelemetry(options?: MicrosoftOpenTelemetryOption spanProcessors.push(a365ExportProcessor); } + // ── Console exporters (auto-enabled when no other exporter is active, or explicitly) ─ + const hasCustomProcessors = + (options?.spanProcessors?.length ?? 0) > 0 || + (options?.metricReaders?.length ?? 0) > 0 || + (options?.logRecordProcessors?.length ?? 0) > 0; + const consoleEnabled = + options?.enableConsoleExporters ?? + (!azureMonitorEnabled && !isOtlpEnabled() && !a365Config.enabled && !hasCustomProcessors); + if (consoleEnabled) { + spanProcessors.push(new SimpleSpanProcessor(new ConsoleSpanExporter())); + metricReaders.push( + new PeriodicExportingMetricReader({ + exporter: new ConsoleMetricExporter(), + exportIntervalMillis: config.metricExportIntervalMillis, + }), + ); + logRecordProcessors.push(new SimpleLogRecordProcessor(new ConsoleLogRecordExporter())); + } + const views: ViewOptions[] = [...(metricHandler ? metricHandler.getViews() : []), ...customViews]; // ── Create and start NodeSDK ────────────────────────────────────── diff --git a/src/types.ts b/src/types.ts index 1cd8f1cf..2d0fd111 100644 --- a/src/types.ts +++ b/src/types.ts @@ -47,6 +47,9 @@ export interface MicrosoftOpenTelemetryOptions { /** A365 observability configuration. When provided with `enabled: true`, A365 export is enabled. */ a365?: A365Options; + + /** Enable console exporters for traces, metrics, and logs. Auto-enabled when no other exporter is active. */ + enableConsoleExporters?: boolean; } /** diff --git a/test/internal/unit/main.test.ts b/test/internal/unit/main.test.ts index 1afff65a..55cf43b7 100644 --- a/test/internal/unit/main.test.ts +++ b/test/internal/unit/main.test.ts @@ -855,4 +855,55 @@ describe("Main functions", () => { await shutdownMicrosoftOpenTelemetry(); }); + + it("console exporters auto-enabled when no built-in exporters are active", async () => { + const { useMicrosoftOpenTelemetry, shutdownMicrosoftOpenTelemetry } = + await import("../../../src/index.js"); + useMicrosoftOpenTelemetry({ azureMonitor: { enabled: false } }); + + const internalSdk = _getSdkInstance(); + const meterProvider = (internalSdk as any)["_meterProvider"]; + const metricReaders = meterProvider?.["_sharedState"]?.metricCollectors || []; + assert.isAbove(metricReaders.length, 0, "Console metric reader should be auto-enabled"); + + await shutdownMicrosoftOpenTelemetry(); + }); + + it("enableConsoleExporters=false suppresses console exporters", async () => { + const { useMicrosoftOpenTelemetry, shutdownMicrosoftOpenTelemetry } = + await import("../../../src/index.js"); + useMicrosoftOpenTelemetry({ + azureMonitor: { enabled: false }, + enableConsoleExporters: false, + }); + + const internalSdk = _getSdkInstance(); + const meterProvider = (internalSdk as any)["_meterProvider"]; + const metricReaders = meterProvider?.["_sharedState"]?.metricCollectors || []; + assert.strictEqual(metricReaders.length, 0, "No metric readers when console is suppressed"); + + await shutdownMicrosoftOpenTelemetry(); + }); + + it("enableConsoleExporters=true alongside Azure Monitor", async () => { + const { useMicrosoftOpenTelemetry, shutdownMicrosoftOpenTelemetry } = + await import("../../../src/index.js"); + useMicrosoftOpenTelemetry({ + enableConsoleExporters: true, + azureMonitor: { + azureMonitorExporterOptions: { + connectionString: + "InstrumentationKey=00000000-0000-0000-0000-000000000000;IngestionEndpoint=https://localhost", + }, + }, + }); + + const internalSdk = _getSdkInstance(); + const meterProvider = (internalSdk as any)["_meterProvider"]; + const metricReaders = meterProvider?.["_sharedState"]?.metricCollectors || []; + // Should have both Azure Monitor metric reader and console metric reader + assert.isAbove(metricReaders.length, 1, "Should have Azure Monitor + Console metric readers"); + + await shutdownMicrosoftOpenTelemetry(); + }); });