@cuylabs/agent-microsoft-opentelemetry 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,966 @@
1
+ // src/errors.ts
2
+ var MicrosoftOpenTelemetryModuleLoadError = class extends Error {
3
+ constructor(message, options) {
4
+ super(message, options);
5
+ this.name = "MicrosoftOpenTelemetryModuleLoadError";
6
+ }
7
+ };
8
+ var MicrosoftOpenTelemetryResourceModuleLoadError = class extends Error {
9
+ constructor(message, options) {
10
+ super(message, options);
11
+ this.name = "MicrosoftOpenTelemetryResourceModuleLoadError";
12
+ }
13
+ };
14
+
15
+ // src/internal/values.ts
16
+ function isNonEmpty(value) {
17
+ return typeof value === "string" && value.trim().length > 0;
18
+ }
19
+ function firstNonEmpty(...values) {
20
+ for (const value of values) {
21
+ if (isNonEmpty(value)) {
22
+ return value.trim();
23
+ }
24
+ }
25
+ return void 0;
26
+ }
27
+ function setPair(pairs, key, value) {
28
+ if (value === null || value === void 0) {
29
+ return;
30
+ }
31
+ const normalized = String(value).trim();
32
+ if (normalized) {
33
+ pairs[key] = normalized;
34
+ }
35
+ }
36
+ function parseOptionalNumber(value) {
37
+ if (!isNonEmpty(value)) {
38
+ return void 0;
39
+ }
40
+ const parsed = Number(value);
41
+ return Number.isFinite(parsed) ? parsed : void 0;
42
+ }
43
+ function parseOptionalBoolean(value) {
44
+ if (!isNonEmpty(value)) {
45
+ return void 0;
46
+ }
47
+ const normalized = value.trim().toLowerCase();
48
+ if (["1", "true", "yes", "on"].includes(normalized)) {
49
+ return true;
50
+ }
51
+ if (["0", "false", "no", "off"].includes(normalized)) {
52
+ return false;
53
+ }
54
+ return void 0;
55
+ }
56
+ function parseList(value) {
57
+ if (!isNonEmpty(value)) {
58
+ return [];
59
+ }
60
+ return value.split(/[,\s]+/).map((item) => item.trim()).filter(Boolean);
61
+ }
62
+ function readPath(value, path) {
63
+ let current = value;
64
+ for (const key of path) {
65
+ if (!current || typeof current !== "object") {
66
+ return void 0;
67
+ }
68
+ current = current[key];
69
+ }
70
+ return typeof current === "string" && current.trim() ? current.trim() : void 0;
71
+ }
72
+ function callOptionalStringMethod(value) {
73
+ if (typeof value !== "function") {
74
+ return void 0;
75
+ }
76
+ try {
77
+ const result = value();
78
+ return typeof result === "string" && result.trim() ? result.trim() : void 0;
79
+ } catch {
80
+ return void 0;
81
+ }
82
+ }
83
+ function callOptionalBooleanMethod(value) {
84
+ if (typeof value !== "function") {
85
+ return false;
86
+ }
87
+ try {
88
+ return value() === true;
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ function parseServiceEndpoint(serviceUrl) {
94
+ if (!isNonEmpty(serviceUrl)) {
95
+ return void 0;
96
+ }
97
+ try {
98
+ const url = new URL(serviceUrl);
99
+ return {
100
+ serverAddress: url.hostname,
101
+ serverPort: url.port ? Number(url.port) : url.protocol === "http:" ? 80 : 443
102
+ };
103
+ } catch {
104
+ return void 0;
105
+ }
106
+ }
107
+
108
+ // src/auth/oauth-token-endpoint.ts
109
+ var CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
110
+ var DEFAULT_TOKEN_LIFETIME_MS = 55 * 60 * 1e3;
111
+ async function requestClientSecretToken(client, request, extra) {
112
+ const body = new URLSearchParams({
113
+ grant_type: "client_credentials",
114
+ client_id: request.clientId,
115
+ client_secret: request.clientSecret,
116
+ scope: request.scope
117
+ });
118
+ if (extra?.fmiPath) {
119
+ body.set("fmi_path", extra.fmiPath);
120
+ }
121
+ return await requestToken(client, body);
122
+ }
123
+ async function requestClientAssertionToken(client, request, extra) {
124
+ const body = new URLSearchParams({
125
+ grant_type: "client_credentials",
126
+ client_id: request.clientId,
127
+ client_assertion: request.clientAssertion,
128
+ client_assertion_type: CLIENT_ASSERTION_TYPE,
129
+ scope: request.scope
130
+ });
131
+ if (extra?.fmiPath) {
132
+ body.set("fmi_path", extra.fmiPath);
133
+ }
134
+ return await requestToken(client, body);
135
+ }
136
+ async function requestToken(client, body) {
137
+ const response = await client.fetch(
138
+ `https://login.microsoftonline.com/${encodeURIComponent(
139
+ client.tenantId
140
+ )}/oauth2/v2.0/token`,
141
+ {
142
+ method: "POST",
143
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
144
+ body: body.toString()
145
+ }
146
+ );
147
+ const payload = parseTokenEndpointResponse(await response.text());
148
+ if (!response.ok || !payload.access_token) {
149
+ throw new Error(
150
+ payload.error_description || payload.error || `token endpoint returned HTTP ${response.status}`
151
+ );
152
+ }
153
+ const expiresInMs = typeof payload.expires_in === "number" && payload.expires_in > 0 ? payload.expires_in * 1e3 : DEFAULT_TOKEN_LIFETIME_MS;
154
+ return {
155
+ accessToken: payload.access_token,
156
+ expiresAtMs: Date.now() + expiresInMs
157
+ };
158
+ }
159
+ function parseTokenEndpointResponse(body) {
160
+ if (!body) {
161
+ return {};
162
+ }
163
+ try {
164
+ return JSON.parse(body);
165
+ } catch {
166
+ return { error_description: body };
167
+ }
168
+ }
169
+
170
+ // src/auth/s2s-token-resolver.ts
171
+ var MICROSOFT_A365_FMI_SCOPE = "api://AzureADTokenExchange/.default";
172
+ var MICROSOFT_A365_OBSERVABILITY_SCOPE = "api://9b975845-388f-4429-889e-eab1ef63949c/.default";
173
+ var DEFAULT_REFRESH_SKEW_MS = 5 * 60 * 1e3;
174
+ function createMicrosoftA365S2STokenResolver(options) {
175
+ const normalized = normalizeOptions(options);
176
+ const cache = /* @__PURE__ */ new Map();
177
+ return async (agentId, tenantId, authScopes) => {
178
+ const request = {
179
+ ...normalized,
180
+ agentId: firstNonEmpty(agentId, normalized.agentId) ?? "",
181
+ tenantId: firstNonEmpty(tenantId, normalized.tenantId) ?? "",
182
+ observabilityScope: firstNonEmpty(authScopes?.[0], normalized.observabilityScope) ?? MICROSOFT_A365_OBSERVABILITY_SCOPE
183
+ };
184
+ const cacheKey = `${request.tenantId}:${request.agentId}:${request.observabilityScope}`;
185
+ const cached = cache.get(cacheKey);
186
+ if (cached && cached.expiresAtMs - request.refreshSkewMs > Date.now()) {
187
+ return cached.accessToken;
188
+ }
189
+ try {
190
+ const token = await acquireObservabilityToken(request);
191
+ cache.set(cacheKey, token);
192
+ return token.accessToken;
193
+ } catch (error) {
194
+ request.logger?.warn("Failed to acquire Microsoft A365 S2S token", {
195
+ error: error instanceof Error ? error.message : String(error),
196
+ useManagedIdentity: request.useManagedIdentity
197
+ });
198
+ return null;
199
+ }
200
+ };
201
+ }
202
+ function normalizeOptions(options) {
203
+ return {
204
+ tenantId: requireNonEmpty("tenantId", options.tenantId),
205
+ agentId: requireNonEmpty("agentId", options.agentId),
206
+ blueprintClientId: requireNonEmpty(
207
+ "blueprintClientId",
208
+ options.blueprintClientId
209
+ ),
210
+ ...options.blueprintClientSecret ? { blueprintClientSecret: options.blueprintClientSecret } : {},
211
+ useManagedIdentity: options.useManagedIdentity ?? false,
212
+ ...options.managedIdentityAssertionProvider ? {
213
+ managedIdentityAssertionProvider: options.managedIdentityAssertionProvider
214
+ } : {},
215
+ allowManagedIdentityClientSecretFallback: options.allowManagedIdentityClientSecretFallback ?? true,
216
+ observabilityScope: options.observabilityScope ?? MICROSOFT_A365_OBSERVABILITY_SCOPE,
217
+ fmiScope: options.fmiScope ?? MICROSOFT_A365_FMI_SCOPE,
218
+ refreshSkewMs: options.refreshSkewMs ?? DEFAULT_REFRESH_SKEW_MS,
219
+ ...options.logger ? { logger: options.logger } : {},
220
+ fetch: options.fetch ?? globalThis.fetch.bind(globalThis)
221
+ };
222
+ }
223
+ async function acquireObservabilityToken(options) {
224
+ const fmiToken = await acquireFmiToken(options);
225
+ return await requestClientAssertionToken(options, {
226
+ clientId: options.agentId,
227
+ clientAssertion: fmiToken.accessToken,
228
+ scope: options.observabilityScope
229
+ });
230
+ }
231
+ async function acquireFmiToken(options) {
232
+ if (options.useManagedIdentity) {
233
+ try {
234
+ const assertion = await options.managedIdentityAssertionProvider?.();
235
+ if (!assertion) {
236
+ throw new Error(
237
+ "managed identity assertion provider returned no token"
238
+ );
239
+ }
240
+ return await requestClientAssertionToken(
241
+ options,
242
+ {
243
+ clientId: options.blueprintClientId,
244
+ clientAssertion: assertion,
245
+ scope: options.fmiScope
246
+ },
247
+ { fmiPath: options.agentId }
248
+ );
249
+ } catch (error) {
250
+ if (!options.allowManagedIdentityClientSecretFallback || !options.blueprintClientSecret) {
251
+ throw error;
252
+ }
253
+ options.logger?.warn(
254
+ "Managed identity FMI token exchange failed; falling back to blueprint client secret",
255
+ { error: error instanceof Error ? error.message : String(error) }
256
+ );
257
+ }
258
+ }
259
+ return await requestClientSecretToken(
260
+ options,
261
+ {
262
+ clientId: options.blueprintClientId,
263
+ clientSecret: requireNonEmpty(
264
+ "blueprintClientSecret",
265
+ options.blueprintClientSecret
266
+ ),
267
+ scope: options.fmiScope
268
+ },
269
+ { fmiPath: options.agentId }
270
+ );
271
+ }
272
+ function requireNonEmpty(name, value) {
273
+ const normalized = value?.trim();
274
+ if (!normalized) {
275
+ throw new Error(`${name} is required`);
276
+ }
277
+ return normalized;
278
+ }
279
+
280
+ // src/auth/env.ts
281
+ function resolveMicrosoftOpenTelemetryEnvironment(env = process.env) {
282
+ const reader = createEnvReader(env);
283
+ const enableObservabilityExporter = parseOptionalBoolean(
284
+ reader(
285
+ "ENABLE_A365_OBSERVABILITY_EXPORTER",
286
+ "A365_OBSERVABILITY_EXPORTER_ENABLED",
287
+ "agent365Observability__exporterEnabled"
288
+ )
289
+ );
290
+ return {
291
+ resource: {
292
+ serviceName: reader(
293
+ "MICROSOFT_OTEL_SERVICE_NAME",
294
+ "OTEL_SERVICE_NAME",
295
+ "A365_OBSERVABILITY_SERVICE_NAME"
296
+ ),
297
+ serviceVersion: reader(
298
+ "MICROSOFT_OTEL_SERVICE_VERSION",
299
+ "OTEL_SERVICE_VERSION",
300
+ "A365_OBSERVABILITY_SERVICE_VERSION"
301
+ ),
302
+ serviceNamespace: reader(
303
+ "MICROSOFT_OTEL_SERVICE_NAMESPACE",
304
+ "OTEL_SERVICE_NAMESPACE"
305
+ ),
306
+ serviceInstanceId: reader(
307
+ "MICROSOFT_OTEL_SERVICE_INSTANCE_ID",
308
+ "OTEL_SERVICE_INSTANCE_ID"
309
+ )
310
+ },
311
+ a365: {
312
+ enabled: parseOptionalBoolean(
313
+ reader("MICROSOFT_OTEL_A365_ENABLED", "A365_OBSERVABILITY_ENABLED")
314
+ ),
315
+ enableObservabilityExporter,
316
+ exporterEnabled: enableObservabilityExporter,
317
+ clusterCategory: reader(
318
+ "A365_OBSERVABILITY_CLUSTER_CATEGORY",
319
+ "CLUSTER_CATEGORY"
320
+ ),
321
+ domainOverride: reader(
322
+ "A365_OBSERVABILITY_DOMAIN_OVERRIDE",
323
+ "agent365Observability__domainOverride"
324
+ ),
325
+ authScopes: firstDefinedList(
326
+ parseList(
327
+ reader(
328
+ "A365_OBSERVABILITY_AUTHENTICATION_SCOPES",
329
+ "A365_OBSERVABILITY_SCOPES_OVERRIDE",
330
+ "agent365Observability__authenticationScopes"
331
+ )
332
+ )
333
+ ),
334
+ observabilityScopeOverride: reader(
335
+ "A365_OBSERVABILITY_SCOPE_OVERRIDE",
336
+ "A365_OBSERVABILITY_SCOPE",
337
+ "agent365Observability__observabilityScope"
338
+ ),
339
+ logLevel: reader(
340
+ "A365_OBSERVABILITY_LOG_LEVEL",
341
+ "agent365Observability__logLevel"
342
+ ),
343
+ useS2SEndpoint: parseOptionalBoolean(
344
+ reader(
345
+ "A365_OBSERVABILITY_USE_S2S_ENDPOINT",
346
+ "agent365Observability__useS2SEndpoint"
347
+ )
348
+ ),
349
+ maxQueueSize: parseOptionalNumber(
350
+ reader("A365_OBSERVABILITY_MAX_QUEUE_SIZE")
351
+ ),
352
+ scheduledDelayMilliseconds: parseOptionalNumber(
353
+ reader("A365_OBSERVABILITY_SCHEDULED_DELAY_MS")
354
+ ),
355
+ exporterTimeoutMilliseconds: parseOptionalNumber(
356
+ reader("A365_OBSERVABILITY_EXPORTER_TIMEOUT_MS")
357
+ ),
358
+ httpRequestTimeoutMilliseconds: parseOptionalNumber(
359
+ reader("A365_OBSERVABILITY_HTTP_REQUEST_TIMEOUT_MS")
360
+ ),
361
+ maxExportBatchSize: parseOptionalNumber(
362
+ reader("A365_OBSERVABILITY_MAX_EXPORT_BATCH_SIZE")
363
+ ),
364
+ maxPayloadBytes: parseOptionalNumber(
365
+ reader("A365_OBSERVABILITY_MAX_PAYLOAD_BYTES")
366
+ )
367
+ },
368
+ azureMonitorEnabled: parseOptionalBoolean(
369
+ reader("MICROSOFT_OTEL_AZURE_MONITOR_ENABLED")
370
+ ),
371
+ instrumentationProfile: parseInstrumentationProfile(
372
+ reader("MICROSOFT_OTEL_INSTRUMENTATION_PROFILE")
373
+ ),
374
+ enableConsoleExporters: parseOptionalBoolean(
375
+ reader("MICROSOFT_OTEL_ENABLE_CONSOLE_EXPORTERS")
376
+ )
377
+ };
378
+ }
379
+ function createMicrosoftA365S2STokenResolverFromEnv(options = {}) {
380
+ const env = options.env ?? process.env;
381
+ const reader = createEnvReader(env);
382
+ const tenantId = requireValue(
383
+ "tenantId",
384
+ firstNonEmpty(
385
+ options.tenantId,
386
+ reader("A365_OBSERVABILITY_TENANT_ID", "agent365Observability__tenantId")
387
+ )
388
+ );
389
+ const agentId = requireValue(
390
+ "agentId",
391
+ firstNonEmpty(
392
+ options.agentId,
393
+ reader("A365_OBSERVABILITY_AGENT_ID", "agent365Observability__agentId")
394
+ )
395
+ );
396
+ const blueprintClientId = requireValue(
397
+ "blueprintClientId",
398
+ firstNonEmpty(
399
+ options.blueprintClientId,
400
+ reader(
401
+ "A365_OBSERVABILITY_BLUEPRINT_CLIENT_ID",
402
+ "A365_OBSERVABILITY_CLIENT_ID",
403
+ "agent365Observability__clientId",
404
+ "agent365Observability__agentBlueprintId"
405
+ )
406
+ )
407
+ );
408
+ return createMicrosoftA365S2STokenResolver({
409
+ ...options,
410
+ tenantId,
411
+ agentId,
412
+ blueprintClientId,
413
+ blueprintClientSecret: firstNonEmpty(
414
+ options.blueprintClientSecret,
415
+ reader(
416
+ "A365_OBSERVABILITY_BLUEPRINT_CLIENT_SECRET",
417
+ "A365_OBSERVABILITY_CLIENT_SECRET",
418
+ "agent365Observability__clientSecret"
419
+ )
420
+ ),
421
+ useManagedIdentity: options.useManagedIdentity ?? parseOptionalBoolean(
422
+ reader(
423
+ "A365_OBSERVABILITY_USE_MANAGED_IDENTITY",
424
+ "agent365Observability__useManagedIdentity"
425
+ )
426
+ ) ?? Boolean(options.managedIdentityAssertionProvider),
427
+ observabilityScope: firstNonEmpty(
428
+ options.observabilityScope,
429
+ reader(
430
+ "A365_OBSERVABILITY_SCOPE",
431
+ "A365_OBSERVABILITY_SCOPES",
432
+ "agent365Observability__observabilityScope"
433
+ )
434
+ ),
435
+ fmiScope: firstNonEmpty(
436
+ options.fmiScope,
437
+ reader(
438
+ "A365_OBSERVABILITY_FMI_SCOPE",
439
+ "A365_FMI_SCOPE",
440
+ "agent365Observability__fmiScope"
441
+ )
442
+ )
443
+ });
444
+ }
445
+ function createEnvReader(env) {
446
+ const normalized = /* @__PURE__ */ new Map();
447
+ for (const [key, value] of Object.entries(env)) {
448
+ if (value !== void 0) {
449
+ normalized.set(key.toLowerCase(), value);
450
+ }
451
+ }
452
+ return (...names) => {
453
+ for (const name of names) {
454
+ const value = firstNonEmpty(
455
+ env[name],
456
+ normalized.get(name.toLowerCase())
457
+ );
458
+ if (value) {
459
+ return value;
460
+ }
461
+ }
462
+ return void 0;
463
+ };
464
+ }
465
+ function firstDefinedList(value) {
466
+ return value.length > 0 ? value : void 0;
467
+ }
468
+ function parseInstrumentationProfile(value) {
469
+ const normalized = value?.trim().toLowerCase();
470
+ if (normalized === "agent-core" || normalized === "microsoft-genai" || normalized === "agent365-genai" || normalized === "full-stack" || normalized === "manual" || normalized === "microsoft-default") {
471
+ return normalized;
472
+ }
473
+ return void 0;
474
+ }
475
+ function requireValue(name, value) {
476
+ if (!value) {
477
+ throw new Error(`${name} is required`);
478
+ }
479
+ return value;
480
+ }
481
+
482
+ // src/a365/attributes.ts
483
+ var MICROSOFT_A365_ATTRIBUTES = {
484
+ tenantId: "microsoft.tenant.id",
485
+ agentId: "gen_ai.agent.id",
486
+ agentName: "gen_ai.agent.name",
487
+ agentDescription: "gen_ai.agent.description",
488
+ agentVersion: "gen_ai.agent.version",
489
+ agentPlatformId: "microsoft.a365.agent.platform.id",
490
+ agentAuid: "microsoft.agent.user.id",
491
+ agentEmail: "microsoft.agent.user.email",
492
+ agentBlueprintId: "microsoft.a365.agent.blueprint.id",
493
+ sessionId: "microsoft.session.id",
494
+ sessionDescription: "microsoft.session.description",
495
+ conversationId: "gen_ai.conversation.id",
496
+ conversationItemLink: "microsoft.conversation.item.link",
497
+ channelName: "microsoft.channel.name",
498
+ channelLink: "microsoft.channel.link",
499
+ userId: "user.id",
500
+ userName: "user.name",
501
+ userEmail: "user.email",
502
+ callerClientIp: "client.address",
503
+ callerAgentId: "microsoft.a365.caller.agent.id",
504
+ callerAgentName: "microsoft.a365.caller.agent.name",
505
+ callerAgentAuid: "microsoft.a365.caller.agent.user.id",
506
+ callerAgentEmail: "microsoft.a365.caller.agent.user.email",
507
+ callerAgentBlueprintId: "microsoft.a365.caller.agent.blueprint.id",
508
+ callerAgentPlatformId: "microsoft.a365.caller.agent.platform.id",
509
+ callerAgentVersion: "microsoft.a365.caller.agent.version",
510
+ serviceName: "service.name",
511
+ serverAddress: "server.address",
512
+ serverPort: "server.port"
513
+ };
514
+
515
+ // src/a365/baggage.ts
516
+ function buildMicrosoftA365BaggagePairs(context) {
517
+ const pairs = {};
518
+ for (const [key, value] of Object.entries(context.extraBaggage ?? {})) {
519
+ setPair(pairs, key, value);
520
+ }
521
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.tenantId, context.tenantId);
522
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.agentId, context.agentId);
523
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.agentName, context.agentName);
524
+ setPair(
525
+ pairs,
526
+ MICROSOFT_A365_ATTRIBUTES.agentDescription,
527
+ context.agentDescription
528
+ );
529
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.agentVersion, context.agentVersion);
530
+ setPair(
531
+ pairs,
532
+ MICROSOFT_A365_ATTRIBUTES.agentPlatformId,
533
+ context.agentPlatformId
534
+ );
535
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.agentAuid, context.agentAuid);
536
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.agentEmail, context.agentEmail);
537
+ setPair(
538
+ pairs,
539
+ MICROSOFT_A365_ATTRIBUTES.agentBlueprintId,
540
+ context.agentBlueprintId
541
+ );
542
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.sessionId, context.sessionId);
543
+ setPair(
544
+ pairs,
545
+ MICROSOFT_A365_ATTRIBUTES.sessionDescription,
546
+ context.sessionDescription
547
+ );
548
+ setPair(
549
+ pairs,
550
+ MICROSOFT_A365_ATTRIBUTES.conversationId,
551
+ context.conversationId
552
+ );
553
+ setPair(
554
+ pairs,
555
+ MICROSOFT_A365_ATTRIBUTES.conversationItemLink,
556
+ context.conversationItemLink
557
+ );
558
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.channelName, context.channelName);
559
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.channelLink, context.channelLink);
560
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.userId, context.userId);
561
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.userName, context.userName);
562
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.userEmail, context.userEmail);
563
+ setPair(
564
+ pairs,
565
+ MICROSOFT_A365_ATTRIBUTES.callerClientIp,
566
+ context.callerClientIp
567
+ );
568
+ setPair(
569
+ pairs,
570
+ MICROSOFT_A365_ATTRIBUTES.callerAgentId,
571
+ context.callerAgentId
572
+ );
573
+ setPair(
574
+ pairs,
575
+ MICROSOFT_A365_ATTRIBUTES.callerAgentName,
576
+ context.callerAgentName
577
+ );
578
+ setPair(
579
+ pairs,
580
+ MICROSOFT_A365_ATTRIBUTES.callerAgentAuid,
581
+ context.callerAgentAuid
582
+ );
583
+ setPair(
584
+ pairs,
585
+ MICROSOFT_A365_ATTRIBUTES.callerAgentEmail,
586
+ context.callerAgentEmail
587
+ );
588
+ setPair(
589
+ pairs,
590
+ MICROSOFT_A365_ATTRIBUTES.callerAgentBlueprintId,
591
+ context.callerAgentBlueprintId
592
+ );
593
+ setPair(
594
+ pairs,
595
+ MICROSOFT_A365_ATTRIBUTES.callerAgentPlatformId,
596
+ context.callerAgentPlatformId
597
+ );
598
+ setPair(
599
+ pairs,
600
+ MICROSOFT_A365_ATTRIBUTES.callerAgentVersion,
601
+ context.callerAgentVersion
602
+ );
603
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.serviceName, context.serviceName);
604
+ setPair(
605
+ pairs,
606
+ MICROSOFT_A365_ATTRIBUTES.serverAddress,
607
+ context.serverAddress
608
+ );
609
+ setPair(pairs, MICROSOFT_A365_ATTRIBUTES.serverPort, context.serverPort);
610
+ return pairs;
611
+ }
612
+
613
+ // src/runtime/module-loader.ts
614
+ var MICROSOFT_OPENTELEMETRY_PACKAGE = "@microsoft/opentelemetry";
615
+ var OTEL_RESOURCES_PACKAGE = "@opentelemetry/resources";
616
+ async function loadMicrosoftOpenTelemetryModule(options = {}) {
617
+ try {
618
+ if (options.getDistroModule) {
619
+ return await options.getDistroModule();
620
+ }
621
+ return await import(MICROSOFT_OPENTELEMETRY_PACKAGE);
622
+ } catch (error) {
623
+ throw new MicrosoftOpenTelemetryModuleLoadError(
624
+ `Unable to load ${MICROSOFT_OPENTELEMETRY_PACKAGE}. Install @microsoft/opentelemetry before using @cuylabs/agent-microsoft-opentelemetry.`,
625
+ { cause: error }
626
+ );
627
+ }
628
+ }
629
+ async function loadOpenTelemetryResourceModule(options = {}) {
630
+ try {
631
+ if (options.getResourceModule) {
632
+ return await options.getResourceModule();
633
+ }
634
+ return await import(OTEL_RESOURCES_PACKAGE);
635
+ } catch (error) {
636
+ throw new MicrosoftOpenTelemetryResourceModuleLoadError(
637
+ `Unable to load ${OTEL_RESOURCES_PACKAGE}. It is installed with @microsoft/opentelemetry and is required when resource options are supplied.`,
638
+ { cause: error }
639
+ );
640
+ }
641
+ }
642
+
643
+ // src/tracing/tracing-config.ts
644
+ function createMicrosoftOpenTelemetryTracingConfig(options = {}) {
645
+ const spanAttributes = {
646
+ ...options.spanAttributes ?? {}
647
+ };
648
+ if (isNonEmpty(options.tenantId)) {
649
+ spanAttributes[MICROSOFT_A365_ATTRIBUTES.tenantId] = options.tenantId.trim();
650
+ }
651
+ return {
652
+ ...isNonEmpty(options.agentId) ? { agentId: options.agentId.trim() } : {},
653
+ ...isNonEmpty(options.agentDescription) ? { agentDescription: options.agentDescription.trim() } : {},
654
+ ...isNonEmpty(options.agentVersion) ? { agentVersion: options.agentVersion.trim() } : {},
655
+ ...options.recordInputs !== void 0 ? { recordInputs: options.recordInputs } : {},
656
+ ...options.recordOutputs !== void 0 ? { recordOutputs: options.recordOutputs } : {},
657
+ emitToolSpans: options.emitToolSpans ?? false,
658
+ ...options.useGenAIOpenTelemetry !== void 0 ? { useGenAIOpenTelemetry: options.useGenAIOpenTelemetry } : {},
659
+ ...options.telemetryIntegrations ? { telemetryIntegrations: options.telemetryIntegrations } : {},
660
+ ...options.useGlobalTelemetryIntegrations !== void 0 ? {
661
+ useGlobalTelemetryIntegrations: options.useGlobalTelemetryIntegrations
662
+ } : {},
663
+ ...Object.keys(spanAttributes).length > 0 ? { spanAttributes } : {}
664
+ };
665
+ }
666
+
667
+ // src/runtime/instrumentation.ts
668
+ var INFRA_INSTRUMENTATION_KEYS = [
669
+ "http",
670
+ "azureSdk",
671
+ "mongoDb",
672
+ "mySql",
673
+ "postgreSql",
674
+ "redis",
675
+ "redis4",
676
+ "bunyan",
677
+ "winston"
678
+ ];
679
+ var MICROSOFT_FRAMEWORK_INSTRUMENTATION_KEYS = [
680
+ "openaiAgents",
681
+ "langchain"
682
+ ];
683
+ function createMicrosoftOpenTelemetryInstrumentationOptions(options = {}) {
684
+ const profile = normalizeInstrumentationProfile(options.profile);
685
+ const instrumentation = {};
686
+ if (profile === "microsoft-default") {
687
+ return mergeInstrumentationOptions(void 0, options.overrides);
688
+ }
689
+ if (profile === "agent-core") {
690
+ setEnabled(instrumentation, INFRA_INSTRUMENTATION_KEYS, false);
691
+ setEnabled(
692
+ instrumentation,
693
+ MICROSOFT_FRAMEWORK_INSTRUMENTATION_KEYS,
694
+ false
695
+ );
696
+ } else if (profile === "microsoft-genai") {
697
+ setEnabled(instrumentation, INFRA_INSTRUMENTATION_KEYS, false);
698
+ setEnabled(instrumentation, MICROSOFT_FRAMEWORK_INSTRUMENTATION_KEYS, true);
699
+ } else if (profile === "full-stack") {
700
+ setEnabled(instrumentation, INFRA_INSTRUMENTATION_KEYS, true);
701
+ setEnabled(instrumentation, MICROSOFT_FRAMEWORK_INSTRUMENTATION_KEYS, true);
702
+ } else if (profile === "manual") {
703
+ setEnabled(
704
+ instrumentation,
705
+ [
706
+ ...INFRA_INSTRUMENTATION_KEYS,
707
+ ...MICROSOFT_FRAMEWORK_INSTRUMENTATION_KEYS
708
+ ],
709
+ false
710
+ );
711
+ }
712
+ return mergeInstrumentationOptions(instrumentation, options.overrides);
713
+ }
714
+ function normalizeInstrumentationProfile(profile) {
715
+ if (profile === "agent365-genai") {
716
+ return "microsoft-genai";
717
+ }
718
+ return profile ?? "agent-core";
719
+ }
720
+ function mergeInstrumentationOptions(base, overrides) {
721
+ if (!base) {
722
+ return { ...overrides ?? {} };
723
+ }
724
+ if (!overrides) {
725
+ return { ...base };
726
+ }
727
+ return {
728
+ ...base,
729
+ ...overrides,
730
+ azureSdk: mergeConfig(base.azureSdk, overrides.azureSdk),
731
+ http: mergeConfig(base.http, overrides.http),
732
+ mongoDb: mergeConfig(base.mongoDb, overrides.mongoDb),
733
+ mySql: mergeConfig(base.mySql, overrides.mySql),
734
+ postgreSql: mergeConfig(base.postgreSql, overrides.postgreSql),
735
+ redis: mergeConfig(base.redis, overrides.redis),
736
+ redis4: mergeConfig(base.redis4, overrides.redis4),
737
+ bunyan: mergeConfig(base.bunyan, overrides.bunyan),
738
+ winston: mergeConfig(base.winston, overrides.winston),
739
+ openaiAgents: mergeConfig(base.openaiAgents, overrides.openaiAgents),
740
+ langchain: mergeConfig(base.langchain, overrides.langchain)
741
+ };
742
+ }
743
+ function setEnabled(target, keys, enabled) {
744
+ for (const key of keys) {
745
+ target[key] = { enabled };
746
+ }
747
+ }
748
+ function mergeConfig(base, override) {
749
+ if (!base && !override) {
750
+ return void 0;
751
+ }
752
+ return {
753
+ ...base ?? {},
754
+ ...override ?? {}
755
+ };
756
+ }
757
+
758
+ // src/runtime/lifecycle.ts
759
+ async function initMicrosoftOpenTelemetry(options = {}) {
760
+ const module = await loadMicrosoftOpenTelemetryModule(options.runtime);
761
+ const resource = await createResource(options.resource, options.runtime);
762
+ const distroOptions = await createDistroOptions(options, resource);
763
+ module.useMicrosoftOpenTelemetry(distroOptions);
764
+ return {
765
+ tracing: createMicrosoftOpenTelemetryTracingConfig(options.agent),
766
+ shutdown: () => module.shutdownMicrosoftOpenTelemetry()
767
+ };
768
+ }
769
+ async function initMicrosoftOpenTelemetryFromEnv(options = {}) {
770
+ const env = resolveMicrosoftOpenTelemetryEnvironment(options.env);
771
+ const explicitA365Enabled = options.a365?.enabled ?? env.a365.enabled;
772
+ const exporterEnabled = options.a365?.enableObservabilityExporter ?? options.a365?.exporterEnabled ?? env.a365.enableObservabilityExporter ?? env.a365.exporterEnabled ?? false;
773
+ const a365Enabled = explicitA365Enabled ?? exporterEnabled;
774
+ return await initMicrosoftOpenTelemetry({
775
+ ...options,
776
+ resource: {
777
+ ...env.resource,
778
+ ...options.resource
779
+ },
780
+ a365: a365Enabled || exporterEnabled || options.a365 ? {
781
+ ...env.a365,
782
+ ...options.a365,
783
+ enabled: a365Enabled,
784
+ enableObservabilityExporter: exporterEnabled,
785
+ tokenResolver: options.a365?.tokenResolver ?? (a365Enabled && exporterEnabled ? createMicrosoftA365S2STokenResolverFromEnv({
786
+ env: options.env
787
+ }) : void 0)
788
+ } : void 0,
789
+ azureMonitor: env.azureMonitorEnabled !== void 0 ? { enabled: env.azureMonitorEnabled } : void 0,
790
+ instrumentationProfile: options.instrumentationProfile ?? env.instrumentationProfile,
791
+ enableConsoleExporters: options.enableConsoleExporters ?? env.enableConsoleExporters
792
+ });
793
+ }
794
+ async function runWithMicrosoftA365Context(requestContext, fn, options = {}) {
795
+ const module = await loadMicrosoftOpenTelemetryModule(options);
796
+ const runWithBaggage = () => {
797
+ const scope = new module.BaggageBuilder().setPairs(buildMicrosoftA365BaggagePairs(requestContext)).build();
798
+ return scope.run(fn);
799
+ };
800
+ const result = requestContext.exportToken && module.runWithExportToken ? module.runWithExportToken(requestContext.exportToken, runWithBaggage) : runWithBaggage();
801
+ return await result;
802
+ }
803
+ async function updateMicrosoftA365ExportToken(token, options = {}) {
804
+ const module = await loadMicrosoftOpenTelemetryModule(options);
805
+ return module.updateExportToken?.(token) ?? false;
806
+ }
807
+ async function createDistroOptions(options, resource) {
808
+ const distroOptions = {
809
+ ...options.distroOptions ?? {}
810
+ };
811
+ if (resource) {
812
+ distroOptions.resource = resource;
813
+ }
814
+ if (options.samplingRatio !== void 0) {
815
+ distroOptions.samplingRatio = options.samplingRatio;
816
+ }
817
+ if (options.tracesPerSecond !== void 0) {
818
+ distroOptions.tracesPerSecond = options.tracesPerSecond;
819
+ }
820
+ if (options.instrumentationProfile !== "microsoft-default" || options.instrumentationOptions) {
821
+ distroOptions.instrumentationOptions = createMicrosoftOpenTelemetryInstrumentationOptions({
822
+ profile: options.instrumentationProfile,
823
+ overrides: options.instrumentationOptions
824
+ });
825
+ }
826
+ if (options.spanProcessors) {
827
+ distroOptions.spanProcessors = [...options.spanProcessors];
828
+ }
829
+ if (options.logRecordProcessors) {
830
+ distroOptions.logRecordProcessors = [...options.logRecordProcessors];
831
+ }
832
+ if (options.metricReaders) {
833
+ distroOptions.metricReaders = [...options.metricReaders];
834
+ }
835
+ if (options.views) {
836
+ distroOptions.views = [...options.views];
837
+ }
838
+ if (options.azureMonitor !== void 0) {
839
+ distroOptions.azureMonitor = options.azureMonitor === false ? { enabled: false } : options.azureMonitor;
840
+ }
841
+ if (options.enableConsoleExporters !== void 0) {
842
+ distroOptions.enableConsoleExporters = options.enableConsoleExporters;
843
+ }
844
+ if (options.a365) {
845
+ distroOptions.a365 = createA365DistroOptions(options.a365);
846
+ }
847
+ return distroOptions;
848
+ }
849
+ function createA365DistroOptions(options) {
850
+ const a365 = {
851
+ enabled: options.enabled ?? true
852
+ };
853
+ const enableObservabilityExporter = options.enableObservabilityExporter ?? options.exporterEnabled;
854
+ if (enableObservabilityExporter !== void 0) {
855
+ a365.enableObservabilityExporter = enableObservabilityExporter;
856
+ }
857
+ if (options.tokenResolver) {
858
+ a365.tokenResolver = createDistroTokenResolver(options.tokenResolver);
859
+ }
860
+ setIfDefined(a365, "clusterCategory", options.clusterCategory);
861
+ setIfDefined(a365, "domainOverride", options.domainOverride);
862
+ setIfDefined(a365, "authScopes", options.authScopes);
863
+ setIfDefined(
864
+ a365,
865
+ "observabilityScopeOverride",
866
+ options.observabilityScopeOverride
867
+ );
868
+ setIfDefined(a365, "logLevel", options.logLevel);
869
+ setIfDefined(a365, "useS2SEndpoint", options.useS2SEndpoint);
870
+ setIfDefined(a365, "maxQueueSize", options.maxQueueSize);
871
+ setIfDefined(
872
+ a365,
873
+ "scheduledDelayMilliseconds",
874
+ options.scheduledDelayMilliseconds
875
+ );
876
+ setIfDefined(
877
+ a365,
878
+ "exporterTimeoutMilliseconds",
879
+ options.exporterTimeoutMilliseconds
880
+ );
881
+ setIfDefined(
882
+ a365,
883
+ "httpRequestTimeoutMilliseconds",
884
+ options.httpRequestTimeoutMilliseconds
885
+ );
886
+ setIfDefined(a365, "maxExportBatchSize", options.maxExportBatchSize);
887
+ setIfDefined(a365, "maxPayloadBytes", options.maxPayloadBytes);
888
+ return a365;
889
+ }
890
+ function createDistroTokenResolver(resolver) {
891
+ return async (agentId, tenantId, authScopes) => {
892
+ return await resolver(agentId, tenantId, authScopes) ?? "";
893
+ };
894
+ }
895
+ async function createResource(options, runtime) {
896
+ const attributes = createResourceAttributes(options);
897
+ if (!attributes) {
898
+ return void 0;
899
+ }
900
+ const resourceModule = await loadOpenTelemetryResourceModule(runtime);
901
+ return resourceModule.resourceFromAttributes(attributes);
902
+ }
903
+ function createResourceAttributes(options) {
904
+ const attributes = {
905
+ ...options?.attributes ?? {}
906
+ };
907
+ setStringAttribute(attributes, "service.name", options?.serviceName);
908
+ setStringAttribute(attributes, "service.version", options?.serviceVersion);
909
+ setStringAttribute(
910
+ attributes,
911
+ "service.namespace",
912
+ options?.serviceNamespace
913
+ );
914
+ setStringAttribute(
915
+ attributes,
916
+ "service.instance.id",
917
+ options?.serviceInstanceId
918
+ );
919
+ return Object.keys(attributes).length > 0 ? attributes : void 0;
920
+ }
921
+ function resolveMicrosoftOpenTelemetryBooleanEnv(value) {
922
+ return parseOptionalBoolean(value);
923
+ }
924
+ function resolveMicrosoftOpenTelemetryNumberEnv(value) {
925
+ return parseOptionalNumber(value);
926
+ }
927
+ function setStringAttribute(attributes, key, value) {
928
+ if (isNonEmpty(value)) {
929
+ attributes[key] = value.trim();
930
+ }
931
+ }
932
+ function setIfDefined(target, key, value) {
933
+ if (value !== void 0) {
934
+ target[key] = value;
935
+ }
936
+ }
937
+
938
+ export {
939
+ MicrosoftOpenTelemetryModuleLoadError,
940
+ MicrosoftOpenTelemetryResourceModuleLoadError,
941
+ firstNonEmpty,
942
+ readPath,
943
+ callOptionalStringMethod,
944
+ callOptionalBooleanMethod,
945
+ parseServiceEndpoint,
946
+ MICROSOFT_A365_FMI_SCOPE,
947
+ MICROSOFT_A365_OBSERVABILITY_SCOPE,
948
+ createMicrosoftA365S2STokenResolver,
949
+ resolveMicrosoftOpenTelemetryEnvironment,
950
+ createMicrosoftA365S2STokenResolverFromEnv,
951
+ createEnvReader,
952
+ MICROSOFT_A365_ATTRIBUTES,
953
+ buildMicrosoftA365BaggagePairs,
954
+ loadMicrosoftOpenTelemetryModule,
955
+ loadOpenTelemetryResourceModule,
956
+ createMicrosoftOpenTelemetryTracingConfig,
957
+ createMicrosoftOpenTelemetryInstrumentationOptions,
958
+ normalizeInstrumentationProfile,
959
+ mergeInstrumentationOptions,
960
+ initMicrosoftOpenTelemetry,
961
+ initMicrosoftOpenTelemetryFromEnv,
962
+ runWithMicrosoftA365Context,
963
+ updateMicrosoftA365ExportToken,
964
+ resolveMicrosoftOpenTelemetryBooleanEnv,
965
+ resolveMicrosoftOpenTelemetryNumberEnv
966
+ };