Skip to content

Commit 720baee

Browse files
committed
comments
1 parent aaf476d commit 720baee

File tree

4 files changed

+28
-27
lines changed

4 files changed

+28
-27
lines changed

packages/agents-a365-observability/src/ObservabilityBuilder.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,7 @@ export class ObservabilityBuilder {
152152
if (this.options.tokenResolver) {
153153
opts.tokenResolver = this.options.tokenResolver;
154154
}
155-
if (this.options.configProvider) {
156-
opts.configProvider = this.options.configProvider;
157-
}
158-
return new BatchSpanProcessor(new Agent365Exporter(opts), {
155+
return new BatchSpanProcessor(new Agent365Exporter(opts, this.options.configProvider), {
159156
maxQueueSize: opts.maxQueueSize,
160157
scheduledDelayMillis: opts.scheduledDelayMilliseconds,
161158
exportTimeoutMillis: opts.exporterTimeoutMilliseconds,
@@ -174,13 +171,10 @@ export class ObservabilityBuilder {
174171
Object.assign(opts, this.options.exporterOptions);
175172
}
176173
opts.clusterCategory = this.options.clusterCategory || opts.clusterCategory || ClusterCategory.prod;
177-
if (this.options.configProvider) {
178-
opts.configProvider = this.options.configProvider;
179-
}
180174

181175
// For per-request export, token is retrieved from OTel Context by Agent365Exporter
182176
// using getExportToken(), so no tokenResolver is needed here
183-
return new PerRequestSpanProcessor(new Agent365Exporter(opts));
177+
return new PerRequestSpanProcessor(new Agent365Exporter(opts, this.options.configProvider));
184178
}
185179

186180
private createExportProcessor(): BatchSpanProcessor | PerRequestSpanProcessor {

packages/agents-a365-observability/src/tracing/exporter/Agent365Exporter.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import { ExportResult, ExportResultCode } from '@opentelemetry/core';
77
import { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
88

9-
import { PowerPlatformApiDiscovery, ClusterCategory } from '@microsoft/agents-a365-runtime';
9+
import { PowerPlatformApiDiscovery, ClusterCategory, IConfigurationProvider } from '@microsoft/agents-a365-runtime';
10+
import type { ObservabilityConfiguration } from '../../configuration';
1011
import {
1112
partitionByIdentity,
1213
parseIdentityKey,
@@ -88,12 +89,15 @@ interface OTLPStatus {
8889
export class Agent365Exporter implements SpanExporter {
8990
private closed = false;
9091
private readonly options: Agent365ExporterOptions;
92+
private readonly configProvider?: IConfigurationProvider<ObservabilityConfiguration>;
9193

9294
/**
9395
* Initialize exporter with a fully constructed options instance.
94-
* If tokenResolver is missing, installs cache-backed resolver.
96+
* @param options Exporter options controlling batching, timeouts, token acquisition and endpoint shape.
97+
* @param configProvider Optional configuration provider. When supplied, the exporter uses it for
98+
* configuration lookups (custom domain, domain override) instead of the default env-based provider.
9599
*/
96-
constructor(options: Agent365ExporterOptions) {
100+
constructor(options: Agent365ExporterOptions, configProvider?: IConfigurationProvider<ObservabilityConfiguration>) {
97101
if (!options) {
98102
throw new Error('Agent365ExporterOptions must be provided (was null/undefined)');
99103
}
@@ -102,6 +106,7 @@ export class Agent365Exporter implements SpanExporter {
102106
throw new Error('Agent365Exporter tokenResolver must be provided for batch export');
103107
}
104108
this.options = options;
109+
this.configProvider = configProvider;
105110
}
106111

107112
/**
@@ -165,15 +170,15 @@ export class Agent365Exporter implements SpanExporter {
165170

166171
const payload = this.buildExportRequest(spans);
167172
const body = JSON.stringify(payload);
168-
const usingCustomServiceEndpoint = useCustomDomainForObservability(this.options.configProvider);
173+
const usingCustomServiceEndpoint = useCustomDomainForObservability(this.configProvider);
169174
// Select endpoint path based on S2S flag
170175
const endpointRelativePath =
171176
this.options.useS2SEndpoint
172177
? `/maven/agent365/service/agents/${agentId}/traces`
173178
: `/maven/agent365/agents/${agentId}/traces`;
174179

175180
let url: string;
176-
const domainOverride = getAgent365ObservabilityDomainOverride(this.options.configProvider);
181+
const domainOverride = getAgent365ObservabilityDomainOverride(this.configProvider);
177182
if (domainOverride) {
178183
url = `${domainOverride}${endpointRelativePath}?api-version=1`;
179184
} else if (usingCustomServiceEndpoint) {

packages/agents-a365-observability/src/tracing/exporter/Agent365ExporterOptions.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@
33
// Licensed under the MIT License.
44
// ------------------------------------------------------------------------------
55

6-
import { ClusterCategory, IConfigurationProvider } from '@microsoft/agents-a365-runtime';
7-
import type { ObservabilityConfiguration } from '../../configuration';
6+
import { ClusterCategory } from '@microsoft/agents-a365-runtime';
87

98
/**
109
* A function that resolves and returns an authentication token for the given agent and tenant.
@@ -49,11 +48,4 @@ export class Agent365ExporterOptions {
4948

5049
/** Maximum number of spans per export batch. */
5150
public maxExportBatchSize: number = 512;
52-
53-
/**
54-
* Optional configuration provider for ObservabilityConfiguration.
55-
* When provided, this is used by the exporter for configuration lookups
56-
* instead of the default provider that reads from environment variables.
57-
*/
58-
public configProvider?: IConfigurationProvider<ObservabilityConfiguration>;
5951
}

tests/observability/core/observabilityBuilder-configProvider.test.ts

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ import { ObservabilityManager } from '@microsoft/agents-a365-observability/src/O
66
import { ObservabilityConfiguration } from '@microsoft/agents-a365-observability/src/configuration/ObservabilityConfiguration';
77
import { DefaultConfigurationProvider } from '@microsoft/agents-a365-runtime';
88

9-
// Capture Agent365Exporter constructor options without performing network calls.
9+
// Capture Agent365Exporter constructor args without performing network calls.
1010
jest.mock('@microsoft/agents-a365-observability/src/tracing/exporter/Agent365Exporter', () => ({
1111
Agent365Exporter: class {
12-
constructor(opts: any) { (global as any).__capturedOpts = opts; }
12+
constructor(opts: any, configProvider?: any) {
13+
(global as any).__capturedOpts = opts;
14+
(global as any).__capturedConfigProvider = configProvider;
15+
}
1316
export() {/* no-op */}
1417
shutdown() {/* no-op */}
1518
forceFlush() {/* no-op */}
@@ -30,11 +33,13 @@ const makeProvider = (exporterEnabled?: boolean) =>
3033
}));
3134

3235
const capturedOpts = () => (global as any).__capturedOpts as any | undefined;
36+
const capturedConfigProvider = () => (global as any).__capturedConfigProvider as any | undefined;
3337

3438
describe('ObservabilityBuilder configProvider', () => {
3539
beforeEach(() => {
3640
delete process.env.ENABLE_A365_OBSERVABILITY_EXPORTER;
3741
delete (global as any).__capturedOpts;
42+
delete (global as any).__capturedConfigProvider;
3843
capturedLogger = null;
3944
jest.spyOn(console, 'log').mockImplementation(() => {});
4045
jest.spyOn(console, 'warn').mockImplementation(() => {});
@@ -44,6 +49,10 @@ describe('ObservabilityBuilder configProvider', () => {
4449
afterEach(async () => {
4550
delete process.env.ENABLE_A365_OBSERVABILITY_EXPORTER;
4651
await ObservabilityManager.shutdown();
52+
const actualLogging = jest.requireActual('@microsoft/agents-a365-observability/src/utils/logging') as any;
53+
if (typeof actualLogging.resetLogger === 'function') {
54+
actualLogging.resetLogger();
55+
}
4756
jest.restoreAllMocks();
4857
});
4958

@@ -61,7 +70,8 @@ describe('ObservabilityBuilder configProvider', () => {
6170
.build();
6271

6372
expect(capturedOpts()).toBeDefined();
64-
expect(capturedOpts().configProvider).toBe(provider);
73+
expect(capturedConfigProvider()).toBe(provider);
74+
expect(capturedOpts().configProvider).toBeUndefined();
6575
expect(capturedOpts().maxQueueSize).toBe(42);
6676
expect(capturedOpts().tokenResolver('a', 'b')).toBe('tok');
6777
});
@@ -90,12 +100,12 @@ describe('ObservabilityBuilder configProvider', () => {
90100
process.env.ENABLE_A365_OBSERVABILITY_EXPORTER = 'true';
91101
new ObservabilityBuilder().withTokenResolver(() => 't').build();
92102
expect(capturedOpts()).toBeDefined();
93-
expect(capturedOpts().configProvider).toBeUndefined();
103+
expect(capturedConfigProvider()).toBeUndefined();
94104
});
95105

96106
it('ObservabilityManager.start() passes configProvider through to exporter', () => {
97107
const provider = makeProvider(true);
98108
ObservabilityManager.start({ serviceName: 'svc', tokenResolver: () => 't', configProvider: provider });
99-
expect(capturedOpts()?.configProvider).toBe(provider);
109+
expect(capturedConfigProvider()).toBe(provider);
100110
});
101111
});

0 commit comments

Comments
 (0)