diff --git a/AutoCollection/Statsbeat.ts b/AutoCollection/Statsbeat.ts index f321f02ff..d74435f4b 100644 --- a/AutoCollection/Statsbeat.ts +++ b/AutoCollection/Statsbeat.ts @@ -54,7 +54,7 @@ class Statsbeat { let statsbeatConnectionString = this._getConnectionString(config); this._statsbeatConfig = new Config(statsbeatConnectionString); this._statsbeatConfig.samplingPercentage = 100; // Do not sample - this._sender = new Sender(this._statsbeatConfig, null, null, this._handleNetworkError); + this._sender = new Sender(this._statsbeatConfig, null, null, null, null, true, this._shutdownStatsbeat); } public enable(isEnabled: boolean) { @@ -351,10 +351,8 @@ class Statsbeat { }); } - private _handleNetworkError(error: Error) { - if (error && error.message && error.message.indexOf("ENOTFOUND") > -1) { // ENOTFOUND - this.enable(false);// Disable Statsbeat as is possible SDK is running in private or restricted network - } + private _shutdownStatsbeat() { + this.enable(false);// Disable Statsbeat as is it failed 3 times cosnecutively during initialization, is possible SDK is running in private or restricted network } private _getConnectionString(config: Config): string { diff --git a/Library/Sender.ts b/Library/Sender.ts index 4714b0ad8..6356135c8 100644 --- a/Library/Sender.ts +++ b/Library/Sender.ts @@ -18,6 +18,7 @@ import { FileAccessControl } from "./FileAccessControl"; const legacyThrottleStatusCode = 439; // - Too many requests and refresh cache const throttleStatusCode = 402; // Monthly Quota Exceeded (new SDK) +const RESPONSE_CODES_INDICATING_REACHED_BREEZE = [200, 206, 402, 408, 429, 439, 500]; class Sender { private static TAG = "Sender"; @@ -30,6 +31,10 @@ class Sender { public static TEMPDIR_PREFIX: string = "appInsights-node"; private _config: Config; + private _isStatsbeatSender: boolean; + private _shutdownStatsbeat: () => void; + private _failedToIngestCounter: number; + private _statsbeatHasReachedIngestionAtLeastOnce: boolean; private _statsbeat: Statsbeat; private _onSuccess: (response: string) => void; private _onError: (error: Error) => void; @@ -44,7 +49,7 @@ class Sender { protected _resendInterval: number; protected _maxBytesOnDisk: number; - constructor(config: Config, getAuthorizationHandler?: (config: Config) => AuthorizationHandler, onSuccess?: (response: string) => void, onError?: (error: Error) => void, statsbeat?: Statsbeat) { + constructor(config: Config, getAuthorizationHandler?: (config: Config) => AuthorizationHandler, onSuccess?: (response: string) => void, onError?: (error: Error) => void, statsbeat?: Statsbeat, isStatsbeatSender?: boolean, shutdownStatsbeat?: () => void) { this._config = config; this._onSuccess = onSuccess; this._onError = onError; @@ -59,6 +64,10 @@ class Sender { this._fileCleanupTimer = null; // tmpdir is /tmp for *nix and USERDIR/AppData/Local/Temp for Windows this._tempDir = path.join(os.tmpdir(), Sender.TEMPDIR_PREFIX + this._config.instrumentationKey); + this._isStatsbeatSender = isStatsbeatSender || false; + this._shutdownStatsbeat = shutdownStatsbeat; + this._failedToIngestCounter = 0; + this._statsbeatHasReachedIngestionAtLeastOnce = false; } /** @@ -78,7 +87,7 @@ class Sender { if (value && !FileAccessControl.OS_PROVIDES_FILE_PROTECTION) { this._enableDiskRetryMode = false; - Logging.warn(Sender.TAG, "Ignoring request to enable disk retry mode. Sufficient file protection capabilities were not detected.") + this._logWarn("Ignoring request to enable disk retry mode. Sufficient file protection capabilities were not detected.") } if (this._enableDiskRetryMode) { if (this._statsbeat) { @@ -131,7 +140,7 @@ class Sender { this._storeToDisk(envelopes); } errorMsg += "Error:" + authError.toString(); - Logging.warn(Sender.TAG, errorMsg); + this._logWarn(errorMsg); if (typeof callback === "function") { callback(errorMsg); @@ -158,7 +167,7 @@ class Sender { zlib.gzip(payload, (err, buffer) => { var dataToSend = buffer; if (err) { - Logging.warn(Sender.TAG, err); + this._logWarn(Util.dumpObj(err)); dataToSend = payload; // something went wrong so send without gzip options.headers["Content-Length"] = payload.length.toString(); } else { @@ -166,7 +175,7 @@ class Sender { options.headers["Content-Length"] = buffer.length.toString(); } - Logging.info(Sender.TAG, options); + this._logInfo(Util.dumpObj(options)); // Ensure this request is not captured by auto-collection. (options)[AutoCollectHttpDependencies.disableCollectionRequestOption] = true; @@ -186,6 +195,15 @@ class Sender { let endTime = +new Date(); let duration = endTime - startTime; this._numConsecutiveFailures = 0; + // Handling of Statsbeat instance sending data, should turn it off if is not able to reach ingestion endpoint + if (this._isStatsbeatSender && !this._statsbeatHasReachedIngestionAtLeastOnce) { + if (RESPONSE_CODES_INDICATING_REACHED_BREEZE.includes(res.statusCode)) { + this._statsbeatHasReachedIngestionAtLeastOnce = true; + } + else { + this._statsbeatFailedToIngest(); + } + } if (this._statsbeat) { if (res.statusCode == throttleStatusCode || res.statusCode == legacyThrottleStatusCode) { // Throttle this._statsbeat.countThrottle(Constants.StatsbeatNetworkCategory.Breeze, endpointHost); @@ -257,7 +275,7 @@ class Sender { if (typeof callback === "function") { callback(responseString); } - Logging.info(Sender.TAG, responseString); + this._logInfo(responseString); if (typeof this._onSuccess === "function") { this._onSuccess(responseString); } @@ -268,6 +286,9 @@ class Sender { var req = Util.makeRequest(this._config, endpointUrl, options, requestCallback); req.on("error", (error: Error) => { + if (this._isStatsbeatSender && !this._statsbeatHasReachedIngestionAtLeastOnce) { + this._statsbeatFailedToIngest(); + } // todo: handle error codes better (group to recoverable/non-recoverable and persist) this._numConsecutiveFailures++; if (this._statsbeat) { @@ -282,10 +303,10 @@ class Sender { if (this._enableDiskRetryMode) { notice = `Ingestion endpoint could not be reached ${this._numConsecutiveFailures} consecutive times. There may be resulting telemetry loss. Most recent error:`; } - Logging.warn(Sender.TAG, notice, Util.dumpObj(error)); + this._logWarn(notice, Util.dumpObj(error)); } else { let notice = "Transient failure to reach ingestion endpoint. This batch of telemetry items will be retried. Error:"; - Logging.info(Sender.TAG, notice, Util.dumpObj(error)); + this._logInfo(notice, Util.dumpObj(error)); } this._onErrorHelper(error); @@ -327,16 +348,37 @@ class Sender { ); } + private _logInfo(message?: any, ...optionalParams: any[]) { + if (!this._isStatsbeatSender) { + Logging.info(Sender.TAG, message, optionalParams); + } + } + + private _logWarn(message?: any, ...optionalParams: any[]) { + if (!this._isStatsbeatSender) { + Logging.warn(Sender.TAG, message, optionalParams); + } + } + + private _statsbeatFailedToIngest() { + if (this._shutdownStatsbeat) { // Check if callback is available + this._failedToIngestCounter++; + if (this._failedToIngestCounter >= 3) { + this._shutdownStatsbeat(); + } + } + } + /** * Stores the payload as a json file on disk in the temp directory */ private async _storeToDisk(envelopes: Contracts.EnvelopeTelemetry[]): Promise { try { - Logging.info(Sender.TAG, "Checking existence of data storage directory: " + this._tempDir); + this._logInfo("Checking existence of data storage directory: " + this._tempDir); await FileSystemHelper.confirmDirExists(this._tempDir); } catch (ex) { - Logging.warn(Sender.TAG, "Failed to create folder to put telemetry: " + (ex && ex.message)); + this._logWarn("Failed to create folder to put telemetry: " + Util.dumpObj(ex)); this._onErrorHelper(ex); return; } @@ -344,14 +386,14 @@ class Sender { await FileAccessControl.applyACLRules(this._tempDir); } catch (ex) { - Logging.warn(Sender.TAG, "Failed to apply file access control to folder: " + (ex && ex.message)); + this._logWarn("Failed to apply file access control to folder: " + Util.dumpObj(ex)); this._onErrorHelper(ex); return; } try { let size = await FileSystemHelper.getShallowDirectorySize(this._tempDir); if (size > this._maxBytesOnDisk) { - Logging.warn(Sender.TAG, "Not saving data due to max size limit being met. Directory size in bytes is: " + size); + this._logWarn("Not saving data due to max size limit being met. Directory size in bytes is: " + size); return; } //create file - file name for now is the timestamp, a better approach would be a UUID but that @@ -361,11 +403,11 @@ class Sender { // Mode 600 is w/r for creator and no read access for others (only applies on *nix) // For Windows, ACL rules are applied to the entire directory (see logic in _confirmDirExists and _applyACLRules) - Logging.info(Sender.TAG, "saving data to disk at: " + fileFullPath); + this._logInfo("saving data to disk at: " + fileFullPath); FileSystemHelper.writeFileAsync(fileFullPath, Util.stringify(envelopes), { mode: 0o600 }); } catch (ex) { - Logging.warn(Sender.TAG, "Failed to persist telemetry to disk: " + (ex && ex.message)); + this._logWarn("Failed to persist telemetry to disk: " + Util.dumpObj(ex)); this._onErrorHelper(ex); return; } @@ -377,7 +419,7 @@ class Sender { */ private _storeToDiskSync(payload: any) { try { - Logging.info(Sender.TAG, "Checking existence of data storage directory: " + this._tempDir); + this._logInfo("Checking existence of data storage directory: " + this._tempDir); if (!fs.existsSync(this._tempDir)) { fs.mkdirSync(this._tempDir); } @@ -387,7 +429,7 @@ class Sender { let dirSize = FileSystemHelper.getShallowDirectorySizeSync(this._tempDir); if (dirSize > this._maxBytesOnDisk) { - Logging.info(Sender.TAG, "Not saving data due to max size limit being met. Directory size in bytes is: " + dirSize); + this._logInfo("Not saving data due to max size limit being met. Directory size in bytes is: " + dirSize); return; } @@ -397,11 +439,11 @@ class Sender { var fileFullPath = path.join(this._tempDir, fileName); // Mode 600 is w/r for creator and no access for anyone else (only applies on *nix) - Logging.info(Sender.TAG, "saving data before crash to disk at: " + fileFullPath); + this._logInfo("saving data before crash to disk at: " + fileFullPath); fs.writeFileSync(fileFullPath, payload, { mode: 0o600 }); } catch (error) { - Logging.warn(Sender.TAG, "Error while saving data to disk: " + (error && error.message)); + this._logWarn("Error while saving data to disk: " + Util.dumpObj(error)); this._onErrorHelper(error); } } diff --git a/Library/Util.ts b/Library/Util.ts index 096f942dd..c598846de 100644 --- a/Library/Util.ts +++ b/Library/Util.ts @@ -404,15 +404,22 @@ class Util { * Returns string representation of an object suitable for diagnostics logging. */ public static dumpObj(object: any): string { - const objectTypeDump: string = Object["prototype"].toString.call(object); - let propertyValueDump: string = ""; - if (objectTypeDump === "[object Error]") { - propertyValueDump = "{ stack: '" + object.stack + "', message: '" + object.message + "', name: '" + object.name + "'"; - } else { - propertyValueDump = JSON.stringify(object); - } + if (object) { + try { + const objectTypeDump: string = Object["prototype"].toString.call(object); + let propertyValueDump: string = ""; + if (objectTypeDump === "[object Error]") { + propertyValueDump = "{ stack: '" + object.stack + "', message: '" + object.message + "', name: '" + object.name + "'"; + } else { + propertyValueDump = this.stringify(object); + } - return objectTypeDump + propertyValueDump; + return objectTypeDump + propertyValueDump; + } + catch (ex) { + return object.toString(); + } + } } public static stringify(payload: any) { diff --git a/Tests/Library/Sender.tests.ts b/Tests/Library/Sender.tests.ts index afca14824..9ab8f459e 100644 --- a/Tests/Library/Sender.tests.ts +++ b/Tests/Library/Sender.tests.ts @@ -428,6 +428,83 @@ describe("Library/Sender", () => { }); }); + it("[Statsbeat Sender] should not turn Statsbeat off succesfully reaching ingestion endpoint at least once", (done) => { + var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); + let shutdownCalled = false; + let shutdown = () => { + shutdownCalled = true; + }; + nockScope = interceptor.reply(200, breezeResponse); + let testSender = new Sender(config, null, null, null, null, true, shutdown); + assert.equal(testSender["_statsbeatHasReachedIngestionAtLeastOnce"], false); + testSender.setDiskRetryMode(false); + testSender.send([testEnvelope], (responseText) => { + assert.equal(testSender["_statsbeatHasReachedIngestionAtLeastOnce"], true); + nockScope = interceptor.reply(503, null); + testSender.send([testEnvelope], (responseText) => { + assert.equal(shutdownCalled, false); + testSender.send([testEnvelope], (responseText) => { + assert.equal(shutdownCalled, false); + testSender.send([testEnvelope], (responseText) => { + assert.equal(shutdownCalled, false); + done(); + }); + }); + }); + }); + }); + + it("[Statsbeat Sender] should turn Statsbeat off if there are 3 failures after initialization", (done) => { + var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); + let shutdownCalled = false; + let shutdown = () => { + shutdownCalled = true; + }; + let testSender = new Sender(config, null, null, null, null, true, shutdown); + testSender.setDiskRetryMode(false); + nockScope = interceptor.reply(503, null); + + testSender.send([testEnvelope], (responseText) => { + assert.equal(shutdownCalled, false); + assert.equal(testSender["_failedToIngestCounter"], 1); + testSender.send([testEnvelope], (responseText) => { + assert.equal(shutdownCalled, false); + assert.equal(testSender["_failedToIngestCounter"], 2); + testSender.send([testEnvelope], (responseText) => { + assert.equal(testSender["_failedToIngestCounter"], 3); + assert.equal(shutdownCalled, true); + done(); + }); + }); + }); + }); + + it("[Statsbeat Sender] should turn off warn logging", (done) => { + var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); + let testSender = new Sender(config, null, null, null, null, true, () => { }); + testSender.setDiskRetryMode(true); + let warntub = sandbox.stub(Logging, "warn"); + nockScope = interceptor.replyWithError("Test Error"); + testSender.send([testEnvelope], (responseText) => { + assert.ok(warntub.notCalled); + assert.equal(testSender["_failedToIngestCounter"], 1); + done(); + }); + }); + + it("[Statsbeat Sender] should turn off info logging", (done) => { + var config = new Config("InstrumentationKey=1aa11111-bbbb-1ccc-8ddd-eeeeffff3333"); + let testSender = new Sender(config, null, null, null, null, true, () => { }); + testSender.setDiskRetryMode(false); + let infoStub = sandbox.stub(Logging, "info"); + nockScope = interceptor.replyWithError("Test Error"); + testSender.send([testEnvelope], (responseText) => { + assert.ok(infoStub.notCalled); + assert.equal(testSender["_failedToIngestCounter"], 1); + done(); + }); + }); + it("Exception counts", (done) => { statsbeatSender.setDiskRetryMode(false); var statsbeatSpy = sandbox.spy(statsbeat, "countRequest"); diff --git a/package-lock.json b/package-lock.json index 813fdfdb0..eda9075a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -346,56 +346,56 @@ } }, "node_modules/@opentelemetry/core": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.0.1.tgz", - "integrity": "sha512-90nQ2X6b/8X+xjcLDBYKooAcOsIlwLRYm+1VsxcX5cHl6V4CSVmDpBreQSDH/A21SqROzapk6813008SatmPpQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.2.0.tgz", + "integrity": "sha512-QiKp8fBbT9ZhRTP+ZVVMyqH62tD/ZQa4gWPi+GnpNetvK1SWPO/8DmRpaSXHwAhu5FWUDJrbFgpLsrDd1zGPOw==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.0.1" + "@opentelemetry/semantic-conventions": "1.2.0" }, "engines": { - "node": ">=8.5.0" + "node": ">=8.12.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.1.0" + "@opentelemetry/api": ">=1.0.0 <1.2.0" } }, "node_modules/@opentelemetry/resources": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.0.1.tgz", - "integrity": "sha512-p8DevOaAEepPucUtImR4cZKHOE2L1jgQAtkdZporV+XnxPA/HqCHPEESyUVuo4f5M0NUlL6k5Pba75KwNJlTRg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.2.0.tgz", + "integrity": "sha512-S5ZlZa2JF+1qhiF7eb3tTtDfKmTODO//pvam9vEyZvr+/At45rIQ7cyznRdMWCppZbholwXWXnrKml29IIG9vQ==", "dependencies": { - "@opentelemetry/core": "1.0.1", - "@opentelemetry/semantic-conventions": "1.0.1" + "@opentelemetry/core": "1.2.0", + "@opentelemetry/semantic-conventions": "1.2.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8.12.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.1.0" + "@opentelemetry/api": ">=1.0.0 <1.2.0" } }, "node_modules/@opentelemetry/sdk-trace-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.0.1.tgz", - "integrity": "sha512-JVSAepTpW7dnqfV7XFN0zHj1jXGNd5OcvIGQl76buogqffdgJdgJWQNrOuUJaus56zrOtlzqFH+YtMA9RGEg8w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.2.0.tgz", + "integrity": "sha512-eHrG9c9OhoDhUmMe63Qzgpcvlgxr2L7BFBbbj2DdZu3vGstayytTT6TDv6mz727lXBqR1HXMbqTGVafS07r3bg==", "dependencies": { - "@opentelemetry/core": "1.0.1", - "@opentelemetry/resources": "1.0.1", - "@opentelemetry/semantic-conventions": "1.0.1" + "@opentelemetry/core": "1.2.0", + "@opentelemetry/resources": "1.2.0", + "@opentelemetry/semantic-conventions": "1.2.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=8.12.0" }, "peerDependencies": { - "@opentelemetry/api": ">=1.0.0 <1.1.0" + "@opentelemetry/api": ">=1.0.0 <1.2.0" } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.0.1.tgz", - "integrity": "sha512-7XU1sfQ8uCVcXLxtAHA8r3qaLJ2oq7sKtEwzZhzuEXqYmjW+n+J4yM3kNo0HQo3Xp1eUe47UM6Wy6yuAvIyllg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.2.0.tgz", + "integrity": "sha512-BNKB9fiYVghALJzCuWO3eNYfdTExPVK4ykrtmfNfy0A6UWYhOYjGMXifUmkunDJNL8ju9tBobo8jF0WR9zGy1Q==", "engines": { - "node": ">=8.0.0" + "node": ">=8.12.0" } }, "node_modules/@types/cls-hooked": { @@ -467,14 +467,14 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.20.0.tgz", - "integrity": "sha512-fapGzoxilCn3sBtC6NtXZX6+P/Hef7VDbyfGqTTpzYydwhlkevB+0vE0EnmHPVTVSy68GUncyJ/2PcrFBeCo5Q==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz", + "integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.20.0", - "@typescript-eslint/type-utils": "5.20.0", - "@typescript-eslint/utils": "5.20.0", + "@typescript-eslint/scope-manager": "5.21.0", + "@typescript-eslint/type-utils": "5.21.0", + "@typescript-eslint/utils": "5.21.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -500,14 +500,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.20.0.tgz", - "integrity": "sha512-UWKibrCZQCYvobmu3/N8TWbEeo/EPQbS41Ux1F9XqPzGuV7pfg6n50ZrFo6hryynD8qOTTfLHtHjjdQtxJ0h/w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz", + "integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.20.0", - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/typescript-estree": "5.20.0", + "@typescript-eslint/scope-manager": "5.21.0", + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/typescript-estree": "5.21.0", "debug": "^4.3.2" }, "engines": { @@ -527,13 +527,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.20.0.tgz", - "integrity": "sha512-h9KtuPZ4D/JuX7rpp1iKg3zOH0WNEa+ZIXwpW/KWmEFDxlA/HSfCMhiyF1HS/drTICjIbpA6OqkAhrP/zkCStg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz", + "integrity": "sha512-XTX0g0IhvzcH/e3393SvjRCfYQxgxtYzL3UREteUneo72EFlt7UNoiYnikUtmGVobTbhUDByhJ4xRBNe+34kOQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/visitor-keys": "5.20.0" + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/visitor-keys": "5.21.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -544,12 +544,12 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.20.0.tgz", - "integrity": "sha512-WxNrCwYB3N/m8ceyoGCgbLmuZwupvzN0rE8NBuwnl7APgjv24ZJIjkNzoFBXPRCGzLNkoU/WfanW0exvp/+3Iw==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz", + "integrity": "sha512-MxmLZj0tkGlkcZCSE17ORaHl8Th3JQwBzyXL/uvC6sNmu128LsgjTX0NIzy+wdH2J7Pd02GN8FaoudJntFvSOw==", "dev": true, "dependencies": { - "@typescript-eslint/utils": "5.20.0", + "@typescript-eslint/utils": "5.21.0", "debug": "^4.3.2", "tsutils": "^3.21.0" }, @@ -570,9 +570,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.20.0.tgz", - "integrity": "sha512-+d8wprF9GyvPwtoB4CxBAR/s0rpP25XKgnOvMf/gMXYDvlUC3rPFHupdTQ/ow9vn7UDe5rX02ovGYQbv/IUCbg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.21.0.tgz", + "integrity": "sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -583,13 +583,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.20.0.tgz", - "integrity": "sha512-36xLjP/+bXusLMrT9fMMYy1KJAGgHhlER2TqpUVDYUQg4w0q/NW/sg4UGAgVwAqb8V4zYg43KMUpM8vV2lve6w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz", + "integrity": "sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/visitor-keys": "5.20.0", + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/visitor-keys": "5.21.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -610,15 +610,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.20.0.tgz", - "integrity": "sha512-lHONGJL1LIO12Ujyx8L8xKbwWSkoUKFSO+0wDAqGXiudWB2EO7WEUT+YZLtVbmOmSllAjLb9tpoIPwpRe5Tn6w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz", + "integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.20.0", - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/typescript-estree": "5.20.0", + "@typescript-eslint/scope-manager": "5.21.0", + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/typescript-estree": "5.21.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -634,12 +634,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.20.0.tgz", - "integrity": "sha512-1flRpNF+0CAQkMNlTJ6L/Z5jiODG/e5+7mk6XwtPOUS3UrTz3UOiAg9jG2VtKsWI6rZQfy4C6a232QNRZTRGlg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz", + "integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.20.0", + "@typescript-eslint/types": "5.21.0", "eslint-visitor-keys": "^3.0.0" }, "engines": { @@ -4101,9 +4101,9 @@ } }, "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -4172,14 +4172,14 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" }, "funding": { @@ -4889,36 +4889,36 @@ "integrity": "sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog==" }, "@opentelemetry/core": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.0.1.tgz", - "integrity": "sha512-90nQ2X6b/8X+xjcLDBYKooAcOsIlwLRYm+1VsxcX5cHl6V4CSVmDpBreQSDH/A21SqROzapk6813008SatmPpQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.2.0.tgz", + "integrity": "sha512-QiKp8fBbT9ZhRTP+ZVVMyqH62tD/ZQa4gWPi+GnpNetvK1SWPO/8DmRpaSXHwAhu5FWUDJrbFgpLsrDd1zGPOw==", "requires": { - "@opentelemetry/semantic-conventions": "1.0.1" + "@opentelemetry/semantic-conventions": "1.2.0" } }, "@opentelemetry/resources": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.0.1.tgz", - "integrity": "sha512-p8DevOaAEepPucUtImR4cZKHOE2L1jgQAtkdZporV+XnxPA/HqCHPEESyUVuo4f5M0NUlL6k5Pba75KwNJlTRg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.2.0.tgz", + "integrity": "sha512-S5ZlZa2JF+1qhiF7eb3tTtDfKmTODO//pvam9vEyZvr+/At45rIQ7cyznRdMWCppZbholwXWXnrKml29IIG9vQ==", "requires": { - "@opentelemetry/core": "1.0.1", - "@opentelemetry/semantic-conventions": "1.0.1" + "@opentelemetry/core": "1.2.0", + "@opentelemetry/semantic-conventions": "1.2.0" } }, "@opentelemetry/sdk-trace-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.0.1.tgz", - "integrity": "sha512-JVSAepTpW7dnqfV7XFN0zHj1jXGNd5OcvIGQl76buogqffdgJdgJWQNrOuUJaus56zrOtlzqFH+YtMA9RGEg8w==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.2.0.tgz", + "integrity": "sha512-eHrG9c9OhoDhUmMe63Qzgpcvlgxr2L7BFBbbj2DdZu3vGstayytTT6TDv6mz727lXBqR1HXMbqTGVafS07r3bg==", "requires": { - "@opentelemetry/core": "1.0.1", - "@opentelemetry/resources": "1.0.1", - "@opentelemetry/semantic-conventions": "1.0.1" + "@opentelemetry/core": "1.2.0", + "@opentelemetry/resources": "1.2.0", + "@opentelemetry/semantic-conventions": "1.2.0" } }, "@opentelemetry/semantic-conventions": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.0.1.tgz", - "integrity": "sha512-7XU1sfQ8uCVcXLxtAHA8r3qaLJ2oq7sKtEwzZhzuEXqYmjW+n+J4yM3kNo0HQo3Xp1eUe47UM6Wy6yuAvIyllg==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.2.0.tgz", + "integrity": "sha512-BNKB9fiYVghALJzCuWO3eNYfdTExPVK4ykrtmfNfy0A6UWYhOYjGMXifUmkunDJNL8ju9tBobo8jF0WR9zGy1Q==" }, "@types/cls-hooked": { "version": "4.3.3", @@ -4988,14 +4988,14 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.20.0.tgz", - "integrity": "sha512-fapGzoxilCn3sBtC6NtXZX6+P/Hef7VDbyfGqTTpzYydwhlkevB+0vE0EnmHPVTVSy68GUncyJ/2PcrFBeCo5Q==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.21.0.tgz", + "integrity": "sha512-fTU85q8v5ZLpoZEyn/u1S2qrFOhi33Edo2CZ0+q1gDaWWm0JuPh3bgOyU8lM0edIEYgKLDkPFiZX2MOupgjlyg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.20.0", - "@typescript-eslint/type-utils": "5.20.0", - "@typescript-eslint/utils": "5.20.0", + "@typescript-eslint/scope-manager": "5.21.0", + "@typescript-eslint/type-utils": "5.21.0", + "@typescript-eslint/utils": "5.21.0", "debug": "^4.3.2", "functional-red-black-tree": "^1.0.1", "ignore": "^5.1.8", @@ -5005,52 +5005,52 @@ } }, "@typescript-eslint/parser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.20.0.tgz", - "integrity": "sha512-UWKibrCZQCYvobmu3/N8TWbEeo/EPQbS41Ux1F9XqPzGuV7pfg6n50ZrFo6hryynD8qOTTfLHtHjjdQtxJ0h/w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.21.0.tgz", + "integrity": "sha512-8RUwTO77hstXUr3pZoWZbRQUxXcSXafZ8/5gpnQCfXvgmP9gpNlRGlWzvfbEQ14TLjmtU8eGnONkff8U2ui2Eg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.20.0", - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/typescript-estree": "5.20.0", + "@typescript-eslint/scope-manager": "5.21.0", + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/typescript-estree": "5.21.0", "debug": "^4.3.2" } }, "@typescript-eslint/scope-manager": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.20.0.tgz", - "integrity": "sha512-h9KtuPZ4D/JuX7rpp1iKg3zOH0WNEa+ZIXwpW/KWmEFDxlA/HSfCMhiyF1HS/drTICjIbpA6OqkAhrP/zkCStg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.21.0.tgz", + "integrity": "sha512-XTX0g0IhvzcH/e3393SvjRCfYQxgxtYzL3UREteUneo72EFlt7UNoiYnikUtmGVobTbhUDByhJ4xRBNe+34kOQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/visitor-keys": "5.20.0" + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/visitor-keys": "5.21.0" } }, "@typescript-eslint/type-utils": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.20.0.tgz", - "integrity": "sha512-WxNrCwYB3N/m8ceyoGCgbLmuZwupvzN0rE8NBuwnl7APgjv24ZJIjkNzoFBXPRCGzLNkoU/WfanW0exvp/+3Iw==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.21.0.tgz", + "integrity": "sha512-MxmLZj0tkGlkcZCSE17ORaHl8Th3JQwBzyXL/uvC6sNmu128LsgjTX0NIzy+wdH2J7Pd02GN8FaoudJntFvSOw==", "dev": true, "requires": { - "@typescript-eslint/utils": "5.20.0", + "@typescript-eslint/utils": "5.21.0", "debug": "^4.3.2", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.20.0.tgz", - "integrity": "sha512-+d8wprF9GyvPwtoB4CxBAR/s0rpP25XKgnOvMf/gMXYDvlUC3rPFHupdTQ/ow9vn7UDe5rX02ovGYQbv/IUCbg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.21.0.tgz", + "integrity": "sha512-XnOOo5Wc2cBlq8Lh5WNvAgHzpjnEzxn4CJBwGkcau7b/tZ556qrWXQz4DJyChYg8JZAD06kczrdgFPpEQZfDsA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.20.0.tgz", - "integrity": "sha512-36xLjP/+bXusLMrT9fMMYy1KJAGgHhlER2TqpUVDYUQg4w0q/NW/sg4UGAgVwAqb8V4zYg43KMUpM8vV2lve6w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.21.0.tgz", + "integrity": "sha512-Y8Y2T2FNvm08qlcoSMoNchh9y2Uj3QmjtwNMdRQkcFG7Muz//wfJBGBxh8R7HAGQFpgYpdHqUpEoPQk+q9Kjfg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/visitor-keys": "5.20.0", + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/visitor-keys": "5.21.0", "debug": "^4.3.2", "globby": "^11.0.4", "is-glob": "^4.0.3", @@ -5059,26 +5059,26 @@ } }, "@typescript-eslint/utils": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.20.0.tgz", - "integrity": "sha512-lHONGJL1LIO12Ujyx8L8xKbwWSkoUKFSO+0wDAqGXiudWB2EO7WEUT+YZLtVbmOmSllAjLb9tpoIPwpRe5Tn6w==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.21.0.tgz", + "integrity": "sha512-q/emogbND9wry7zxy7VYri+7ydawo2HDZhRZ5k6yggIvXa7PvBbAAZ4PFH/oZLem72ezC4Pr63rJvDK/sTlL8Q==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.20.0", - "@typescript-eslint/types": "5.20.0", - "@typescript-eslint/typescript-estree": "5.20.0", + "@typescript-eslint/scope-manager": "5.21.0", + "@typescript-eslint/types": "5.21.0", + "@typescript-eslint/typescript-estree": "5.21.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.20.0.tgz", - "integrity": "sha512-1flRpNF+0CAQkMNlTJ6L/Z5jiODG/e5+7mk6XwtPOUS3UrTz3UOiAg9jG2VtKsWI6rZQfy4C6a232QNRZTRGlg==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.21.0.tgz", + "integrity": "sha512-SX8jNN+iHqAF0riZQMkm7e8+POXa/fXw5cxL+gjpyP+FI+JVNhii53EmQgDAfDcBpFekYSlO0fGytMQwRiMQCA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.20.0", + "@typescript-eslint/types": "5.21.0", "eslint-visitor-keys": "^3.0.0" } }, @@ -7629,9 +7629,9 @@ } }, "tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, "tsutils": { "version": "3.21.0", @@ -7677,14 +7677,14 @@ "dev": true }, "unbox-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", - "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has-bigints": "^1.0.1", - "has-symbols": "^1.0.2", + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } },