Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/agent/aksLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,12 @@ export class AKSLoader extends AgentLoader {
// Create metricReaders array and add OTLP reader if environment variables request it
try {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No changelog update? Or did I miss it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This project does not have a changelog. Open to adding one in another PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, if it makes sense to have a CHANGELOG for these changes, then adding that to another PR sounds like a plan.

const metricReaders: MetricReader[] = [];
const metricsExporter = (process.env.OTEL_METRICS_EXPORTER || '').toLowerCase();
const exportersList = metricsExporter.split(',').map(exp => exp.trim());
const hasOtlpExporter = exportersList.includes('otlp');

if (
process.env.OTEL_METRICS_EXPORTER === "otlp" &&
hasOtlpExporter &&
(process.env.OTEL_EXPORTER_OTLP_ENDPOINT || process.env.OTEL_EXPORTER_OTLP_METRICS_ENDPOINT)
) {
try {
Expand Down
165 changes: 165 additions & 0 deletions test/unitTests/agent/aksLoader.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,4 +212,169 @@ describe("agent/AKSLoader", () => {
// The protobuf exporter should have different internal structure than the HTTP exporter
assert.ok(exporter, "Protobuf exporter should exist");
});

it("constructor creates OTLP metric reader when OTEL_METRICS_EXPORTER contains otlp with other exporters (comma-separated)", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "console,otlp,prometheus",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(options.metricReaders, "metricReaders should be present in options when otlp is included with other exporters");
assert.equal(options.metricReaders.length, 1, "Should have exactly one metric reader");

// Verify the metric reader is a PeriodicExportingMetricReader
const metricReader = options.metricReaders[0];
assert.equal(metricReader.constructor.name, "PeriodicExportingMetricReader", "Should be a PeriodicExportingMetricReader");

// Verify the exporter is an OTLP exporter
const exporter = (metricReader as any)._exporter;
assert.equal(exporter.constructor.name, "OTLPMetricExporter", "Should be an OTLPMetricExporter");
});

it("constructor creates OTLP metric reader when OTEL_METRICS_EXPORTER contains otlp with spaces", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "console, otlp, prometheus",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(options.metricReaders, "metricReaders should be present in options when otlp is included with spaces");
assert.equal(options.metricReaders.length, 1, "Should have exactly one metric reader");

// Verify the exporter is an OTLP exporter
const metricReader = options.metricReaders[0];
const exporter = (metricReader as any)._exporter;
assert.equal(exporter.constructor.name, "OTLPMetricExporter", "Should be an OTLPMetricExporter");
});

it("constructor creates OTLP metric reader when OTEL_METRICS_EXPORTER has otlp at the beginning", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "otlp,console,prometheus",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(options.metricReaders, "metricReaders should be present in options when otlp is at the beginning");
assert.equal(options.metricReaders.length, 1, "Should have exactly one metric reader");

// Verify the exporter is an OTLP exporter
const metricReader = options.metricReaders[0];
const exporter = (metricReader as any)._exporter;
assert.equal(exporter.constructor.name, "OTLPMetricExporter", "Should be an OTLPMetricExporter");
});

it("constructor creates OTLP metric reader when OTEL_METRICS_EXPORTER has otlp at the end", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "console,prometheus,otlp",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(options.metricReaders, "metricReaders should be present in options when otlp is at the end");
assert.equal(options.metricReaders.length, 1, "Should have exactly one metric reader");

// Verify the exporter is an OTLP exporter
const metricReader = options.metricReaders[0];
const exporter = (metricReader as any)._exporter;
assert.equal(exporter.constructor.name, "OTLPMetricExporter", "Should be an OTLPMetricExporter");
});

it("constructor does not create OTLP metric reader when OTEL_METRICS_EXPORTER contains similar strings but not otlp", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "console,otlp-custom,prometheus",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that no metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(!options.metricReaders || options.metricReaders.length === 0, "Should not have any metric readers when 'otlp' is not exactly present (only similar strings like 'otlp-custom')");
});

it("constructor does not create OTLP metric reader when OTEL_METRICS_EXPORTER is empty with multiple exporters", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "console,prometheus",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that no metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(!options.metricReaders || options.metricReaders.length === 0, "Should not have any metric readers when otlp is not included in the list");
});

it("constructor creates OTLP metric reader when OTEL_METRICS_EXPORTER contains uppercase OTLP", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "OTLP",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(options.metricReaders, "metricReaders should be present in options when OTLP is uppercase");
assert.equal(options.metricReaders.length, 1, "Should have exactly one metric reader");

// Verify the metric reader is a PeriodicExportingMetricReader
const metricReader = options.metricReaders[0];
assert.equal(metricReader.constructor.name, "PeriodicExportingMetricReader", "Should be a PeriodicExportingMetricReader");

// Verify the exporter is an OTLP exporter
const exporter = (metricReader as any)._exporter;
assert.equal(exporter.constructor.name, "OTLPMetricExporter", "Should be an OTLPMetricExporter");
});

it("constructor creates OTLP metric reader when OTEL_METRICS_EXPORTER contains mixed case otlp with other exporters", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_METRICS_EXPORTER"]: "CONSOLE,OtLp,PROMETHEUS",
["OTEL_EXPORTER_OTLP_ENDPOINT"]: "http://localhost:4317"
};
process.env = env;

const agent = new AKSLoader();

// Verify that metricReaders were added to the options
const options = (agent as any)._options;
assert.ok(options.metricReaders, "metricReaders should be present in options when OtLp is mixed case with other exporters");
assert.equal(options.metricReaders.length, 1, "Should have exactly one metric reader");

// Verify the metric reader is a PeriodicExportingMetricReader
const metricReader = options.metricReaders[0];
assert.equal(metricReader.constructor.name, "PeriodicExportingMetricReader", "Should be a PeriodicExportingMetricReader");

// Verify the exporter is an OTLP exporter
const exporter = (metricReader as any)._exporter;
assert.equal(exporter.constructor.name, "OTLPMetricExporter", "Should be an OTLPMetricExporter");
});
});
Loading