Skip to content

Commit b6bcffa

Browse files
authored
Introduce temporary Python distro fix for OTEL compatibility (#1536)
* Update Python agent image tag to 1.0.0b28-aks * Enable OTEL toggle in AppmonitoringAgent configuration * Enable OTEL in validation Helm chart * Enable OTEL logs and metrics in validation Helm chart * Refactor error handling and logging in test apps * Add support for Python-specific OTEL metrics configuration and update tests * Revert Python upgrade, keep 1.0.0b26-aks
1 parent e3e5686 commit b6bcffa

File tree

8 files changed

+72
-10
lines changed

8 files changed

+72
-10
lines changed

appmonitoring/ts/src/Mutations.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ export class Mutations {
165165
/**
166166
* Generates environment variables necessary to configure agents. Agents take configuration from these environment variables once they run.
167167
*/
168-
public static GenerateEnvironmentVariables(podInfo: PodInfo, platforms: AutoInstrumentationPlatforms[], disableAppLogs: boolean, connectionString: string, armId: string, armRegion: string, clusterName: string, otelParams: OtelParams, existingEnvironmentVariables?: Record<string, IEnvironmentVariable>): IEnvironmentVariable[] {
168+
public static GenerateEnvironmentVariables(podInfo: PodInfo, platforms: AutoInstrumentationPlatforms[], disableAppLogs: boolean, connectionString: string, armId: string, armRegion: string, clusterName: string, otelParams: OtelParams, existingEnvironmentVariables?: Record<string, IEnvironmentVariable>, isPythonEnabled?: boolean): IEnvironmentVariable[] {
169169
const ownerNameAttribute = `k8s.${podInfo.ownerKind?.toLowerCase()}.name=${podInfo.ownerName}`;
170170
const ownerUidAttribute = `k8s.${podInfo.ownerKind?.toLowerCase()}.uid=${podInfo.ownerUid}`;
171171
const containerNameAttribute = `k8s.container.name=${podInfo.onlyContainerName}`;
@@ -303,11 +303,14 @@ export class Mutations {
303303
}
304304

305305
if (otelParams.metricsEnabled) {
306+
// //!!! temporary special case: when Python is enabled (via private-preview annotation), set OTEL_METRICS_EXPORTER to "otlp" only
307+
// Python distro can't handle azure_monitor currently
308+
const metricsExporterValue = isPythonEnabled ? "otlp" : "otlp,azure_monitor";
306309
returnValue.push(
307310
// setting this to ensure Microsoft distros do send OTLP metrics (forked, sent to Breeze and OTLP endpoint). For OSS SDKs this defaults to "otlp" anyway, so no impact
308311
{
309312
name: "OTEL_METRICS_EXPORTER",
310-
value: `otlp,azure_monitor`
313+
value: metricsExporterValue
311314
},
312315
{
313316
name: "OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", //!!! http -> https

appmonitoring/ts/src/Patcher.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ export class Patcher {
4949
const enableApplicationLogsAnnotation = spec.template.metadata?.annotations?.[EnableApplicationLogsAnnotationName];
5050
const enableApplicationLogs: boolean = enableApplicationLogsAnnotation?.toLocaleLowerCase() === "true" || enableApplicationLogsAnnotation?.toLocaleLowerCase() === "1";
5151

52+
// determine if Python is enabled (Python can only be enabled via private-preview annotation)
53+
const isPythonPrivatePreview: boolean = platforms.includes(AutoInstrumentationPlatforms.Python);
54+
5255
// add new volumes (used to store agent binaries)
5356
const newVolumes: IVolume[] = Mutations.GenerateVolumes(platforms);
5457
podSpec.volumes = (podSpec.volumes ?? <IVolume[]>[]).concat(newVolumes);
@@ -65,7 +68,7 @@ export class Patcher {
6568
container.env?.forEach(env => allEnvironmentVariables[env.name] = env);
6669

6770
// Generate environment variables with knowledge of existing ones for OTEL_RESOURCE_ATTRIBUTES merging
68-
const newEnvironmentVariables: IEnvironmentVariable[] = Mutations.GenerateEnvironmentVariables(podInfo, platforms, !enableApplicationLogs, cr.spec?.destination?.applicationInsightsConnectionString, armId, armRegion, clusterName, otelParams, allEnvironmentVariables);
71+
const newEnvironmentVariables: IEnvironmentVariable[] = Mutations.GenerateEnvironmentVariables(podInfo, platforms, !enableApplicationLogs, cr.spec?.destination?.applicationInsightsConnectionString, armId, armRegion, clusterName, otelParams, allEnvironmentVariables, isPythonPrivatePreview);
6972

7073
/*
7174
We could be receiving customer's original set of environment variables (e.g. in case of kubectl apply),
@@ -147,7 +150,7 @@ export class Patcher {
147150
// remove environment variables and volume mounts from all containers by name
148151
// we don't care about values of environment variables here, we just need all names, so set parameters to get all of them
149152
const otelParams: OtelParams = { logsEnabled: true, metricsEnabled: true, logsPortHttpProtobuf: 0, metricsPortHttpProtobuf: 0 };
150-
const environmentVariablesToRemove: IEnvironmentVariable[] = Mutations.GenerateEnvironmentVariables(new PodInfo(), allPlatforms, true, "", "", "", "", otelParams);
153+
const environmentVariablesToRemove: IEnvironmentVariable[] = Mutations.GenerateEnvironmentVariables(new PodInfo(), allPlatforms, true, "", "", "", "", otelParams, undefined, false);
151154
const volumeMountsToRemove: IVolumeMount[] = Mutations.GenerateVolumeMounts(allPlatforms);
152155

153156
podSpec.containers?.forEach(container => {

appmonitoring/ts/src/tests/Mutations.spec.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ describe("OTEL Resource Attributes Merging", () => {
3434
"eastus",
3535
"test-cluster",
3636
testOtelParams,
37-
existingEnvironmentVariables
37+
existingEnvironmentVariables,
38+
false
3839
);
3940

4041
const otelResourceAttributes = generatedEnvVars.find(env => env.name === "OTEL_RESOURCE_ATTRIBUTES");
@@ -208,4 +209,56 @@ describe("OTEL Metrics Exporter Environment Variable", () => {
208209
expect(otelMetricsInsecure).toBeDefined();
209210
expect(otelMetricsInsecure!.value).toBe("true");
210211
});
212+
213+
it("should set OTEL_METRICS_EXPORTER to 'otlp' only when Python is enabled", () => {
214+
const testOtelParams: OtelParams = {
215+
logsEnabled: false,
216+
metricsEnabled: true,
217+
logsPortHttpProtobuf: 4318,
218+
metricsPortHttpProtobuf: 4319
219+
};
220+
221+
const generatedEnvVars = Mutations.GenerateEnvironmentVariables(
222+
podInfo,
223+
[AutoInstrumentationPlatforms.Python],
224+
false,
225+
"InstrumentationKey=test-key",
226+
"/subscriptions/test/resourceGroups/test-rg",
227+
"eastus",
228+
"test-cluster",
229+
testOtelParams,
230+
undefined,
231+
true // isPythonEnabled = true
232+
);
233+
234+
const otelMetricsExporter = generatedEnvVars.find(env => env.name === "OTEL_METRICS_EXPORTER");
235+
expect(otelMetricsExporter).toBeDefined();
236+
expect(otelMetricsExporter!.value).toBe("otlp");
237+
});
238+
239+
it("should set OTEL_METRICS_EXPORTER to 'otlp,azure_monitor' when Python is not enabled", () => {
240+
const testOtelParams: OtelParams = {
241+
logsEnabled: false,
242+
metricsEnabled: true,
243+
logsPortHttpProtobuf: 4318,
244+
metricsPortHttpProtobuf: 4319
245+
};
246+
247+
const generatedEnvVars = Mutations.GenerateEnvironmentVariables(
248+
podInfo,
249+
[AutoInstrumentationPlatforms.Python],
250+
false,
251+
"InstrumentationKey=test-key",
252+
"/subscriptions/test/resourceGroups/test-rg",
253+
"eastus",
254+
"test-cluster",
255+
testOtelParams,
256+
undefined,
257+
false // isPythonEnabled = false
258+
);
259+
260+
const otelMetricsExporter = generatedEnvVars.find(env => env.name === "OTEL_METRICS_EXPORTER");
261+
expect(otelMetricsExporter).toBeDefined();
262+
expect(otelMetricsExporter!.value).toBe("otlp,azure_monitor");
263+
});
211264
});

appmonitoring/ts/src/tests/Patcher.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ describe("Patcher", () => {
6666
newVolumes.forEach(vol => expect((<any>result[0]).value.spec.template.spec.volumes).toContainEqual(vol));
6767
admissionReview.request.object.spec.template.spec.volumes.forEach(vol => expect((<any>result[0]).value.spec.template.spec.volumes).toContainEqual(vol));
6868

69-
const newEnvironmentVariables: object[] = Mutations.GenerateEnvironmentVariables(podInfo, platforms, true, cr1.spec.destination.applicationInsightsConnectionString, clusterArmId, clusterArmRegion, clusterName, testOtelParams);
69+
const newEnvironmentVariables: object[] = Mutations.GenerateEnvironmentVariables(podInfo, platforms, true, cr1.spec.destination.applicationInsightsConnectionString, clusterArmId, clusterArmRegion, clusterName, testOtelParams, undefined, platforms.includes(AutoInstrumentationPlatforms.Python));
7070
expect((<any>result[0]).value.spec.template.spec.containers.length).toBe(admissionReview.request.object.spec.template.spec.containers.length);
7171
newEnvironmentVariables.forEach(env => expect((<any>result[0]).value.spec.template.spec.containers[0].env).toContainEqual(env));
7272
newEnvironmentVariables.forEach(env => expect((<any>result[0]).value.spec.template.spec.containers[1].env).toContainEqual(env));
@@ -127,7 +127,7 @@ describe("Patcher", () => {
127127
newVolumes.forEach(vol => expect((<any>result[0]).value.spec.template.spec.volumes).toContainEqual(vol));
128128
admissionReview.request.object.spec.template.spec.volumes.forEach(vol => expect((<any>result[0]).value.spec.template.spec.volumes).toContainEqual(vol));
129129

130-
const newEnvironmentVariables: object[] = Mutations.GenerateEnvironmentVariables(podInfo, cr1.spec.settings.autoInstrumentationPlatforms, true, cr1.spec.destination.applicationInsightsConnectionString, clusterArmId, clusterArmRegion, clusterName, testOtelParams);
130+
const newEnvironmentVariables: object[] = Mutations.GenerateEnvironmentVariables(podInfo, cr1.spec.settings.autoInstrumentationPlatforms, true, cr1.spec.destination.applicationInsightsConnectionString, clusterArmId, clusterArmRegion, clusterName, testOtelParams, undefined, cr1.spec.settings.autoInstrumentationPlatforms.includes(AutoInstrumentationPlatforms.Python));
131131
expect((<any>result[0]).value.spec.template.spec.containers.length).toBe(admissionReview.request.object.spec.template.spec.containers.length);
132132
newEnvironmentVariables.forEach(env => expect((<any>result[0]).value.spec.template.spec.containers[0].env).toContainEqual(env));
133133
newEnvironmentVariables.forEach(env => expect((<any>result[0]).value.spec.template.spec.containers[1].env).toContainEqual(env));

appmonitoring/validation-helm/app-monitoring-addon/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"name": "app-monitoring-addon",
44
"description": "app-monitoring addon helm chart",
55
"type": "application",
6-
"version": "1.0.0-beta.8"
6+
"version": "1.0.0-beta.9"
77
}

appmonitoring/validation-helm/test-apps/dotnet/dotnet-test-app.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task<IActionResult> CallTarget()
5252
}
5353
catch (Exception ex)
5454
{
55-
return StatusCode(500, new { error = $"Failed to reach {targetUrl}: {ex.Message}" });
55+
return StatusCode(500, new { error = $"Failed to reach {targetUrl}" });
5656
}
5757
}
5858
}

appmonitoring/validation-helm/test-apps/java/src/main/java/com/example/HelloController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public String callTarget() {
6767
try {
6868
logger.info("Attempting to call target URL: {}", targetUrl);
6969
String response = restTemplate.getForObject(targetUrl, String.class);
70-
logger.info("Received response from target: {}", response);
70+
logger.info("Received response from target.");
7171
return "Response from target: " + response;
7272
} catch (Exception e) {
7373
logger.error("Error calling target URL: {}", targetUrl, e);

appmonitoring/validation-helm/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ global:
66
Versions:
77
Kubernetes: "1.25.0"
88
AppmonitoringAgent:
9+
isOtelToggleEnabled: true
10+
isOpenTelemetryLogsEnabled: true
11+
isOpenTelemetryMetricsEnabled: true
912
cpuRequest: "100m"
1013
memoryRequest: "128Mi"
1114
cpuLimit: "500m"

0 commit comments

Comments
 (0)