Skip to content

Commit 1ac75e2

Browse files
authored
[Azure Monitor Exporter] Add support for aadAudience configuration using Connection String (Azure#27317)
### Packages impacted by this PR @azure/monitor-opentelemetry-exporter
1 parent 57cd99f commit 1ac75e2

File tree

11 files changed

+230
-88
lines changed

11 files changed

+230
-88
lines changed

sdk/monitor/monitor-opentelemetry-exporter/review/monitor-opentelemetry-exporter.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class ApplicationInsightsSampler implements Sampler {
3838
// @public
3939
export abstract class AzureMonitorBaseExporter {
4040
constructor(options?: AzureMonitorExporterOptions, isStatsbeatExporter?: boolean);
41+
protected aadAudience: string | undefined;
4142
protected endpointUrl: string;
4243
protected instrumentationKey: string;
4344
protected trackStatsbeat: boolean;

sdk/monitor/monitor-opentelemetry-exporter/src/Declarations/Contracts/Constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export type ConnectionString = { [key in ConnectionStringKey]?: string };
1414
*/
1515
export type ConnectionStringKey =
1616
| "authorization"
17+
| "aadaudience"
1718
| "instrumentationkey"
1819
| "ingestionendpoint"
1920
| "liveendpoint"

sdk/monitor/monitor-opentelemetry-exporter/src/export/base.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ export abstract class AzureMonitorBaseExporter {
2626
*Flag to determine if exporter will generate Statsbeat data
2727
*/
2828
protected trackStatsbeat: boolean = false;
29+
/**
30+
* Instrumentation key to be used for exported envelopes
31+
*/
32+
protected aadAudience: string | undefined;
2933
private isStatsbeatExporter: boolean;
3034

3135
/**
@@ -49,6 +53,7 @@ export abstract class AzureMonitorBaseExporter {
4953
this.instrumentationKey =
5054
parsedConnectionString.instrumentationkey || this.instrumentationKey;
5155
this.endpointUrl = parsedConnectionString.ingestionendpoint?.trim() || this.endpointUrl;
56+
this.aadAudience = parsedConnectionString.aadaudience;
5257
}
5358

5459
// Instrumentation key is required

sdk/monitor/monitor-opentelemetry-exporter/src/export/log.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ export class AzureMonitorLogExporter extends AzureMonitorBaseExporter implements
2727

2828
constructor(options: AzureMonitorExporterOptions = {}) {
2929
super(options);
30-
this._sender = new HttpSender(
31-
this.endpointUrl,
32-
this.instrumentationKey,
33-
this.trackStatsbeat,
34-
options
35-
);
30+
this._sender = new HttpSender({
31+
endpointUrl: this.endpointUrl,
32+
instrumentationKey: this.instrumentationKey,
33+
trackStatsbeat: this.trackStatsbeat,
34+
exporterOptions: options,
35+
aadAudience: this.aadAudience,
36+
});
3637
diag.debug("AzureMonitorLogExporter was successfully setup");
3738
}
3839

sdk/monitor/monitor-opentelemetry-exporter/src/export/metric.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,13 @@ export class AzureMonitorMetricExporter
3434

3535
constructor(options: AzureMonitorExporterOptions = {}) {
3636
super(options);
37-
this._sender = new HttpSender(
38-
this.endpointUrl,
39-
this.instrumentationKey,
40-
this.trackStatsbeat,
41-
options
42-
);
37+
this._sender = new HttpSender({
38+
endpointUrl: this.endpointUrl,
39+
instrumentationKey: this.instrumentationKey,
40+
trackStatsbeat: this.trackStatsbeat,
41+
exporterOptions: options,
42+
aadAudience: this.aadAudience,
43+
});
4344
diag.debug("AzureMonitorMetricExporter was successfully setup");
4445
}
4546

sdk/monitor/monitor-opentelemetry-exporter/src/export/statsbeat/statsbeatExporter.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ export class AzureMonitorStatsbeatExporter
2828
*/
2929
constructor(options: AzureMonitorExporterOptions) {
3030
super(options, true);
31-
this._sender = new HttpSender(
32-
this.endpointUrl,
33-
this.instrumentationKey,
34-
this.trackStatsbeat,
35-
options
36-
);
31+
this._sender = new HttpSender({
32+
endpointUrl: this.endpointUrl,
33+
instrumentationKey: this.instrumentationKey,
34+
trackStatsbeat: this.trackStatsbeat,
35+
exporterOptions: options,
36+
});
3737
}
3838

3939
/**

sdk/monitor/monitor-opentelemetry-exporter/src/export/trace.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ export class AzureMonitorTraceExporter extends AzureMonitorBaseExporter implemen
2727
*/
2828
constructor(options: AzureMonitorExporterOptions = {}) {
2929
super(options);
30-
this.sender = new HttpSender(
31-
this.endpointUrl,
32-
this.instrumentationKey,
33-
this.trackStatsbeat,
34-
options
35-
);
30+
this.sender = new HttpSender({
31+
endpointUrl: this.endpointUrl,
32+
instrumentationKey: this.instrumentationKey,
33+
trackStatsbeat: this.trackStatsbeat,
34+
exporterOptions: options,
35+
aadAudience: this.aadAudience,
36+
});
3637
diag.debug("AzureMonitorTraceExporter was successfully setup");
3738
}
3839

sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/baseSender.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,24 @@ export abstract class BaseSender {
2727
private statsbeatFailureCount: number = 0;
2828
private batchSendRetryIntervalMs: number = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;
2929

30-
constructor(
31-
endpointUrl: string,
32-
instrumentationKey: string,
33-
trackStatsbeat: boolean,
34-
options: AzureMonitorExporterOptions = {}
35-
) {
30+
constructor(options: {
31+
endpointUrl: string;
32+
instrumentationKey: string;
33+
trackStatsbeat: boolean;
34+
exporterOptions: AzureMonitorExporterOptions;
35+
aadAudience?: string;
36+
}) {
3637
this.numConsecutiveRedirects = 0;
37-
this.persister = new FileSystemPersist(instrumentationKey, options);
38-
if (trackStatsbeat) {
38+
this.persister = new FileSystemPersist(options.instrumentationKey, options.exporterOptions);
39+
if (options.trackStatsbeat) {
3940
// Initialize statsbeatMetrics
4041
this.networkStatsbeatMetrics = new NetworkStatsbeatMetrics({
41-
instrumentationKey: instrumentationKey,
42-
endpointUrl: endpointUrl,
42+
instrumentationKey: options.instrumentationKey,
43+
endpointUrl: options.endpointUrl,
4344
});
4445
this.longIntervalStatsbeatMetrics = getInstance({
45-
instrumentationKey: instrumentationKey,
46-
endpointUrl: endpointUrl,
46+
instrumentationKey: options.instrumentationKey,
47+
endpointUrl: options.endpointUrl,
4748
});
4849
}
4950
this.retryTimer = null;

sdk/monitor/monitor-opentelemetry-exporter/src/platform/nodejs/httpSender.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,28 @@ export class HttpSender extends BaseSender {
2424
private readonly appInsightsClient: ApplicationInsightsClient;
2525
private appInsightsClientOptions: ApplicationInsightsClientOptionalParams;
2626

27-
constructor(
28-
endpointUrl: string,
29-
instrumentationKey: string,
30-
trackStatsbeat: boolean,
31-
options?: AzureMonitorExporterOptions
32-
) {
33-
super(endpointUrl, instrumentationKey, trackStatsbeat, options);
27+
constructor(options: {
28+
endpointUrl: string;
29+
instrumentationKey: string;
30+
trackStatsbeat: boolean;
31+
exporterOptions: AzureMonitorExporterOptions;
32+
aadAudience?: string;
33+
}) {
34+
super(options);
3435
// Build endpoint using provided configuration or default values
3536
this.appInsightsClientOptions = {
36-
host: endpointUrl,
37-
...options,
37+
host: options.endpointUrl,
38+
...options.exporterOptions,
3839
};
3940

4041
if (this.appInsightsClientOptions.credential) {
4142
// Add credentialScopes
42-
this.appInsightsClientOptions.credentialScopes = [applicationInsightsResource];
43+
if (options.aadAudience) {
44+
this.appInsightsClientOptions.credentialScopes = [options.aadAudience];
45+
} else {
46+
// Default
47+
this.appInsightsClientOptions.credentialScopes = [applicationInsightsResource];
48+
}
4349
}
4450
this.appInsightsClient = new ApplicationInsightsClient(this.appInsightsClientOptions);
4551

sdk/monitor/monitor-opentelemetry-exporter/test/internal/connectionStringParser.test.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,16 @@ describe("ConnectionStringParser", () => {
1212
const instrumentationKey = "instr_key";
1313
const ingestionEndpoint = "ingest";
1414
const liveEndpoint = "live";
15-
const connectionString = `Authorization=${authorization};InstrumentationKey=${instrumentationKey};IngestionEndpoint=${ingestionEndpoint};LiveEndpoint=${liveEndpoint}`;
15+
const aadAudience = "audience";
16+
const connectionString = `Authorization=${authorization};InstrumentationKey=${instrumentationKey};IngestionEndpoint=${ingestionEndpoint};LiveEndpoint=${liveEndpoint};AadAudience=${aadAudience}`;
1617

1718
const result = ConnectionStringParser.parse(connectionString);
1819

19-
assert.deepEqual(result.authorization, authorization);
20-
assert.deepEqual(result.instrumentationkey, instrumentationKey);
21-
assert.deepEqual(result.ingestionendpoint, ingestionEndpoint);
22-
assert.deepEqual(result.liveendpoint, liveEndpoint);
20+
assert.strictEqual(result.authorization, authorization);
21+
assert.strictEqual(result.instrumentationkey, instrumentationKey);
22+
assert.strictEqual(result.ingestionendpoint, ingestionEndpoint);
23+
assert.strictEqual(result.liveendpoint, liveEndpoint);
24+
assert.strictEqual(result.aadaudience, aadAudience);
2325
});
2426

2527
it("should sanitize URLs", () => {
@@ -29,9 +31,9 @@ describe("ConnectionStringParser", () => {
2931
const connectionString = `InstrumentationKey=${instrumentationKey};IngestionEndpoint=${ingestionEndpoint};LiveEndpoint=${liveEndpoint}`;
3032

3133
const result = ConnectionStringParser.parse(connectionString);
32-
assert.deepEqual(result.instrumentationkey, instrumentationKey);
33-
assert.deepEqual(result.ingestionendpoint, "https://test.com");
34-
assert.deepEqual(result.liveendpoint, "https://livetest.net");
34+
assert.strictEqual(result.instrumentationkey, instrumentationKey);
35+
assert.strictEqual(result.ingestionendpoint, "https://test.com");
36+
assert.strictEqual(result.liveendpoint, "https://livetest.net");
3537
});
3638

3739
it("should ignore invalid fields", () => {
@@ -43,10 +45,10 @@ describe("ConnectionStringParser", () => {
4345

4446
const result = ConnectionStringParser.parse(connectionString);
4547

46-
assert.deepEqual(result.authorization, undefined);
47-
assert.deepEqual(result.instrumentationkey, undefined);
48-
assert.deepEqual(result.ingestionendpoint, Constants.DEFAULT_BREEZE_ENDPOINT);
49-
assert.deepEqual(result.liveendpoint, Constants.DEFAULT_LIVEMETRICS_ENDPOINT);
48+
assert.strictEqual(result.authorization, undefined);
49+
assert.strictEqual(result.instrumentationkey, undefined);
50+
assert.strictEqual(result.ingestionendpoint, Constants.DEFAULT_BREEZE_ENDPOINT);
51+
assert.strictEqual(result.liveendpoint, Constants.DEFAULT_LIVEMETRICS_ENDPOINT);
5052
});
5153

5254
const runTest = (options: {
@@ -59,13 +61,13 @@ describe("ConnectionStringParser", () => {
5961
const result = ConnectionStringParser.parse(options.connectionString);
6062

6163
if (options.expectedAuthorization) {
62-
assert.deepEqual(result.authorization, options.expectedAuthorization);
64+
assert.strictEqual(result.authorization, options.expectedAuthorization);
6365
}
6466
if (options.expectedInstrumentationKey) {
65-
assert.deepEqual(result.instrumentationkey, options.expectedInstrumentationKey);
67+
assert.strictEqual(result.instrumentationkey, options.expectedInstrumentationKey);
6668
}
67-
assert.deepEqual(result.ingestionendpoint, options.expectedBreezeEndpoint);
68-
assert.deepEqual(result.liveendpoint, options.expectedLiveMetricsEndpoint);
69+
assert.strictEqual(result.ingestionendpoint, options.expectedBreezeEndpoint);
70+
assert.strictEqual(result.liveendpoint, options.expectedLiveMetricsEndpoint);
6971
};
7072

7173
it("should use correct default endpoints", () => {

0 commit comments

Comments
 (0)