Skip to content

Commit

Permalink
[Beta] Align with SDK versions used by all telemetry (#1137)
Browse files Browse the repository at this point in the history
* Align with SDK versions used by all telemetry

* Add test stubs

* test

* Update

* Test

* Update
  • Loading branch information
hectorhdzg committed May 6, 2023
1 parent 130e58f commit ae42bd3
Show file tree
Hide file tree
Showing 13 changed files with 230 additions and 169 deletions.
17 changes: 13 additions & 4 deletions src/logs/logHandler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { ApplicationInsightsSampler } from "@azure/monitor-opentelemetry-exporter";
import { context, trace } from "@opentelemetry/api";
import { SDK_INFO } from "@opentelemetry/core";
import { IdGenerator, RandomIdGenerator, SamplingDecision, SamplingResult } from "@opentelemetry/sdk-trace-base";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";

Expand Down Expand Up @@ -36,7 +38,7 @@ import {
import { Logger } from "../shared/logging";
import { IStandardMetricBaseDimensions, IMetricTraceDimensions } from "../metrics/types";
import { MetricHandler } from "../metrics/metricHandler";
import { ApplicationInsightsSampler } from "@azure/monitor-opentelemetry-exporter";
import { AZURE_MONITOR_DISTRO_VERSION } from "../declarations/constants";

export class LogHandler {
// Statsbeat is instantiated here such that it can be accessed by the diagnostic-channel.
Expand All @@ -50,6 +52,7 @@ export class LogHandler {
private _metricHandler: MetricHandler;
private _aiSampler: ApplicationInsightsSampler;
private _instrumentationKey: string;
private _aiInternalSdkVersion: string;

constructor(config: ApplicationInsightsConfig, metricHandler?: MetricHandler, statsbeat?: Statsbeat) {
this._config = config;
Expand All @@ -69,6 +72,14 @@ export class LogHandler {
const parsedConnectionString = parser.parse(this._config.azureMonitorExporterConfig.connectionString);
this._instrumentationKey = parsedConnectionString.instrumentationkey;
this._console.enable(this._config.logInstrumentations);

const { node } = process.versions;
let nodeVersion = node.split(".");
let opentelemetryVersion = SDK_INFO[SemanticResourceAttributes.TELEMETRY_SDK_VERSION];
let prefix = process.env["AZURE_MONITOR_AGENT_PREFIX"]
? process.env["AZURE_MONITOR_AGENT_PREFIX"]
: "";
this._aiInternalSdkVersion = `${prefix}node${nodeVersion}:otel${opentelemetryVersion}:dst${AZURE_MONITOR_DISTRO_VERSION}`;
}

/**
Expand Down Expand Up @@ -349,9 +360,7 @@ export class LogHandler {
}
const serviceInstanceId = attributes[SemanticResourceAttributes.SERVICE_INSTANCE_ID];
tags[KnownContextTagKeys.AiCloudRoleInstance] = String(serviceInstanceId);
tags[KnownContextTagKeys.AiInternalSdkVersion] = String(
attributes[SemanticResourceAttributes.TELEMETRY_SDK_VERSION]
);
tags[KnownContextTagKeys.AiInternalSdkVersion] = this._aiInternalSdkVersion;

// Add Correlation headers
const spanContext = trace.getSpanContext(context.active());
Expand Down
62 changes: 31 additions & 31 deletions src/metrics/collection/nativePerformanceMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,38 +37,38 @@ export class NativePerformanceMetrics {
NativeMetricsCounter.MEMORY_USAGE_NON_HEAP
);

// Try to require in the native-metrics library. If it's found initialize it, else do nothing and never try again.
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const NativeMetricsEmitter = require("applicationinsights-native-metrics");
this._emitter = new NativeMetricsEmitter();
Logger.getInstance().info("Native metrics module successfully loaded!");
} catch (err) {
// Package not available.
return;
}
// Enable the emitter if we were able to construct one
if (this._emitter) {
try {
// enable self
this._emitter.enable(true, this._collectionInterval);
} catch (err) {
Logger.getInstance().error("Native metrics enable failed", err);
}
// // Try to require in the native-metrics library. If it's found initialize it, else do nothing and never try again.
// try {
// // eslint-disable-next-line @typescript-eslint/no-var-requires
// const NativeMetricsEmitter = require("applicationinsights-native-metrics");
// this._emitter = new NativeMetricsEmitter();
// Logger.getInstance().info("Native metrics module successfully loaded!");
// } catch (err) {
// // Package not available.
// return;
// }
// // Enable the emitter if we were able to construct one
// if (this._emitter) {
// try {
// // enable self
// this._emitter.enable(true, this._collectionInterval);
// } catch (err) {
// Logger.getInstance().error("Native metrics enable failed", err);
// }

// Add histogram data collection
if (!this._handle) {
this._handle = setInterval(
() => this._collectHistogramData(),
this._collectionInterval
);
this._handle.unref();
}
// Add observable callbacks
this._heapMemoryTotalGauge.addCallback(this._getHeapTotal.bind(this));
this._heapMemoryUsageGauge.addCallback(this._getHeapUsage.bind(this));
this._memoryUsageNonHeapGauge.addCallback(this._getNonHeapUsage.bind(this));
}
// // Add histogram data collection
// if (!this._handle) {
// this._handle = setInterval(
// () => this._collectHistogramData(),
// this._collectionInterval
// );
// this._handle.unref();
// }
// // Add observable callbacks
// this._heapMemoryTotalGauge.addCallback(this._getHeapTotal.bind(this));
// this._heapMemoryUsageGauge.addCallback(this._getHeapUsage.bind(this));
// this._memoryUsageNonHeapGauge.addCallback(this._getNonHeapUsage.bind(this));
// }
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/metrics/handlers/heartBeatHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class HeartBeatHandler {
}

public async shutdown(): Promise<void> {
this._metricGauge.removeCallback(this._metricGaugeCallback);
await this._meterProvider.shutdown();
}

Expand Down
2 changes: 1 addition & 1 deletion src/metrics/handlers/performanceCounterMetricsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ export class PerformanceCounterMetricsHandler {
}

public shutdown() {
this._meterProvider.shutdown();
this._processMetrics.shutdown();
this._requestMetrics.shutdown();
this._meterProvider.shutdown();
}

public recordSpan(span: ReadableSpan): void {
Expand Down
1 change: 0 additions & 1 deletion src/metrics/handlers/standardMetricsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ export class StandardMetricsHandler {
}

public shutdown() {
this._meterProvider.shutdown();
this._dependencyMetrics.shutdown();
this._exceptionMetrics.shutdown();
this._traceMetrics.shutdown();
Expand Down
3 changes: 3 additions & 0 deletions src/metrics/metricHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export class MetricHandler {
await this._perfCounterMetricsHandler?.flush();
}

/**
* @deprecated This should not be used
*/
public getConfig(): ApplicationInsightsConfig {
return this._config;
}
Expand Down
133 changes: 52 additions & 81 deletions test/unitTests/logs/logHandler.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import { ApplicationInsightsClient } from "../../../src";

describe("Library/LogHandler", () => {
let sandbox: sinon.SinonSandbox;
let handler: LogHandler;
let traceHandler: TraceHandler;
let stub: sinon.SinonStub;
let metricHandler: MetricHandler;
const _config = new ApplicationInsightsConfig();
_config.connectionString = "InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;IngestionEndpoint=https://westus.in.applicationinsights.azure.com/;LiveEndpoint=https://west.live.monitor.azure.com/";

Expand All @@ -30,19 +34,39 @@ describe("Library/LogHandler", () => {

afterEach(() => {
sandbox.restore();
handler.shutdown();
if (traceHandler) {
traceHandler.shutdown();
}
if (metricHandler) {
metricHandler.shutdown();
}
});

function createLogHandler(config: ApplicationInsightsConfig, metricHandler?: MetricHandler) {
handler = new LogHandler(config, metricHandler);
stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
}

describe("#autoCollect", () => {
it("exception enablement during start", () => {
_config.enableAutoCollectExceptions = true;
const handler = new LogHandler(_config);
createLogHandler(_config);
assert.ok(handler["_exceptions"], "Exceptions not enabled");
});
});

describe("#manual track APIs", () => {
it("_logToEnvelope", () => {
const handler = new LogHandler(_config);
createLogHandler(_config);
const telemetry: Telemetry = {};
const data: MonitorDomain = {};
const envelope = handler["_logToEnvelope"](
Expand All @@ -64,16 +88,24 @@ describe("Library/LogHandler", () => {
assert.equal(envelope.tags["ai.cloud.role"], "Web");
assert.equal(envelope.tags["ai.cloud.roleInstance"], os.hostname());
assert.ok(
envelope.tags["ai.internal.sdkVersion"].indexOf("node") == 0,
envelope.tags["ai.internal.sdkVersion"].indexOf("node") > 0,
"Incorrect SDK version"
);
assert.ok(
envelope.tags["ai.internal.sdkVersion"].indexOf(":otel") > 0,
"Incorrect SDK version"
);
assert.ok(
envelope.tags["ai.internal.sdkVersion"].indexOf(":dst") > 0,
"Incorrect SDK version"
);
});

it("tracing", () => {
const logHandler = new LogHandler(_config);
const traceHandler = new TraceHandler(_config);
createLogHandler(_config);
traceHandler = new TraceHandler(_config);
traceHandler["_tracer"].startActiveSpan("test", () => {
const envelope = logHandler["_logToEnvelope"]({}, "", {});
const envelope = handler["_logToEnvelope"]({}, "", {});
const spanContext = trace.getSpanContext(context.active());
assert.ok(isValidTraceId(envelope.tags["ai.operation.id"]), "Valid operation Id");
assert.ok(
Expand All @@ -89,8 +121,8 @@ describe("Library/LogHandler", () => {
let otherConfig = new ApplicationInsightsConfig();
otherConfig.connectionString = _config.connectionString;
otherConfig.samplingRatio = 0;
const logHandler = new LogHandler(otherConfig);
const stub = sinon.stub(logHandler["_batchProcessor"], "send");
createLogHandler(otherConfig);
const stub = sinon.stub(handler["_batchProcessor"], "send");
const telemetry: AvailabilityTelemetry = {
name: "TestName",
duration: 2000, //2 seconds
Expand All @@ -99,22 +131,13 @@ describe("Library/LogHandler", () => {
message: "testMessage",
success: false,
};
logHandler.trackAvailability(telemetry);
handler.trackAvailability(telemetry);
assert.ok(stub.notCalled);
});


it("trackAvailability", (done) => {
const handler = new LogHandler(_config);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
createLogHandler(_config);
const telemetry: AvailabilityTelemetry = {
name: "TestName",
duration: 2000, //2 seconds
Expand Down Expand Up @@ -156,16 +179,7 @@ describe("Library/LogHandler", () => {
});

it("trackPageView", (done) => {
const handler = new LogHandler(_config);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
createLogHandler(_config);
const telemetry: PageViewTelemetry = {
name: "TestName",
duration: 2000, //2 seconds
Expand Down Expand Up @@ -205,16 +219,7 @@ describe("Library/LogHandler", () => {
});

it("trackTrace", (done) => {
const handler = new LogHandler(_config);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
createLogHandler(_config);
const telemetry: TraceTelemetry = {
message: "testMessage",
severity: "Information",
Expand Down Expand Up @@ -249,16 +254,7 @@ describe("Library/LogHandler", () => {
});

it("trackException", (done) => {
const handler = new LogHandler(_config);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
createLogHandler(_config);
const measurements: { [key: string]: number } = {};
measurements["test"] = 123;
const telemetry: ExceptionTelemetry = {
Expand Down Expand Up @@ -304,16 +300,7 @@ describe("Library/LogHandler", () => {
});

it("trackEvent", (done) => {
const handler = new LogHandler(_config);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
createLogHandler(_config);
const measurements: { [key: string]: number } = {};
measurements["test"] = 123;
const telemetry: EventTelemetry = {
Expand Down Expand Up @@ -351,17 +338,9 @@ describe("Library/LogHandler", () => {

it("Exception standard metrics processed", (done) => {
_config.enableAutoCollectStandardMetrics = true;
const metricHandler = new MetricHandler(_config);
const handler = new LogHandler(_config, metricHandler);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
metricHandler = new MetricHandler(_config);
createLogHandler(_config, metricHandler);

const telemetry: ExceptionTelemetry = {
exception: new Error("TestError"),
severity: "Critical",
Expand All @@ -385,17 +364,8 @@ describe("Library/LogHandler", () => {

it("Trace standard metrics processed", (done) => {
_config.enableAutoCollectStandardMetrics = true;
const metricHandler = new MetricHandler(_config);
const handler = new LogHandler(_config, metricHandler);
const stub = sinon.stub(handler["_exporter"], "export").callsFake(
(envelopes: any, resultCallback: any) =>
new Promise((resolve, reject) => {
resultCallback({
code: ExportResultCode.SUCCESS,
});
resolve();
})
);
metricHandler = new MetricHandler(_config);
createLogHandler(_config, metricHandler);
const telemetry: TraceTelemetry = {
message: "testMessage",
severity: "Information",
Expand Down Expand Up @@ -424,6 +394,7 @@ describe("Library/LogHandler", () => {
const logsStatsbeatCollection = appInsights["_logHandler"]["_exporter"]["_statsbeatMetrics"]["_networkStatsbeatCollection"];
assert.strictEqual(logsStatsbeatCollection[0].totalSuccesfulRequestCount, 1);
assert.strictEqual(logsStatsbeatCollection[0].intervalRequestExecutionTime, 100);
appInsights.shutdown();
});
});
});

0 comments on commit ae42bd3

Please sign in to comment.