Skip to content

Commit 5b80904

Browse files
committed
debugging App Insights to Log Analytics 4
1 parent 0eb872e commit 5b80904

2 files changed

Lines changed: 36 additions & 106 deletions

File tree

src/instrumentation.ts

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* PURPOSE:
77
* Initializes Azure Monitor OpenTelemetry SDK for automatic distributed tracing,
88
* metrics collection, and log correlation in Azure Application Insights.
9-
* Also initializes the classic Application Insights SDK for custom events.
109
*
1110
* CRITICAL REQUIREMENT:
1211
* This module MUST be imported BEFORE any other application code. OpenTelemetry
@@ -35,7 +34,6 @@
3534
*/
3635

3736
import { useAzureMonitor, AzureMonitorOpenTelemetryOptions } from '@azure/monitor-opentelemetry';
38-
import appInsights from 'applicationinsights';
3937

4038
// Configure Azure Monitor OpenTelemetry
4139
const options: AzureMonitorOpenTelemetryOptions = {
@@ -55,23 +53,14 @@ const options: AzureMonitorOpenTelemetryOptions = {
5553
const connectionString = process.env.APPLICATIONINSIGHTS_CONNECTION_STRING;
5654

5755
if (connectionString) {
58-
console.log('[PerfSimNode] Initializing Azure Monitor OpenTelemetry...');
59-
useAzureMonitor(options);
60-
console.log('[PerfSimNode] Azure Monitor OpenTelemetry initialized');
61-
62-
// Also initialize the classic Application Insights SDK for custom events (trackEvent)
63-
// OpenTelemetry handles auto-instrumentation, but we need the classic SDK for custom events
64-
console.log('[PerfSimNode] Initializing Application Insights SDK for custom events...');
65-
appInsights.setup(connectionString)
66-
.setAutoCollectRequests(false) // Disabled - OpenTelemetry handles this
67-
.setAutoCollectPerformance(false, false) // Disabled - OpenTelemetry handles this
68-
.setAutoCollectExceptions(false) // Disabled - OpenTelemetry handles this
69-
.setAutoCollectDependencies(false) // Disabled - OpenTelemetry handles this
70-
.setAutoCollectConsole(false)
71-
.setUseDiskRetryCaching(true)
72-
.setSendLiveMetrics(false)
73-
.start();
74-
console.log('[PerfSimNode] Application Insights SDK initialized');
56+
try {
57+
console.log('[PerfSimNode] Initializing Azure Monitor OpenTelemetry...');
58+
useAzureMonitor(options);
59+
console.log('[PerfSimNode] Azure Monitor OpenTelemetry initialized');
60+
} catch (error) {
61+
console.error('[PerfSimNode] Failed to initialize Azure Monitor OpenTelemetry:', error);
62+
// Continue without OpenTelemetry - app should still work
63+
}
7564
} else {
7665
console.log('[PerfSimNode] APPLICATIONINSIGHTS_CONNECTION_STRING not set - Application Insights disabled');
7766
}

src/services/simulation-context.service.ts

Lines changed: 28 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,44 @@
44
* =============================================================================
55
*
66
* PURPOSE:
7-
* Tracks simulation lifecycle events in Azure Application Insights, enabling
8-
* users to filter and correlate telemetry by simulation ID using KQL queries.
7+
* Sets simulation context on OpenTelemetry spans, enabling users to filter
8+
* and correlate telemetry by simulation ID using KQL queries in App Insights.
99
*
1010
* HOW IT WORKS:
11-
* 1. When a simulation starts, tracks a "SimulationStarted" custom event
12-
* 2. When a simulation ends, tracks a "SimulationEnded" custom event
13-
* 3. Both events include SimulationId and SimulationType as properties
14-
* 4. Also sets OpenTelemetry span attributes for trace correlation
11+
* 1. When a simulation starts, sets SimulationId and SimulationType as span attributes
12+
* 2. These attributes flow to Application Insights as customDimensions
13+
* 3. Users can filter traces, requests, and dependencies by simulation ID
1514
*
1615
* APPLICATION INSIGHTS INTEGRATION:
17-
* - Uses the applicationinsights SDK's trackEvent() for custom events
18-
* - Custom events appear in the customEvents table in Log Analytics
19-
* - Properties appear in customDimensions for KQL filtering
16+
* - Uses OpenTelemetry span attributes (via @azure/monitor-opentelemetry)
17+
* - Attributes appear in customDimensions on traces and requests tables
2018
* - Works transparently — if App Insights is not configured, calls are no-ops
2119
*
2220
* KQL QUERY EXAMPLES:
23-
* // Find all simulation events
24-
* customEvents
25-
* | where name in ("SimulationStarted", "SimulationEnded")
26-
* | project timestamp, name, customDimensions.SimulationId, customDimensions.SimulationType
27-
*
28-
* // Find all events for a specific simulation
29-
* customEvents
21+
* // Find all requests for a specific simulation
22+
* requests
3023
* | where customDimensions.SimulationId == "abc123-def4-..."
3124
* | order by timestamp desc
3225
*
33-
* // Find all CPU stress simulations
34-
* customEvents
26+
* // Find all CPU stress simulation traces
27+
* traces
3528
* | where customDimensions.SimulationType == "CPU_STRESS"
3629
* | order by timestamp desc
3730
*
31+
* // Find dependencies triggered during a simulation
32+
* dependencies
33+
* | where customDimensions.SimulationId == "abc123-def4-..."
34+
* | order by timestamp desc
35+
*
3836
* PORTING NOTES:
39-
* - .NET: Use TelemetryClient.TrackEvent()
40-
* - Java: Use TelemetryClient.trackEvent()
41-
* - Python: Use azure.monitor.opentelemetry or applicationinsights SDK
37+
* - .NET: Use Activity.Current?.SetTag() or TelemetryClient
38+
* - Java: Use OpenTelemetry Span.setAttribute()
39+
* - Python: Use opentelemetry span.set_attribute()
4240
*
4341
* @module services/simulation-context
4442
*/
4543

4644
import { trace, SpanStatusCode } from '@opentelemetry/api';
47-
import appInsights from 'applicationinsights';
4845

4946
/**
5047
* Simulation context information.
@@ -58,29 +55,10 @@ export interface SimulationContextInfo {
5855
* Service for tracking simulation context and correlating with Application Insights.
5956
*
6057
* This service provides methods to:
61-
* - Track simulation start/end as custom events in App Insights
6258
* - Set simulation context on the current OpenTelemetry span
6359
* - Enable filtering of App Insights telemetry by simulation ID
6460
*/
6561
class SimulationContextServiceClass {
66-
/**
67-
* Gets the Application Insights telemetry client.
68-
* The client is initialized in instrumentation.ts at application startup.
69-
* Returns null if App Insights is not configured.
70-
*/
71-
private getClient(): appInsights.TelemetryClient | null {
72-
try {
73-
// Check if appInsights module and defaultClient exist
74-
if (appInsights && appInsights.defaultClient) {
75-
return appInsights.defaultClient;
76-
}
77-
return null;
78-
} catch {
79-
// App Insights not initialized - return null silently
80-
return null;
81-
}
82-
}
83-
8462
/**
8563
* Sets the simulation context on the current OpenTelemetry span.
8664
*
@@ -91,10 +69,6 @@ class SimulationContextServiceClass {
9169
* @param simulationType - Type of simulation (e.g., 'CPU_STRESS', 'MEMORY_PRESSURE')
9270
*/
9371
setContext(simulationId: string, simulationType: string): void {
94-
// Track the SimulationStarted custom event
95-
this.trackCustomEvent('SimulationStarted', simulationId, simulationType);
96-
97-
// Also set OpenTelemetry span attributes for trace correlation
9872
try {
9973
const activeSpan = trace.getActiveSpan();
10074
if (activeSpan) {
@@ -108,51 +82,21 @@ class SimulationContextServiceClass {
10882
}
10983

11084
/**
111-
* Tracks a simulation ended event.
85+
* Tracks a simulation ended event by setting attributes on the current span.
11286
*
11387
* @param simulationId - Unique identifier for the simulation
11488
* @param simulationType - Type of simulation
11589
*/
11690
trackSimulationEnded(simulationId: string, simulationType: string): void {
117-
this.trackCustomEvent('SimulationEnded', simulationId, simulationType);
118-
}
119-
120-
/**
121-
* Tracks a custom event in Application Insights.
122-
*
123-
* @param eventName - Name of the event (e.g., 'SimulationStarted', 'SimulationEnded')
124-
* @param simulationId - Unique identifier for the simulation
125-
* @param simulationType - Type of simulation
126-
* @param additionalProperties - Optional additional properties to include
127-
*/
128-
private trackCustomEvent(
129-
eventName: string,
130-
simulationId: string,
131-
simulationType: string,
132-
additionalProperties?: Record<string, string>
133-
): void {
134-
const client = this.getClient();
135-
if (!client) {
136-
console.log(`[SimulationContext] No client available - skipping ${eventName} event for ${simulationType}`);
137-
return;
138-
}
139-
14091
try {
141-
client.trackEvent({
142-
name: eventName,
143-
properties: {
144-
SimulationId: simulationId,
145-
SimulationType: simulationType,
146-
...additionalProperties,
147-
},
148-
});
149-
150-
// Flush immediately to ensure event is sent (don't wait for batching)
151-
client.flush();
152-
153-
console.log(`[SimulationContext] Tracked and flushed ${eventName} for ${simulationType} (${simulationId.substring(0, 8)}...)`);
92+
const activeSpan = trace.getActiveSpan();
93+
if (activeSpan) {
94+
activeSpan.setAttribute('SimulationEnded', true);
95+
activeSpan.setAttribute('SimulationId', simulationId);
96+
activeSpan.setAttribute('SimulationType', simulationType);
97+
}
15498
} catch (error) {
155-
console.error(`[SimulationContext] Failed to track ${eventName}:`, error);
99+
console.debug('[SimulationContext] Failed to track simulation ended:', error);
156100
}
157101
}
158102

@@ -164,9 +108,7 @@ class SimulationContextServiceClass {
164108
* @returns A function to call when the simulation ends
165109
*/
166110
trackSimulationStart(simulationId: string, simulationType: string): () => void {
167-
this.trackCustomEvent('SimulationStarted', simulationId, simulationType);
168-
169-
// Also start an OpenTelemetry span for trace correlation
111+
// Start an OpenTelemetry span for trace correlation
170112
let span: ReturnType<ReturnType<typeof trace.getTracer>['startSpan']> | null = null;
171113
try {
172114
const tracer = trace.getTracer('perfsimnode');
@@ -182,7 +124,6 @@ class SimulationContextServiceClass {
182124

183125
// Return cleanup function
184126
return () => {
185-
this.trackCustomEvent('SimulationEnded', simulationId, simulationType);
186127
if (span) {
187128
span.setStatus({ code: SpanStatusCode.OK });
188129
span.end();

0 commit comments

Comments
 (0)