Repository: microsoft/ApplicationInsights-node.js
Pull request #1425 (2025-04-28 05:30:32)

Add Shim Support for Full Request and Dependency Filtering
https://github.com/microsoft/ApplicationInsights-node.js/issues/1422

Adds support for disabling requests and dependencies across all instrumentations rather than just HTTP.


Patch:
diff --git a/src/main.ts b/src/main.ts
index 3fef3f9..b2eda00 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -17,6 +17,7 @@ import { AZURE_MONITOR_STATSBEAT_FEATURES, AzureMonitorOpenTelemetryOptions } fr
 import { ApplicationInsightsConfig } from "./shared/configuration/config";
 import { LogApi } from "./shim/logsApi";
 import { StatsbeatFeature, StatsbeatInstrumentation } from "./shim/types";
+import { RequestSpanProcessor } from "./traces/requestProcessor";
 
 let autoCollectLogs: AutoCollectLogs;
 let exceptions: AutoCollectExceptions;
@@ -31,6 +32,8 @@ export function useAzureMonitor(options?: AzureMonitorOpenTelemetryOptions) {
         instrumentation: StatsbeatInstrumentation.NONE,
         feature: StatsbeatFeature.SHIM
     });
+    // Allows for full filtering of dependency/request spans
+    options.spanProcessors = [new RequestSpanProcessor(options.enableAutoCollectDependencies, options.enableAutoCollectRequests)];
     distroUseAzureMonitor(options);
     const internalConfig = new ApplicationInsightsConfig(options);
     const logApi = new LogApi(logs.getLogger("ApplicationInsightsLogger"));
diff --git a/src/shim/shim-config.ts b/src/shim/shim-config.ts
index f099c16..11f05ad 100644
--- a/src/shim/shim-config.ts
+++ b/src/shim/shim-config.ts
@@ -186,6 +186,14 @@ class Config implements IConfig {
             options.enableAutoCollectExceptions = this.enableAutoCollectExceptions;
         }
 
+        if (typeof (this.enableAutoCollectRequests) === "boolean") {
+            options.enableAutoCollectRequests = this.enableAutoCollectRequests;
+        }
+
+        if (typeof (this.enableAutoCollectDependencies) === "boolean") {
+            options.enableAutoCollectDependencies = this.enableAutoCollectDependencies;
+        }
+
         if (this.enableAutoCollectDependencies === false && this.enableAutoCollectRequests === false) {
             options.instrumentationOptions.http.enabled = false;
         }
diff --git a/src/traces/requestProcessor.ts b/src/traces/requestProcessor.ts
new file mode 100644
index 0000000..779d639
--- /dev/null
+++ b/src/traces/requestProcessor.ts
@@ -0,0 +1,44 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT license.
+
+import { Context, SpanKind, TraceFlags } from "@opentelemetry/api";
+import { ReadableSpan, Span, SpanProcessor } from "@opentelemetry/sdk-trace-base";
+
+/**
+ * Azure Monitor Incoming & Outgoing Request Processor.
+ * @internal
+ */
+export class RequestSpanProcessor implements SpanProcessor {
+    private _enableDependencyTelemetry: boolean;
+    private _enableRequestTelemetry: boolean;
+
+    constructor(enableDependencyTelemetry: boolean, enableRequestTelemetry: boolean) {
+        this._enableDependencyTelemetry = enableDependencyTelemetry;
+        this._enableRequestTelemetry = enableRequestTelemetry;
+    }
+
+    forceFlush(): Promise<void> {
+        return Promise.resolve();
+    }
+
+    onStart(span: Span, _context: Context): void {
+        if (this._enableDependencyTelemetry === false) {
+            if (span.kind === SpanKind.CLIENT || span.kind === SpanKind.PRODUCER) {
+                span.spanContext().traceFlags = TraceFlags.SAMPLED;
+            }
+        }
+        if (this._enableRequestTelemetry === false) {
+            if (span.kind === SpanKind.SERVER || span.kind === SpanKind.CONSUMER) {
+                span.spanContext().traceFlags = TraceFlags.SAMPLED;
+            }
+        }
+    }
+
+    onEnd(span: ReadableSpan): void {
+        return;
+    }
+
+    shutdown(): Promise<void> {
+        return Promise.resolve();
+    }
+}
\ No newline at end of file
diff --git a/src/types.ts b/src/types.ts
index cf897c1..8e3267e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -31,6 +31,8 @@ export interface AzureMonitorOpenTelemetryOptions extends DistroOptions {
    * if true performance counters will be collected every second and sent to Azure Monitor
    */
   enableAutoCollectPerformance?: boolean;
+  enableAutoCollectDependencies?: boolean;
+  enableAutoCollectRequests?: boolean;
 }
 
 export interface InstrumentationOptions extends DistroInstrumentationOptions {


Test patch:
diff --git a/test/unitTests/agent/aksLoader.tests.ts b/test/unitTests/agent/aksLoader.tests.ts
index 52e844b..b0faa37 100644
--- a/test/unitTests/agent/aksLoader.tests.ts
+++ b/test/unitTests/agent/aksLoader.tests.ts
@@ -57,7 +57,7 @@ describe("agent/AKSLoader", () => {
         assert.equal(meterProvider["_sharedState"]["metricCollectors"][0]["_metricReader"]["_exporter"].constructor.name, "AzureMonitorMetricExporter");
         let tracerProvider = ((trace.getTracerProvider() as ProxyTracerProvider).getDelegate()) as any;
         assert.equal(tracerProvider.constructor.name, "NodeTracerProvider");
-        assert.equal(tracerProvider["_registeredSpanProcessors"][1]["_exporter"].constructor.name, "AzureMonitorTraceExporter");
+        assert.equal(tracerProvider["_registeredSpanProcessors"][2]["_exporter"].constructor.name, "AzureMonitorTraceExporter");
         let loggerProvider = logs.getLoggerProvider() as any;
         assert.equal(loggerProvider.constructor.name, "LoggerProvider");
         assert.equal(loggerProvider["_sharedState"]["registeredLogRecordProcessors"][1]["_exporter"].constructor.name, "AzureMonitorLogExporter");
diff --git a/test/unitTests/main.tests.ts b/test/unitTests/main.tests.ts
index cbc89e2..f3f616f 100644
--- a/test/unitTests/main.tests.ts
+++ b/test/unitTests/main.tests.ts
@@ -30,8 +30,8 @@ describe("ApplicationInsightsClient", () => {
 
         let tracerProvider = ((trace.getTracerProvider() as ProxyTracerProvider).getDelegate() as any);
         let spanProcessors = tracerProvider["_registeredSpanProcessors"];
-        assert.ok(spanProcessors.length == 3, "wrong number of spanProcessors");
-        otlpExporter = spanProcessors[2]["_exporter"];
+        assert.ok(spanProcessors.length == 4, "wrong number of spanProcessors");
+        otlpExporter = spanProcessors[3]["_exporter"];
         assert.ok(otlpExporter instanceof OTLPTraceExporter, "wrong exporter");
 
         let loggerProvider = ((logs.getLoggerProvider() as LoggerProvider) as any);
diff --git a/test/unitTests/shim/applicationInsights.tests.ts b/test/unitTests/shim/applicationInsights.tests.ts
index 71557cc..ac794f2 100644
--- a/test/unitTests/shim/applicationInsights.tests.ts
+++ b/test/unitTests/shim/applicationInsights.tests.ts
@@ -93,6 +93,15 @@ describe("ApplicationInsights", () => {
             assert.equal(JSON.stringify((appInsights.defaultClient["_options"].instrumentationOptions as InstrumentationOptions).winston), JSON.stringify({ enabled: false }));
         });
 
+        it("should set dependency and request collection", () => {
+            appInsights.setup(connString)
+                .setAutoCollectRequests(true)
+                .setAutoCollectDependencies(false)
+            appInsights.start();
+            assert.equal(appInsights.defaultClient["_options"].enableAutoCollectDependencies, false);
+            assert.equal(appInsights.defaultClient["_options"].enableAutoCollectRequests, true);
+        });
+
         describe("#CorrelationContext", () => {
             it("should return context once AppInsights is intialized", () => {
                 appInsights.setup(connString).start();