From c949fffcef17836e38586a5d2300d1c79ac6520c Mon Sep 17 00:00:00 2001 From: Jackson Weber <47067795+JacksonWeber@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:18:03 -0800 Subject: [PATCH] Add New Features to Statsbeat (#1250) * Add new features to statsbeat. * Clean up native metrics statsbeat logic and add tests. * Update NativePerformance.tests.ts * Update NativePerformance.tests.ts * Ensure that undefined client/statsbeat will not error out. * Update statsbeat value for native metrics. * Update JsonConfig tests as overloaded readFileSync method is not attaching spy correctly. --- AutoCollection/NativePerformance.ts | 9 ++ AutoCollection/WebSnippet.ts | 4 +- Declarations/Constants.ts | 2 + Library/JsonConfig.ts | 9 +- Library/QuickPulseStateManager.ts | 9 +- Library/TelemetryClient.ts | 2 +- .../AutoCollection/NativePerformance.tests.ts | 7 ++ Tests/AutoCollection/Statsbeat.tests.ts | 4 + Tests/Library/QuickPulseStateManager.tests.ts | 49 ++++++-- Tests/Library/jsonConfig.tests.ts | 9 +- ...formanceMetricsTelemetryProcessor.tests.ts | 18 ++- applicationinsights.ts | 4 +- package-lock.json | 108 +++++++++--------- 13 files changed, 151 insertions(+), 83 deletions(-) diff --git a/AutoCollection/NativePerformance.ts b/AutoCollection/NativePerformance.ts index 711f57bd0..0cdd05459 100644 --- a/AutoCollection/NativePerformance.ts +++ b/AutoCollection/NativePerformance.ts @@ -3,6 +3,7 @@ import Constants = require("../Declarations/Constants"); import Context = require("../Library/Context"); import Logging = require("../Library/Logging"); import { IBaseConfig } from "../Declarations/Interfaces"; +import Statsbeat = require("./Statsbeat"); /** * Interface which defines which specific extended metrics should be disabled @@ -26,6 +27,7 @@ export class AutoCollectNativePerformance { private _handle: NodeJS.Timer; private _client: TelemetryClient; private _disabledMetrics: IDisabledExtendedMetrics = {}; + private _statsbeat: Statsbeat | undefined; constructor(client: TelemetryClient) { // Note: Only 1 instance of this can exist. So when we reconstruct this object, @@ -35,6 +37,7 @@ export class AutoCollectNativePerformance { } AutoCollectNativePerformance.INSTANCE = this; this._client = client; + this._statsbeat = this._client?.getStatsbeat(); } /** @@ -67,6 +70,9 @@ export class AutoCollectNativePerformance { // Enable the emitter if we were able to construct one if (this._isEnabled && AutoCollectNativePerformance._emitter) { + if (this._statsbeat) { + this._statsbeat.addFeature(Constants.StatsbeatFeature.NATIVE_METRICS); + } // enable self AutoCollectNativePerformance._emitter.enable(true, collectionInterval); if (!this._handle) { @@ -74,6 +80,9 @@ export class AutoCollectNativePerformance { this._handle.unref(); } } else if (AutoCollectNativePerformance._emitter) { + if (this._statsbeat) { + this._statsbeat.removeFeature(Constants.StatsbeatFeature.NATIVE_METRICS); + } // disable self AutoCollectNativePerformance._emitter.enable(false); if (this._handle) { diff --git a/AutoCollection/WebSnippet.ts b/AutoCollection/WebSnippet.ts index f01cfd83e..53bc40aae 100644 --- a/AutoCollection/WebSnippet.ts +++ b/AutoCollection/WebSnippet.ts @@ -23,7 +23,7 @@ class WebSnippet { private _isEnabled: boolean; private _isInitialized: boolean; private _isIkeyValid: boolean = true; - private _statsbeat: Statsbeat; + private _statsbeat: Statsbeat | undefined; private _webInstrumentationIkey: string; private _clientWebInstrumentationConfig: IWebInstrumentationConfig[]; private _clientWebInstrumentationSrc: string; @@ -43,7 +43,7 @@ class WebSnippet { this._clientWebInstrumentationConfig = client.config.webInstrumentationConfig; this._clientWebInstrumentationSrc = client.config.webInstrumentationSrc; - this._statsbeat = client.getStatsbeat(); + this._statsbeat = client?.getStatsbeat(); } public enable(isEnabled: boolean, webInstrumentationConnectionString?: string ) { diff --git a/Declarations/Constants.ts b/Declarations/Constants.ts index b9d1a64f0..cf13f91da 100644 --- a/Declarations/Constants.ts +++ b/Declarations/Constants.ts @@ -162,6 +162,8 @@ export enum StatsbeatFeature { DISK_RETRY = 1, AAD_HANDLING = 2, WEB_SNIPPET = 4, + LIVE_METRICS = 16, + NATIVE_METRICS = 8192 } export enum StatsbeatInstrumentation { diff --git a/Library/JsonConfig.ts b/Library/JsonConfig.ts index a5df4ff19..33ba3ba73 100644 --- a/Library/JsonConfig.ts +++ b/Library/JsonConfig.ts @@ -35,6 +35,7 @@ const ENV_webSnippet_connectionString = "APPLICATIONINSIGHTS_WEB_SNIPPET_CONNECT export class JsonConfig implements IJsonConfig { private static _instance: JsonConfig; + private _tempDir: string; public connectionString: string; public instrumentationKey: string; @@ -130,17 +131,17 @@ export class JsonConfig implements IJsonConfig { else { let configFileName = "applicationinsights.json"; let rootPath = path.join(__dirname, "../../"); // Root of applicationinsights folder (__dirname = ../out/Library) - let tempDir = path.join(rootPath, configFileName); // default + this._tempDir = path.join(rootPath, configFileName); // default let configFile = process.env[ENV_CONFIGURATION_FILE]; if (configFile) { if (path.isAbsolute(configFile)) { - tempDir = configFile; + this._tempDir = configFile; } else { - tempDir = path.join(rootPath, configFile);// Relative path to applicationinsights folder + this._tempDir = path.join(rootPath, configFile);// Relative path to applicationinsights folder } try { - jsonString = fs.readFileSync(tempDir, "utf8"); + jsonString = fs.readFileSync(this._tempDir, "utf8"); } catch (err) { Logging.warn("Failed to read JSON config file: ", err); diff --git a/Library/QuickPulseStateManager.ts b/Library/QuickPulseStateManager.ts index 23a5b9fed..2e2520402 100644 --- a/Library/QuickPulseStateManager.ts +++ b/Library/QuickPulseStateManager.ts @@ -8,6 +8,8 @@ import Context = require("./Context"); import * as http from "http"; import * as Contracts from "../Declarations/Contracts"; +import Statsbeat = require("../AutoCollection/Statsbeat"); +import TelemetryClient = require("./TelemetryClient"); /** State Container for sending to the QuickPulse Service */ @@ -33,12 +35,14 @@ class QuickPulseStateManager { private _collectors: { enable: (enable: boolean) => void }[] = []; private _redirectedHost: string = null; private _pollingIntervalHint: number = -1; + private _statsbeat: Statsbeat | undefined; - constructor(config: Config, context?: Context, getAuthorizationHandler?: (config: Config) => AuthorizationHandler) { + constructor(config: Config, context?: Context, getAuthorizationHandler?: (config: Config) => AuthorizationHandler, client?: TelemetryClient) { this.config = config; this.context = context || new Context(); this._sender = new QuickPulseSender(this.config, getAuthorizationHandler); this._isEnabled = false; + this._statsbeat = client?.getStatsbeat(); } /** @@ -78,6 +82,9 @@ class QuickPulseStateManager { if (isEnabled && !this._isEnabled) { this._isEnabled = true; this._goQuickPulse(); + if (this._statsbeat) { + this._statsbeat.addFeature(Constants.StatsbeatFeature.LIVE_METRICS); + } } else if (!isEnabled && this._isEnabled) { this._isEnabled = false; clearTimeout(this._handle); diff --git a/Library/TelemetryClient.ts b/Library/TelemetryClient.ts index 6636be9b6..6ea268624 100644 --- a/Library/TelemetryClient.ts +++ b/Library/TelemetryClient.ts @@ -24,7 +24,7 @@ import { Tags } from "../Declarations/Contracts"; class TelemetryClient { private static TAG = "TelemetryClient"; private _telemetryProcessors: { (envelope: Contracts.EnvelopeTelemetry, contextObjects: { [name: string]: any; }): boolean; }[] = []; - private _statsbeat: Statsbeat; + private _statsbeat: Statsbeat | undefined; public config: Config; public context: Context; diff --git a/Tests/AutoCollection/NativePerformance.tests.ts b/Tests/AutoCollection/NativePerformance.tests.ts index 50fc2848e..3524a4b40 100644 --- a/Tests/AutoCollection/NativePerformance.tests.ts +++ b/Tests/AutoCollection/NativePerformance.tests.ts @@ -5,6 +5,7 @@ import AppInsights = require("../../applicationinsights"); import TelemetryClient = require("../../Library/TelemetryClient"); import { AutoCollectNativePerformance } from "../../AutoCollection/NativePerformance"; import { JsonConfig } from "../../Library/JsonConfig"; +import * as Constants from "../../Declarations/Constants"; const ENV_nativeMetricsDisablers = "APPLICATION_INSIGHTS_DISABLE_EXTENDED_METRIC"; const ENV_nativeMetricsDisableAll = "APPLICATION_INSIGHTS_DISABLE_ALL_EXTENDED_METRICS"; @@ -25,6 +26,8 @@ describe("AutoCollection/NativePerformance", () => { it("init should enable and dispose should stop autocollection interval", () => { var setIntervalSpy = sandbox.spy(global, "setInterval"); var clearIntervalSpy = sandbox.spy(global, "clearInterval"); + const statsAddSpy = sandbox.spy(AutoCollectNativePerformance.INSTANCE["_statsbeat"], "addFeature"); + const statsRemoveSpy = sandbox.spy(AutoCollectNativePerformance.INSTANCE["_statsbeat"], "removeFeature"); AppInsights.setup("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333") .setAutoCollectHeartbeat(false) @@ -32,8 +35,12 @@ describe("AutoCollection/NativePerformance", () => { .setAutoCollectPreAggregatedMetrics(false) .start(); if (AutoCollectNativePerformance["_metricsAvailable"]) { + assert.ok(statsAddSpy.calledOnce); + assert.strictEqual(AutoCollectNativePerformance.INSTANCE["_statsbeat"]["_feature"], Constants.StatsbeatFeature.NATIVE_METRICS + Constants.StatsbeatFeature.DISK_RETRY); assert.equal(setIntervalSpy.callCount, 3, "setInteval should be called three times as part of NativePerformance initialization as well as Statsbeat"); AppInsights.dispose(); + assert.ok(statsRemoveSpy.calledOnce); + assert.strictEqual(AutoCollectNativePerformance.INSTANCE["_statsbeat"]["_feature"], Constants.StatsbeatFeature.DISK_RETRY); assert.equal(clearIntervalSpy.callCount, 1, "clearInterval should be called once as part of NativePerformance shutdown"); } else { assert.equal(setIntervalSpy.callCount, 2, "setInterval should not be called if NativePerformance package is not available, Statsbeat will be called"); diff --git a/Tests/AutoCollection/Statsbeat.tests.ts b/Tests/AutoCollection/Statsbeat.tests.ts index 2abf8137e..89a96f3d0 100644 --- a/Tests/AutoCollection/Statsbeat.tests.ts +++ b/Tests/AutoCollection/Statsbeat.tests.ts @@ -323,6 +323,10 @@ describe("AutoCollection/Statsbeat", () => { assert.equal(statsBeat["_feature"], 3); statsBeat.removeFeature(Constants.StatsbeatFeature.DISK_RETRY); assert.equal(statsBeat["_feature"], 2); + statsBeat.addFeature(Constants.StatsbeatFeature.LIVE_METRICS); + assert.equal(statsBeat["_feature"], 18); + statsBeat.addFeature(Constants.StatsbeatFeature.NATIVE_METRICS); + assert.equal(statsBeat["_feature"], 8210); }); it("Multiple network categories and endpoints", (done) => { diff --git a/Tests/Library/QuickPulseStateManager.tests.ts b/Tests/Library/QuickPulseStateManager.tests.ts index ab4df29ad..fdf4c763f 100644 --- a/Tests/Library/QuickPulseStateManager.tests.ts +++ b/Tests/Library/QuickPulseStateManager.tests.ts @@ -9,6 +9,7 @@ import { IncomingMessage } from "http"; import Config = require("../../Library/Config"); import QuickPulseSender = require("../../Library/QuickPulseSender"); import Util = require("../../Library/Util"); +import { TelemetryClient } from "../../applicationinsights"; describe("Library/QuickPulseStateManager", () => { Util.tlsRestrictedAgent = new https.Agent(); @@ -20,7 +21,7 @@ describe("Library/QuickPulseStateManager", () => { }); it("should create a config with ikey", () => { - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); assert.ok(qps.config); assert.equal(qps.config.instrumentationKey, "1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); @@ -33,8 +34,16 @@ describe("Library/QuickPulseStateManager", () => { assert.ok(qps["_collectors"].length === 0); }); + it("should not error if statsbeat is undefined", () => { + const client: TelemetryClient = new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); + client["_statsbeat"] = undefined; + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, client); + assert.ok(qps); + }); + it("should reuse authorization handler if provided", () => { - var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); + const config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); + var client = new TelemetryClient("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333;"); var handler = new AuthorizationHandler({ async getToken(scopes: string | string[], options?: any): Promise { return { token: "testToken", }; @@ -44,7 +53,7 @@ describe("Library/QuickPulseStateManager", () => { return handler; }; qps = new QuickPulseClient(config, null, getAuthorizationHandler); - assert.equal(qps["_sender"]["_getAuthorizationHandler"](config), handler); + assert.equal(qps["_sender"]["_getAuthorizationHandler"](client.config), handler); }); }); @@ -52,18 +61,38 @@ describe("Library/QuickPulseStateManager", () => { let qps: QuickPulseClient; beforeEach(() => { - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); }) afterEach(() => { qps = null; }); it("should call _goQuickPulse() when isEnabled == true", () => { + const sinonSpy = sinon.spy(qps["_statsbeat"], "addFeature"); + const qpsStub = sinon.stub(qps, "_goQuickPulse"); + + assert.ok(qpsStub.notCalled); + qps.enable(true); + + assert.ok(sinonSpy.calledOnce); + assert.ok(qpsStub.calledOnce); + assert.equal(qps["_isEnabled"], true); + assert.equal(qps["_statsbeat"]["_feature"], 16); + + qpsStub.restore(); + }); + + it("should handle calling enable twice", () => { + const sinonSpy = sinon.spy(qps["_statsbeat"], "addFeature"); const qpsStub = sinon.stub(qps, "_goQuickPulse"); assert.ok(qpsStub.notCalled); qps.enable(true); + qps.enable(true); + + assert.ok(sinonSpy.calledOnce); assert.ok(qpsStub.calledOnce); assert.equal(qps["_isEnabled"], true); + assert.equal(qps["_statsbeat"]["_feature"], 16); qpsStub.restore(); }); @@ -83,7 +112,7 @@ describe("Library/QuickPulseStateManager", () => { describe("#reset", () => { it("should reset metric and document buffers", () => { - let qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + let qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); (qps["_metrics"]) = { foo: "bar" }; (qps["_documents"]) = [{ foo: "bar" }]; @@ -103,7 +132,7 @@ describe("Library/QuickPulseStateManager", () => { let pingStub: sinon.SinonStub; beforeEach(() => { - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); postStub = sinon.stub(qps, "_post"); pingStub = sinon.stub(qps, "_ping"); }) @@ -144,7 +173,7 @@ describe("Library/QuickPulseStateManager", () => { beforeEach(() => { clock = sinon.useFakeTimers(); - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); postStub = sinon.stub(qps, "_post"); pingStub = sinon.stub(qps, "_ping"); }) @@ -183,7 +212,7 @@ describe("Library/QuickPulseStateManager", () => { beforeEach(() => { clock = sinon.useFakeTimers(); - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); submitDataStub = sinon.stub(qps['_sender'], "_submitData"); }) afterEach(() => { @@ -234,7 +263,7 @@ describe("Library/QuickPulseStateManager", () => { let qps: QuickPulseClient; beforeEach(() => { - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); }) afterEach(() => { @@ -272,7 +301,7 @@ describe("Library/QuickPulseStateManager", () => { beforeEach(() => { sandbox = sinon.sandbox.create(); - qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); + qps = new QuickPulseClient(new Config("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"), undefined, undefined, new TelemetryClient("1aa11111-bbbb-1ccc-8ddd-eeeeffff3333")); }); afterEach(() => { diff --git a/Tests/Library/jsonConfig.tests.ts b/Tests/Library/jsonConfig.tests.ts index afc883a41..71f8fe7c0 100644 --- a/Tests/Library/jsonConfig.tests.ts +++ b/Tests/Library/jsonConfig.tests.ts @@ -1,12 +1,9 @@ import assert = require("assert"); import sinon = require("sinon"); -import fs = require("fs"); import path = require("path"); import AppInsights = require("../../applicationinsights"); import Logging = require("../../Library/Logging"); import { JsonConfig } from "../../Library/JsonConfig"; -import { IConfig } from "../../Declarations/Interfaces"; - describe("Json Config", () => { var sandbox: sinon.SinonSandbox; @@ -31,13 +28,11 @@ describe("Json Config", () => { describe("config path", () => { it("Default file path", () => { - let fileSpy = sandbox.spy(fs, "readFileSync"); let loggerSpy = sandbox.spy(Logging, "info"); const config = JsonConfig.getInstance(); assert.equal(loggerSpy.callCount, 0); - assert.equal(fileSpy.called, 1); - let defaultPath = path.resolve(process.cwd(), "applicationinsights.json"); - assert.equal(fileSpy.args[0][0], defaultPath); + const defaultPath = path.resolve(process.cwd(), "applicationinsights.json"); + assert.deepStrictEqual(config["_tempDir"], defaultPath); assert.equal(config.proxyHttpUrl, undefined); }); diff --git a/Tests/TelemetryProcessors/PerformanceMetricsTelemetryProcessor.tests.ts b/Tests/TelemetryProcessors/PerformanceMetricsTelemetryProcessor.tests.ts index 043b89ebb..d233724f0 100644 --- a/Tests/TelemetryProcessors/PerformanceMetricsTelemetryProcessor.tests.ts +++ b/Tests/TelemetryProcessors/PerformanceMetricsTelemetryProcessor.tests.ts @@ -5,7 +5,7 @@ import Config = require("../../Library/Config"); import QuickPulse = require("../../TelemetryProcessors/PerformanceMetricsTelemetryProcessor"); import QuickPulseStateManager = require("../../Library/QuickPulseStateManager"); import AutoCollectPerformance = require("../../AutoCollection/Performance"); -import { Contracts } from "../../applicationinsights"; +import { Contracts, TelemetryClient } from "../../applicationinsights"; describe("TelemetryProcessors/PerformanceMetricsTelemetryProcessor", () => { describe("#PerformanceMetricsTelemetryProcessor()", () => { @@ -35,7 +35,7 @@ describe("TelemetryProcessors/PerformanceMetricsTelemetryProcessor", () => { it("should add document to the provided client", () => { var qpSpy = sinon.spy(QuickPulse, "performanceMetricsTelemetryProcessor"); - var client: QuickPulseStateManager = new QuickPulseStateManager(new Config(ikey)); + var client: QuickPulseStateManager = new QuickPulseStateManager(new Config(ikey), undefined, undefined, new TelemetryClient(ikey)); var addDocumentStub = sinon.stub(client, "addDocument"); // Act @@ -50,5 +50,19 @@ describe("TelemetryProcessors/PerformanceMetricsTelemetryProcessor", () => { qpSpy.restore(); addDocumentStub.restore(); }); + + it("should not error on undefined statsbeat", () => { + const qpSpy = sinon.spy(QuickPulse, "performanceMetricsTelemetryProcessor"); + const telemetryClient = new TelemetryClient(ikey); + telemetryClient["_statsbeat"] = undefined; + + const client: QuickPulseStateManager = new QuickPulseStateManager(new Config(ikey), undefined, undefined, telemetryClient); + + const res = QuickPulse.performanceMetricsTelemetryProcessor(envelope, client); + + assert.ok(qpSpy.calledOnce); + assert.equal(res, true); + qpSpy.restore(); + }) }); }); diff --git a/applicationinsights.ts b/applicationinsights.ts index 4cc24ce88..8c313aa90 100644 --- a/applicationinsights.ts +++ b/applicationinsights.ts @@ -158,7 +158,7 @@ export function start() { // Initialize Live metrics in case config was provided in telemetryClient config, double initialization check is part of liveMetrics client if (!liveMetricsClient) { // No qps client exists. Create one and prepare it to be enabled at .start() - liveMetricsClient = new QuickPulseClient(defaultClient.config, defaultClient.context, defaultClient.getAuthorizationHandler); + liveMetricsClient = new QuickPulseClient(defaultClient.config, defaultClient.context, defaultClient.getAuthorizationHandler, defaultClient); _performanceLiveMetrics = new AutoCollectPerformance(liveMetricsClient as any, 1000, true); liveMetricsClient.addCollector(_performanceLiveMetrics); defaultClient.quickPulseClient = liveMetricsClient; // Need this so we can forward all manual tracks to live metrics via PerformanceMetricsTelemetryProcessor @@ -483,7 +483,7 @@ export class Configuration { if (!liveMetricsClient && enable) { // No qps client exists. Create one and prepare it to be enabled at .start() - liveMetricsClient = new QuickPulseClient(defaultClient.config, defaultClient.context, defaultClient.getAuthorizationHandler); + liveMetricsClient = new QuickPulseClient(defaultClient.config, defaultClient.context, defaultClient.getAuthorizationHandler, defaultClient); _performanceLiveMetrics = new AutoCollectPerformance(liveMetricsClient as any, 1000, true); liveMetricsClient.addCollector(_performanceLiveMetrics); defaultClient.quickPulseClient = liveMetricsClient; // Need this so we can forward all manual tracks to live metrics via PerformanceMetricsTelemetryProcessor diff --git a/package-lock.json b/package-lock.json index 60839a9e5..dce4a3630 100644 --- a/package-lock.json +++ b/package-lock.json @@ -190,9 +190,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -213,9 +213,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", - "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.55.0.tgz", + "integrity": "sha512-qQfo2mxH5yVom1kacMtZZJFVdW+E70mqHMJvVg6WTLo+VBuQJ4TojZlfWBjK0ve5BdEeNAVxOsl/nvNMpJOaJA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -315,25 +315,25 @@ } }, "node_modules/@opentelemetry/api": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.6.0.tgz", - "integrity": "sha512-OWlrQAnWn9577PhVgqjUvMr1pg57Bc4jv0iL4w0PRuOSRvq67rvHW9Ie/dZVMvCzhSCB+UxhcY/PmCmFj33Q+g==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.7.0.tgz", + "integrity": "sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw==", "engines": { "node": ">=8.0.0" } }, "node_modules/@opentelemetry/core": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.17.1.tgz", - "integrity": "sha512-I6LrZvl1FF97FQXPR0iieWQmKnGxYtMbWA1GrAXnLUR+B1Hn2m8KqQNEIlZAucyv00GBgpWkpllmULmZfG8P3g==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.18.1.tgz", + "integrity": "sha512-kvnUqezHMhsQvdsnhnqTNfAJs3ox/isB0SVrM1dhVFw7SsB7TstuVa6fgWnN2GdPyilIFLUvvbTZoVRmx6eiRg==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.17.1" + "@opentelemetry/semantic-conventions": "1.18.1" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.7.0" + "@opentelemetry/api": ">=1.0.0 <1.8.0" } }, "node_modules/@opentelemetry/instrumentation": { @@ -355,40 +355,40 @@ } }, "node_modules/@opentelemetry/resources": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.17.1.tgz", - "integrity": "sha512-M2e5emqg5I7qRKqlzKx0ROkcPyF8PbcSaWEdsm72od9txP7Z/Pl8PDYOyu80xWvbHAWk5mDxOF6v3vNdifzclA==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.18.1.tgz", + "integrity": "sha512-JjbcQLYMttXcIabflLRuaw5oof5gToYV9fuXbcsoOeQ0BlbwUn6DAZi++PNsSz2jjPeASfDls10iaO/8BRIPRA==", "dependencies": { - "@opentelemetry/core": "1.17.1", - "@opentelemetry/semantic-conventions": "1.17.1" + "@opentelemetry/core": "1.18.1", + "@opentelemetry/semantic-conventions": "1.18.1" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.7.0" + "@opentelemetry/api": ">=1.0.0 <1.8.0" } }, "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.17.1.tgz", - "integrity": "sha512-pfSJJSjZj5jkCJUQZicSpzN8Iz9UKMryPWikZRGObPnJo6cUSoKkjZh6BM3j+D47G4olMBN+YZKYqkFM1L6zNA==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.18.1.tgz", + "integrity": "sha512-tRHfDxN5dO+nop78EWJpzZwHsN1ewrZRVVwo03VJa3JQZxToRDH29/+MB24+yoa+IArerdr7INFJiX/iN4gjqg==", "dependencies": { - "@opentelemetry/core": "1.17.1", - "@opentelemetry/resources": "1.17.1", - "@opentelemetry/semantic-conventions": "1.17.1" + "@opentelemetry/core": "1.18.1", + "@opentelemetry/resources": "1.18.1", + "@opentelemetry/semantic-conventions": "1.18.1" }, "engines": { "node": ">=14" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.7.0" + "@opentelemetry/api": ">=1.0.0 <1.8.0" } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.17.1.tgz", - "integrity": "sha512-xbR2U+2YjauIuo42qmE8XyJK6dYeRMLJuOlUP5SO4auET4VtOHOzgkRVOq+Ik18N+Xf3YPcqJs9dZMiDddz1eQ==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.18.1.tgz", + "integrity": "sha512-+NLGHr6VZwcgE/2lw8zDIufOCGnzsA5CbQIMleXZTrgkBd0TanCX+MiDYJ1TOS4KL/Tqk0nFRxawnaYr6pkZkA==", "engines": { "node": ">=14" } @@ -402,9 +402,9 @@ } }, "node_modules/@types/cls-hooked": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.7.tgz", - "integrity": "sha512-cSLdCRRDCzrFY2qB6VfF5ZOWC29zr6Cx6/XRI1IbD9RWOSU/bP4B6l24kjoQBScHtt8J+1GGAHX5edsNhzCtfA==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/@types/cls-hooked/-/cls-hooked-4.3.8.tgz", + "integrity": "sha512-tf/7H883gFA6MPlWI15EQtfNZ+oPL0gLKkOlx9UHFrun1fC/FkuyNBpTKq1B5E3T4fbvjId6WifHUdSGsMMuPg==", "dev": true, "dependencies": { "@types/node": "*" @@ -429,9 +429,9 @@ "dev": true }, "node_modules/@types/shimmer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.4.tgz", - "integrity": "sha512-hsughtxFsdJ9+Gxd/qH8zHE+KT6YEAxx9hJLoSXhxTBKHMQ2NMhN23fRJ75M9RRn2hDMNn13H3gS1EktA9VgDA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.0.5.tgz", + "integrity": "sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww==" }, "node_modules/@types/sinon": { "version": "2.1.2", @@ -452,9 +452,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "bin": { "acorn": "bin/acorn" }, @@ -1036,15 +1036,15 @@ } }, "node_modules/eslint": { - "version": "8.52.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", - "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "version": "8.55.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.55.0.tgz", + "integrity": "sha512-iyUUAM0PCKj5QpwGfmCAG9XXbZCWsqP/eWAWrG/W0umvjuLRBECwSFdt+rCntju0xEH7teIABPwXpahftIaTdA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.52.0", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.55.0", "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -1326,9 +1326,9 @@ } }, "node_modules/flat-cache": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", - "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, "dependencies": { "flatted": "^3.2.9", @@ -1336,7 +1336,7 @@ "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { @@ -1662,9 +1662,9 @@ } }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", + "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", "dev": true, "engines": { "node": ">= 4" @@ -2449,9 +2449,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "engines": { "node": ">=6"