Skip to content
Closed
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
23 changes: 23 additions & 0 deletions src/agent/aksLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,27 @@ export class AKSLoader extends AgentLoader {
);
}
}

public initialize() {
// For AKS auto attach scenario, temporarily store and remove OTEL_TRACES_EXPORTER and OTEL_LOGS_EXPORTER
// to ensure they don't interfere with useAzureMonitor setup
const originalTracesExporter = process.env.OTEL_TRACES_EXPORTER;
const originalLogsExporter = process.env.OTEL_LOGS_EXPORTER;

delete process.env.OTEL_TRACES_EXPORTER;
delete process.env.OTEL_LOGS_EXPORTER;

try {
// Call parent initialize method
super.initialize();
} finally {
// Restore the original environment variables after useAzureMonitor is complete
if (originalTracesExporter !== undefined) {
process.env.OTEL_TRACES_EXPORTER = originalTracesExporter;
}
if (originalLogsExporter !== undefined) {
process.env.OTEL_LOGS_EXPORTER = originalLogsExporter;
}
}
}
}
107 changes: 107 additions & 0 deletions test/unitTests/agent/aksLoader.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,111 @@ describe("agent/AKSLoader", () => {
let loggerProvider = logs.getLoggerProvider() as any;
assert.equal(loggerProvider.constructor.name, "LoggerProvider");
});

describe("OTEL environment variable handling", () => {
it("should remove OTEL_TRACES_EXPORTER and OTEL_LOGS_EXPORTER during initialization", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_TRACES_EXPORTER"]: "jaeger",
["OTEL_LOGS_EXPORTER"]: "console"
};
process.env = env;

const agent = new AKSLoader();

// Spy on the parent initialize method to check environment during call
let envDuringParentCall: { traces?: string; logs?: string } = {};
const originalInitialize = Object.getPrototypeOf(Object.getPrototypeOf(agent)).initialize;
const parentInitializeSpy = sandbox.stub(Object.getPrototypeOf(Object.getPrototypeOf(agent)), 'initialize').callsFake(function() {
Comment on lines +77 to +78
Copy link

Copilot AI Aug 30, 2025

Choose a reason for hiding this comment

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

The double Object.getPrototypeOf() calls are difficult to read and maintain. Consider storing the parent class in a variable or using a more explicit approach to access the grandparent's initialize method.

Suggested change
const originalInitialize = Object.getPrototypeOf(Object.getPrototypeOf(agent)).initialize;
const parentInitializeSpy = sandbox.stub(Object.getPrototypeOf(Object.getPrototypeOf(agent)), 'initialize').callsFake(function() {
const grandparentProto = Object.getPrototypeOf(Object.getPrototypeOf(agent));
const originalInitialize = grandparentProto.initialize;
const parentInitializeSpy = sandbox.stub(grandparentProto, 'initialize').callsFake(function() {

Copilot uses AI. Check for mistakes.
envDuringParentCall.traces = process.env.OTEL_TRACES_EXPORTER;
envDuringParentCall.logs = process.env.OTEL_LOGS_EXPORTER;
return originalInitialize.call(this);
});

agent.initialize();

// Verify that environment variables were undefined during parent initialize call
assert.strictEqual(envDuringParentCall.traces, undefined, "OTEL_TRACES_EXPORTER should be undefined during parent initialize");
assert.strictEqual(envDuringParentCall.logs, undefined, "OTEL_LOGS_EXPORTER should be undefined during parent initialize");

// Verify parent initialize was called
assert.ok(parentInitializeSpy.calledOnce, "Parent initialize should be called once");

parentInitializeSpy.restore();
});

it("should restore OTEL_TRACES_EXPORTER and OTEL_LOGS_EXPORTER after initialization", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_TRACES_EXPORTER"]: "jaeger",
["OTEL_LOGS_EXPORTER"]: "console"
};
process.env = env;

const agent = new AKSLoader();
agent.initialize();

// Verify environment variables are restored after initialization
assert.strictEqual(process.env.OTEL_TRACES_EXPORTER, "jaeger", "OTEL_TRACES_EXPORTER should be restored");
assert.strictEqual(process.env.OTEL_LOGS_EXPORTER, "console", "OTEL_LOGS_EXPORTER should be restored");
});

it("should handle cases where OTEL environment variables are not set", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"
// OTEL variables intentionally not set
};
process.env = env;

const agent = new AKSLoader();
agent.initialize();

// Verify that undefined variables remain undefined
assert.strictEqual(process.env.OTEL_TRACES_EXPORTER, undefined, "OTEL_TRACES_EXPORTER should remain undefined");
assert.strictEqual(process.env.OTEL_LOGS_EXPORTER, undefined, "OTEL_LOGS_EXPORTER should remain undefined");
});

it("should restore environment variables even if parent initialize throws", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_TRACES_EXPORTER"]: "jaeger",
["OTEL_LOGS_EXPORTER"]: "console"
};
process.env = env;

const agent = new AKSLoader();

// Stub parent initialize to throw an error
const parentInitializeStub = sandbox.stub(Object.getPrototypeOf(Object.getPrototypeOf(agent)), 'initialize').throws(new Error("Test error"));
Copy link

Copilot AI Aug 30, 2025

Choose a reason for hiding this comment

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

Same issue with double Object.getPrototypeOf() calls making the code hard to read and maintain. Consider extracting this pattern into a helper variable.

Suggested change
const parentInitializeStub = sandbox.stub(Object.getPrototypeOf(Object.getPrototypeOf(agent)), 'initialize').throws(new Error("Test error"));
const parentPrototype = Object.getPrototypeOf(Object.getPrototypeOf(agent));
const parentInitializeStub = sandbox.stub(parentPrototype, 'initialize').throws(new Error("Test error"));

Copilot uses AI. Check for mistakes.

try {
agent.initialize();
assert.fail("Expected initialize to throw an error");
} catch (error: any) {
assert.strictEqual(error.message, "Test error", "Should propagate the error from parent initialize");
}

// Verify environment variables are still restored despite the error
assert.strictEqual(process.env.OTEL_TRACES_EXPORTER, "jaeger", "OTEL_TRACES_EXPORTER should be restored even after error");
assert.strictEqual(process.env.OTEL_LOGS_EXPORTER, "console", "OTEL_LOGS_EXPORTER should be restored even after error");

parentInitializeStub.restore();
});

it("should handle partial environment variable sets correctly", () => {
const env = {
["APPLICATIONINSIGHTS_CONNECTION_STRING"]: "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333",
["OTEL_TRACES_EXPORTER"]: "jaeger"
// OTEL_LOGS_EXPORTER intentionally not set
};
process.env = env;

const agent = new AKSLoader();
agent.initialize();

// Verify that only the set variable is restored
assert.strictEqual(process.env.OTEL_TRACES_EXPORTER, "jaeger", "OTEL_TRACES_EXPORTER should be restored");
assert.strictEqual(process.env.OTEL_LOGS_EXPORTER, undefined, "OTEL_LOGS_EXPORTER should remain undefined");
});
});
});
Loading