@azure/monitor-opentelemetry-exporter 1.0.0-beta.10 → 1.0.0-beta.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -6
- package/dist/index.js +286 -188
- package/dist-esm/src/export/base.js +22 -16
- package/dist-esm/src/export/base.js.map +1 -1
- package/dist-esm/src/export/statsbeat/longIntervalStatsbeatMetrics.js +118 -0
- package/dist-esm/src/export/statsbeat/longIntervalStatsbeatMetrics.js.map +1 -0
- package/dist-esm/src/export/statsbeat/networkStatsbeatMetrics.js +249 -0
- package/dist-esm/src/export/statsbeat/networkStatsbeatMetrics.js.map +1 -0
- package/dist-esm/src/export/{statsbeat.js → statsbeat/statsbeatExporter.js} +4 -5
- package/dist-esm/src/export/statsbeat/statsbeatExporter.js.map +1 -0
- package/dist-esm/src/export/statsbeat/statsbeatMetrics.js +26 -240
- package/dist-esm/src/export/statsbeat/statsbeatMetrics.js.map +1 -1
- package/dist-esm/src/export/statsbeat/types.js +9 -0
- package/dist-esm/src/export/statsbeat/types.js.map +1 -1
- package/dist-esm/src/generated/applicationInsightsClient.js +1 -1
- package/dist-esm/src/generated/applicationInsightsClient.js.map +1 -1
- package/dist-esm/src/index.js +1 -1
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/platform/nodejs/context/context.js +9 -2
- package/dist-esm/src/platform/nodejs/context/context.js.map +1 -1
- package/dist-esm/src/utils/constants/applicationinsights.js +1 -30
- package/dist-esm/src/utils/constants/applicationinsights.js.map +1 -1
- package/dist-esm/src/utils/metricUtils.js +2 -42
- package/dist-esm/src/utils/metricUtils.js.map +1 -1
- package/dist-esm/src/utils/spanUtils.js +35 -31
- package/dist-esm/src/utils/spanUtils.js.map +1 -1
- package/package.json +13 -14
- package/types/monitor-opentelemetry-exporter.d.ts +28 -2
- package/dist-esm/src/export/statsbeat.js.map +0 -1
|
@@ -6,8 +6,9 @@ import { ConnectionStringParser } from "../utils/connectionStringParser";
|
|
|
6
6
|
import { HttpSender, FileSystemPersist } from "../platform";
|
|
7
7
|
import { isRetriable } from "../utils/breezeUtils";
|
|
8
8
|
import { DEFAULT_BREEZE_ENDPOINT, ENV_CONNECTION_STRING } from "../Declarations/Constants";
|
|
9
|
-
import {
|
|
9
|
+
import { NetworkStatsbeatMetrics } from "./statsbeat/networkStatsbeatMetrics";
|
|
10
10
|
import { MAX_STATSBEAT_FAILURES } from "./statsbeat/types";
|
|
11
|
+
import { getInstance } from "./statsbeat/longIntervalStatsbeatMetrics";
|
|
11
12
|
const DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60000;
|
|
12
13
|
/**
|
|
13
14
|
* Azure Monitor OpenTelemetry Trace Exporter.
|
|
@@ -48,7 +49,11 @@ export class AzureMonitorBaseExporter {
|
|
|
48
49
|
this._persister = new FileSystemPersist(this._instrumentationKey, this._options);
|
|
49
50
|
if (!this._isStatsbeatExporter) {
|
|
50
51
|
// Initialize statsbeatMetrics
|
|
51
|
-
this.
|
|
52
|
+
this._networkStatsbeatMetrics = new NetworkStatsbeatMetrics({
|
|
53
|
+
instrumentationKey: this._instrumentationKey,
|
|
54
|
+
endpointUrl: this._endpointUrl,
|
|
55
|
+
});
|
|
56
|
+
this._longIntervalStatsbeatMetrics = getInstance({
|
|
52
57
|
instrumentationKey: this._instrumentationKey,
|
|
53
58
|
endpointUrl: this._endpointUrl,
|
|
54
59
|
});
|
|
@@ -104,13 +109,13 @@ export class AzureMonitorBaseExporter {
|
|
|
104
109
|
this._retryTimer.unref();
|
|
105
110
|
}
|
|
106
111
|
// If we are not exportings statsbeat and statsbeat is not disabled -- count success
|
|
107
|
-
(_a = this.
|
|
112
|
+
(_a = this._networkStatsbeatMetrics) === null || _a === void 0 ? void 0 : _a.countSuccess(duration);
|
|
108
113
|
return { code: ExportResultCode.SUCCESS };
|
|
109
114
|
}
|
|
110
115
|
else if (statusCode && isRetriable(statusCode)) {
|
|
111
116
|
// Failed -- persist failed data
|
|
112
117
|
if (statusCode === 429 || statusCode === 439) {
|
|
113
|
-
(_b = this.
|
|
118
|
+
(_b = this._networkStatsbeatMetrics) === null || _b === void 0 ? void 0 : _b.countThrottle(statusCode);
|
|
114
119
|
}
|
|
115
120
|
if (result) {
|
|
116
121
|
diag.info(result);
|
|
@@ -124,27 +129,27 @@ export class AzureMonitorBaseExporter {
|
|
|
124
129
|
});
|
|
125
130
|
}
|
|
126
131
|
if (filteredEnvelopes.length > 0) {
|
|
127
|
-
(_c = this.
|
|
132
|
+
(_c = this._networkStatsbeatMetrics) === null || _c === void 0 ? void 0 : _c.countRetry(statusCode);
|
|
128
133
|
// calls resultCallback(ExportResult) based on result of persister.push
|
|
129
134
|
return await this._persist(filteredEnvelopes);
|
|
130
135
|
}
|
|
131
136
|
// Failed -- not retriable
|
|
132
|
-
(_d = this.
|
|
137
|
+
(_d = this._networkStatsbeatMetrics) === null || _d === void 0 ? void 0 : _d.countFailure(duration, statusCode);
|
|
133
138
|
return {
|
|
134
139
|
code: ExportResultCode.FAILED,
|
|
135
140
|
};
|
|
136
141
|
}
|
|
137
142
|
else {
|
|
138
143
|
// calls resultCallback(ExportResult) based on result of persister.push
|
|
139
|
-
(_e = this.
|
|
144
|
+
(_e = this._networkStatsbeatMetrics) === null || _e === void 0 ? void 0 : _e.countRetry(statusCode);
|
|
140
145
|
return await this._persist(envelopes);
|
|
141
146
|
}
|
|
142
147
|
}
|
|
143
148
|
else {
|
|
144
149
|
// Failed -- not retriable
|
|
145
|
-
if (this.
|
|
150
|
+
if (this._networkStatsbeatMetrics) {
|
|
146
151
|
if (statusCode) {
|
|
147
|
-
this.
|
|
152
|
+
this._networkStatsbeatMetrics.countFailure(duration, statusCode);
|
|
148
153
|
}
|
|
149
154
|
}
|
|
150
155
|
else {
|
|
@@ -176,34 +181,35 @@ export class AzureMonitorBaseExporter {
|
|
|
176
181
|
}
|
|
177
182
|
else {
|
|
178
183
|
let redirectError = new Error("Circular redirect");
|
|
179
|
-
(_f = this.
|
|
184
|
+
(_f = this._networkStatsbeatMetrics) === null || _f === void 0 ? void 0 : _f.countException(redirectError);
|
|
180
185
|
return { code: ExportResultCode.FAILED, error: redirectError };
|
|
181
186
|
}
|
|
182
187
|
}
|
|
183
188
|
else if (restError.statusCode && isRetriable(restError.statusCode)) {
|
|
184
|
-
(_g = this.
|
|
189
|
+
(_g = this._networkStatsbeatMetrics) === null || _g === void 0 ? void 0 : _g.countRetry(restError.statusCode);
|
|
185
190
|
return await this._persist(envelopes);
|
|
186
191
|
}
|
|
187
192
|
if (this._isNetworkError(restError)) {
|
|
188
193
|
if (restError.statusCode) {
|
|
189
|
-
(_h = this.
|
|
194
|
+
(_h = this._networkStatsbeatMetrics) === null || _h === void 0 ? void 0 : _h.countRetry(restError.statusCode);
|
|
190
195
|
}
|
|
191
196
|
diag.error("Retrying due to transient client side error. Error message:", restError.message);
|
|
192
197
|
return await this._persist(envelopes);
|
|
193
198
|
}
|
|
194
|
-
(_j = this.
|
|
199
|
+
(_j = this._networkStatsbeatMetrics) === null || _j === void 0 ? void 0 : _j.countException(restError);
|
|
195
200
|
diag.error("Envelopes could not be exported and are not retriable. Error message:", restError.message);
|
|
196
201
|
return { code: ExportResultCode.FAILED, error: restError };
|
|
197
202
|
}
|
|
198
203
|
}
|
|
199
204
|
// Disable collection of statsbeat metrics after max failures
|
|
200
205
|
_incrementStatsbeatFailure() {
|
|
201
|
-
var _a;
|
|
206
|
+
var _a, _b;
|
|
202
207
|
this._statsbeatFailureCount++;
|
|
203
208
|
if (this._statsbeatFailureCount > MAX_STATSBEAT_FAILURES) {
|
|
204
209
|
this._isStatsbeatExporter = false;
|
|
205
|
-
(_a = this.
|
|
206
|
-
this.
|
|
210
|
+
(_a = this._networkStatsbeatMetrics) === null || _a === void 0 ? void 0 : _a.shutdown();
|
|
211
|
+
(_b = this._longIntervalStatsbeatMetrics) === null || _b === void 0 ? void 0 : _b.shutdown();
|
|
212
|
+
this._networkStatsbeatMetrics = undefined;
|
|
207
213
|
this._statsbeatFailureCount = 0;
|
|
208
214
|
}
|
|
209
215
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/export/base.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { diag } from \"@opentelemetry/api\";\nimport { ExportResult, ExportResultCode } from \"@opentelemetry/core\";\nimport { RestError } from \"@azure/core-rest-pipeline\";\nimport { ConnectionStringParser } from \"../utils/connectionStringParser\";\nimport { HttpSender, FileSystemPersist } from \"../platform\";\nimport { AzureMonitorExporterOptions } from \"../config\";\nimport { PersistentStorage, Sender } from \"../types\";\nimport { isRetriable, BreezeResponse } from \"../utils/breezeUtils\";\nimport { DEFAULT_BREEZE_ENDPOINT, ENV_CONNECTION_STRING } from \"../Declarations/Constants\";\nimport { TelemetryItem as Envelope } from \"../generated\";\nimport { StatsbeatMetrics } from \"./statsbeat/statsbeatMetrics\";\nimport { MAX_STATSBEAT_FAILURES } from \"./statsbeat/types\";\n\nconst DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60_000;\n/**\n * Azure Monitor OpenTelemetry Trace Exporter.\n */\nexport abstract class AzureMonitorBaseExporter {\n /**\n * Instrumentation key to be used for exported envelopes\n */\n protected _instrumentationKey: string = \"\";\n private _endpointUrl: string = \"\";\n private readonly _persister: PersistentStorage;\n private readonly _sender: Sender;\n private _numConsecutiveRedirects: number;\n private _retryTimer: NodeJS.Timer | null;\n private _statsbeatMetrics: StatsbeatMetrics | undefined;\n private _isStatsbeatExporter: boolean;\n private _statsbeatFailureCount: number = 0;\n private _batchSendRetryIntervalMs: number = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;\n /**\n * Exporter internal configuration\n */\n private readonly _options: AzureMonitorExporterOptions;\n\n /**\n * Initializes a new instance of the AzureMonitorBaseExporter class.\n * @param AzureMonitorExporterOptions - Exporter configuration.\n */\n constructor(options: AzureMonitorExporterOptions = {}, isStatsbeatExporter?: boolean) {\n this._options = options;\n this._numConsecutiveRedirects = 0;\n this._instrumentationKey = \"\";\n this._endpointUrl = DEFAULT_BREEZE_ENDPOINT;\n const connectionString = this._options.connectionString || process.env[ENV_CONNECTION_STRING];\n this._isStatsbeatExporter = isStatsbeatExporter ? isStatsbeatExporter : false;\n\n if (connectionString) {\n const parsedConnectionString = ConnectionStringParser.parse(connectionString);\n this._instrumentationKey =\n parsedConnectionString.instrumentationkey || this._instrumentationKey;\n this._endpointUrl = parsedConnectionString.ingestionendpoint?.trim() || this._endpointUrl;\n }\n\n // Instrumentation key is required\n if (!this._instrumentationKey) {\n const message =\n \"No instrumentation key or connection string was provided to the Azure Monitor Exporter\";\n diag.error(message);\n throw new Error(message);\n }\n this._sender = new HttpSender(this._endpointUrl, this._options);\n this._persister = new FileSystemPersist(this._instrumentationKey, this._options);\n\n if (!this._isStatsbeatExporter) {\n // Initialize statsbeatMetrics\n this._statsbeatMetrics = new StatsbeatMetrics({\n instrumentationKey: this._instrumentationKey,\n endpointUrl: this._endpointUrl,\n });\n }\n this._retryTimer = null;\n diag.debug(\"AzureMonitorExporter was successfully setup\");\n }\n\n /**\n * Persist envelopes to disk\n */\n private async _persist(envelopes: unknown[]): Promise<ExportResult> {\n try {\n const success = await this._persister.push(envelopes);\n return success\n ? { code: ExportResultCode.SUCCESS }\n : {\n code: ExportResultCode.FAILED,\n error: new Error(\"Failed to persist envelope in disk.\"),\n };\n } catch (ex: any) {\n return { code: ExportResultCode.FAILED, error: ex };\n }\n }\n\n /**\n * Shutdown exporter\n */\n protected async _shutdown(): Promise<void> {\n return this._sender.shutdown();\n }\n\n /**\n * Export envelopes\n */\n protected async _exportEnvelopes(envelopes: Envelope[]): Promise<ExportResult> {\n diag.info(`Exporting ${envelopes.length} envelope(s)`);\n\n if (envelopes.length < 1) {\n return { code: ExportResultCode.SUCCESS };\n }\n\n try {\n const startTime = new Date().getTime();\n const { result, statusCode } = await this._sender.send(envelopes);\n const endTime = new Date().getTime();\n const duration = endTime - startTime;\n this._numConsecutiveRedirects = 0;\n\n if (statusCode === 200) {\n // Success -- @todo: start retry timer\n if (!this._retryTimer) {\n this._retryTimer = setTimeout(() => {\n this._retryTimer = null;\n this._sendFirstPersistedFile();\n }, this._batchSendRetryIntervalMs);\n this._retryTimer.unref();\n }\n // If we are not exportings statsbeat and statsbeat is not disabled -- count success\n this._statsbeatMetrics?.countSuccess(duration);\n return { code: ExportResultCode.SUCCESS };\n } else if (statusCode && isRetriable(statusCode)) {\n // Failed -- persist failed data\n if (statusCode === 429 || statusCode === 439) {\n this._statsbeatMetrics?.countThrottle(statusCode);\n }\n if (result) {\n diag.info(result);\n const breezeResponse = JSON.parse(result) as BreezeResponse;\n const filteredEnvelopes: Envelope[] = [];\n if (breezeResponse.errors) {\n breezeResponse.errors.forEach((error) => {\n if (error.statusCode && isRetriable(error.statusCode)) {\n filteredEnvelopes.push(envelopes[error.index]);\n }\n });\n }\n if (filteredEnvelopes.length > 0) {\n this._statsbeatMetrics?.countRetry(statusCode);\n // calls resultCallback(ExportResult) based on result of persister.push\n return await this._persist(filteredEnvelopes);\n }\n // Failed -- not retriable\n this._statsbeatMetrics?.countFailure(duration, statusCode);\n return {\n code: ExportResultCode.FAILED,\n };\n } else {\n // calls resultCallback(ExportResult) based on result of persister.push\n this._statsbeatMetrics?.countRetry(statusCode);\n return await this._persist(envelopes);\n }\n } else {\n // Failed -- not retriable\n if (this._statsbeatMetrics) {\n if (statusCode) {\n this._statsbeatMetrics.countFailure(duration, statusCode);\n }\n } else {\n this._incrementStatsbeatFailure();\n }\n return {\n code: ExportResultCode.FAILED,\n };\n }\n } catch (error: any) {\n const restError = error as RestError;\n if (\n restError.statusCode &&\n (restError.statusCode === 307 || // Temporary redirect\n restError.statusCode === 308)\n ) {\n // Permanent redirect\n this._numConsecutiveRedirects++;\n // To prevent circular redirects\n if (this._numConsecutiveRedirects < 10) {\n if (restError.response && restError.response.headers) {\n const location = restError.response.headers.get(\"location\");\n if (location) {\n // Update sender URL\n this._sender.handlePermanentRedirect(location);\n // Send to redirect endpoint as HTTPs library doesn't handle redirect automatically\n return this._exportEnvelopes(envelopes);\n }\n }\n } else {\n let redirectError = new Error(\"Circular redirect\");\n this._statsbeatMetrics?.countException(redirectError);\n return { code: ExportResultCode.FAILED, error: redirectError };\n }\n } else if (restError.statusCode && isRetriable(restError.statusCode)) {\n this._statsbeatMetrics?.countRetry(restError.statusCode);\n return await this._persist(envelopes);\n }\n if (this._isNetworkError(restError)) {\n if (restError.statusCode) {\n this._statsbeatMetrics?.countRetry(restError.statusCode);\n }\n diag.error(\n \"Retrying due to transient client side error. Error message:\",\n restError.message\n );\n return await this._persist(envelopes);\n }\n this._statsbeatMetrics?.countException(restError);\n diag.error(\n \"Envelopes could not be exported and are not retriable. Error message:\",\n restError.message\n );\n return { code: ExportResultCode.FAILED, error: restError };\n }\n }\n\n // Disable collection of statsbeat metrics after max failures\n private _incrementStatsbeatFailure() {\n this._statsbeatFailureCount++;\n if (this._statsbeatFailureCount > MAX_STATSBEAT_FAILURES) {\n this._isStatsbeatExporter = false;\n this._statsbeatMetrics?.shutdown();\n this._statsbeatMetrics = undefined;\n this._statsbeatFailureCount = 0;\n }\n }\n\n private async _sendFirstPersistedFile(): Promise<void> {\n try {\n const envelopes = (await this._persister.shift()) as Envelope[] | null;\n if (envelopes) {\n await this._sender.send(envelopes);\n }\n } catch (err: any) {\n diag.warn(`Failed to fetch persisted file`, err);\n }\n }\n\n private _isNetworkError(error: RestError): boolean {\n if (error && error.code && error.code === \"REQUEST_SEND_ERROR\") {\n return true;\n }\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/export/base.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { diag } from \"@opentelemetry/api\";\nimport { ExportResult, ExportResultCode } from \"@opentelemetry/core\";\nimport { RestError } from \"@azure/core-rest-pipeline\";\nimport { ConnectionStringParser } from \"../utils/connectionStringParser\";\nimport { HttpSender, FileSystemPersist } from \"../platform\";\nimport { AzureMonitorExporterOptions } from \"../config\";\nimport { PersistentStorage, Sender } from \"../types\";\nimport { isRetriable, BreezeResponse } from \"../utils/breezeUtils\";\nimport { DEFAULT_BREEZE_ENDPOINT, ENV_CONNECTION_STRING } from \"../Declarations/Constants\";\nimport { TelemetryItem as Envelope } from \"../generated\";\nimport { NetworkStatsbeatMetrics } from \"./statsbeat/networkStatsbeatMetrics\";\nimport { MAX_STATSBEAT_FAILURES } from \"./statsbeat/types\";\nimport { getInstance } from \"./statsbeat/longIntervalStatsbeatMetrics\";\n\nconst DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60_000;\n/**\n * Azure Monitor OpenTelemetry Trace Exporter.\n */\nexport abstract class AzureMonitorBaseExporter {\n /**\n * Instrumentation key to be used for exported envelopes\n */\n protected _instrumentationKey: string = \"\";\n private _endpointUrl: string = \"\";\n private readonly _persister: PersistentStorage;\n private readonly _sender: Sender;\n private _numConsecutiveRedirects: number;\n private _retryTimer: NodeJS.Timer | null;\n private _networkStatsbeatMetrics: NetworkStatsbeatMetrics | undefined;\n private _longIntervalStatsbeatMetrics;\n private _isStatsbeatExporter: boolean;\n private _statsbeatFailureCount: number = 0;\n private _batchSendRetryIntervalMs: number = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;\n /**\n * Exporter internal configuration\n */\n private readonly _options: AzureMonitorExporterOptions;\n\n /**\n * Initializes a new instance of the AzureMonitorBaseExporter class.\n * @param AzureMonitorExporterOptions - Exporter configuration.\n */\n constructor(options: AzureMonitorExporterOptions = {}, isStatsbeatExporter?: boolean) {\n this._options = options;\n this._numConsecutiveRedirects = 0;\n this._instrumentationKey = \"\";\n this._endpointUrl = DEFAULT_BREEZE_ENDPOINT;\n const connectionString = this._options.connectionString || process.env[ENV_CONNECTION_STRING];\n this._isStatsbeatExporter = isStatsbeatExporter ? isStatsbeatExporter : false;\n\n if (connectionString) {\n const parsedConnectionString = ConnectionStringParser.parse(connectionString);\n this._instrumentationKey =\n parsedConnectionString.instrumentationkey || this._instrumentationKey;\n this._endpointUrl = parsedConnectionString.ingestionendpoint?.trim() || this._endpointUrl;\n }\n\n // Instrumentation key is required\n if (!this._instrumentationKey) {\n const message =\n \"No instrumentation key or connection string was provided to the Azure Monitor Exporter\";\n diag.error(message);\n throw new Error(message);\n }\n this._sender = new HttpSender(this._endpointUrl, this._options);\n this._persister = new FileSystemPersist(this._instrumentationKey, this._options);\n\n if (!this._isStatsbeatExporter) {\n // Initialize statsbeatMetrics\n this._networkStatsbeatMetrics = new NetworkStatsbeatMetrics({\n instrumentationKey: this._instrumentationKey,\n endpointUrl: this._endpointUrl,\n });\n this._longIntervalStatsbeatMetrics = getInstance({\n instrumentationKey: this._instrumentationKey,\n endpointUrl: this._endpointUrl,\n });\n }\n this._retryTimer = null;\n diag.debug(\"AzureMonitorExporter was successfully setup\");\n }\n\n /**\n * Persist envelopes to disk\n */\n private async _persist(envelopes: unknown[]): Promise<ExportResult> {\n try {\n const success = await this._persister.push(envelopes);\n return success\n ? { code: ExportResultCode.SUCCESS }\n : {\n code: ExportResultCode.FAILED,\n error: new Error(\"Failed to persist envelope in disk.\"),\n };\n } catch (ex: any) {\n return { code: ExportResultCode.FAILED, error: ex };\n }\n }\n\n /**\n * Shutdown exporter\n */\n protected async _shutdown(): Promise<void> {\n return this._sender.shutdown();\n }\n\n /**\n * Export envelopes\n */\n protected async _exportEnvelopes(envelopes: Envelope[]): Promise<ExportResult> {\n diag.info(`Exporting ${envelopes.length} envelope(s)`);\n\n if (envelopes.length < 1) {\n return { code: ExportResultCode.SUCCESS };\n }\n\n try {\n const startTime = new Date().getTime();\n const { result, statusCode } = await this._sender.send(envelopes);\n const endTime = new Date().getTime();\n const duration = endTime - startTime;\n this._numConsecutiveRedirects = 0;\n\n if (statusCode === 200) {\n // Success -- @todo: start retry timer\n if (!this._retryTimer) {\n this._retryTimer = setTimeout(() => {\n this._retryTimer = null;\n this._sendFirstPersistedFile();\n }, this._batchSendRetryIntervalMs);\n this._retryTimer.unref();\n }\n // If we are not exportings statsbeat and statsbeat is not disabled -- count success\n this._networkStatsbeatMetrics?.countSuccess(duration);\n return { code: ExportResultCode.SUCCESS };\n } else if (statusCode && isRetriable(statusCode)) {\n // Failed -- persist failed data\n if (statusCode === 429 || statusCode === 439) {\n this._networkStatsbeatMetrics?.countThrottle(statusCode);\n }\n if (result) {\n diag.info(result);\n const breezeResponse = JSON.parse(result) as BreezeResponse;\n const filteredEnvelopes: Envelope[] = [];\n if (breezeResponse.errors) {\n breezeResponse.errors.forEach((error) => {\n if (error.statusCode && isRetriable(error.statusCode)) {\n filteredEnvelopes.push(envelopes[error.index]);\n }\n });\n }\n if (filteredEnvelopes.length > 0) {\n this._networkStatsbeatMetrics?.countRetry(statusCode);\n // calls resultCallback(ExportResult) based on result of persister.push\n return await this._persist(filteredEnvelopes);\n }\n // Failed -- not retriable\n this._networkStatsbeatMetrics?.countFailure(duration, statusCode);\n return {\n code: ExportResultCode.FAILED,\n };\n } else {\n // calls resultCallback(ExportResult) based on result of persister.push\n this._networkStatsbeatMetrics?.countRetry(statusCode);\n return await this._persist(envelopes);\n }\n } else {\n // Failed -- not retriable\n if (this._networkStatsbeatMetrics) {\n if (statusCode) {\n this._networkStatsbeatMetrics.countFailure(duration, statusCode);\n }\n } else {\n this._incrementStatsbeatFailure();\n }\n return {\n code: ExportResultCode.FAILED,\n };\n }\n } catch (error: any) {\n const restError = error as RestError;\n if (\n restError.statusCode &&\n (restError.statusCode === 307 || // Temporary redirect\n restError.statusCode === 308)\n ) {\n // Permanent redirect\n this._numConsecutiveRedirects++;\n // To prevent circular redirects\n if (this._numConsecutiveRedirects < 10) {\n if (restError.response && restError.response.headers) {\n const location = restError.response.headers.get(\"location\");\n if (location) {\n // Update sender URL\n this._sender.handlePermanentRedirect(location);\n // Send to redirect endpoint as HTTPs library doesn't handle redirect automatically\n return this._exportEnvelopes(envelopes);\n }\n }\n } else {\n let redirectError = new Error(\"Circular redirect\");\n this._networkStatsbeatMetrics?.countException(redirectError);\n return { code: ExportResultCode.FAILED, error: redirectError };\n }\n } else if (restError.statusCode && isRetriable(restError.statusCode)) {\n this._networkStatsbeatMetrics?.countRetry(restError.statusCode);\n return await this._persist(envelopes);\n }\n if (this._isNetworkError(restError)) {\n if (restError.statusCode) {\n this._networkStatsbeatMetrics?.countRetry(restError.statusCode);\n }\n diag.error(\n \"Retrying due to transient client side error. Error message:\",\n restError.message\n );\n return await this._persist(envelopes);\n }\n this._networkStatsbeatMetrics?.countException(restError);\n diag.error(\n \"Envelopes could not be exported and are not retriable. Error message:\",\n restError.message\n );\n return { code: ExportResultCode.FAILED, error: restError };\n }\n }\n\n // Disable collection of statsbeat metrics after max failures\n private _incrementStatsbeatFailure() {\n this._statsbeatFailureCount++;\n if (this._statsbeatFailureCount > MAX_STATSBEAT_FAILURES) {\n this._isStatsbeatExporter = false;\n this._networkStatsbeatMetrics?.shutdown();\n this._longIntervalStatsbeatMetrics?.shutdown();\n this._networkStatsbeatMetrics = undefined;\n this._statsbeatFailureCount = 0;\n }\n }\n\n private async _sendFirstPersistedFile(): Promise<void> {\n try {\n const envelopes = (await this._persister.shift()) as Envelope[] | null;\n if (envelopes) {\n await this._sender.send(envelopes);\n }\n } catch (err: any) {\n diag.warn(`Failed to fetch persisted file`, err);\n }\n }\n\n private _isNetworkError(error: RestError): boolean {\n if (error && error.code && error.code === \"REQUEST_SEND_ERROR\") {\n return true;\n }\n return false;\n }\n}\n"]}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
import { diag, } from "@opentelemetry/api";
|
|
4
|
+
import { ExportResultCode } from "@opentelemetry/core";
|
|
5
|
+
import { MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics";
|
|
6
|
+
import { AzureMonitorStatsbeatExporter } from "../../index";
|
|
7
|
+
import * as ai from "../../utils/constants/applicationinsights";
|
|
8
|
+
import { StatsbeatMetrics } from "./statsbeatMetrics";
|
|
9
|
+
import { StatsbeatCounter, STATSBEAT_LANGUAGE, StatsbeatFeatureType, } from "./types";
|
|
10
|
+
let instance = null;
|
|
11
|
+
/**
|
|
12
|
+
* Long Interval Statsbeat Metrics
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
class LongIntervalStatsbeatMetrics extends StatsbeatMetrics {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
super();
|
|
18
|
+
this._AZURE_MONITOR_STATSBEAT_FEATURES = process.env.AZURE_MONITOR_STATSBEAT_FEATURES;
|
|
19
|
+
this._statsCollectionLongInterval = 86400000; // 1 day
|
|
20
|
+
this._isInitialized = false;
|
|
21
|
+
this._attach = "sdk";
|
|
22
|
+
this._feature = 0;
|
|
23
|
+
this._instrumentation = 0;
|
|
24
|
+
this._connectionString = super._getConnectionString(options.endpointUrl);
|
|
25
|
+
const exporterConfig = {
|
|
26
|
+
connectionString: this._connectionString,
|
|
27
|
+
};
|
|
28
|
+
if (this._AZURE_MONITOR_STATSBEAT_FEATURES) {
|
|
29
|
+
try {
|
|
30
|
+
this._feature = JSON.parse(this._AZURE_MONITOR_STATSBEAT_FEATURES).feature;
|
|
31
|
+
this._instrumentation = JSON.parse(this._AZURE_MONITOR_STATSBEAT_FEATURES).instrumentation;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
diag.error(`LongIntervalStatsbeat: Failed to parse features/instrumentations (error ${error})`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
this._longIntervalStatsbeatMeterProvider = new MeterProvider();
|
|
38
|
+
this._longIntervalAzureExporter = new AzureMonitorStatsbeatExporter(exporterConfig);
|
|
39
|
+
// Export Long Interval Statsbeats every day
|
|
40
|
+
const longIntervalMetricReaderOptions = {
|
|
41
|
+
exporter: this._longIntervalAzureExporter,
|
|
42
|
+
exportIntervalMillis: Number(process.env.LONG_INTERVAL_EXPORT_MILLIS) || this._statsCollectionLongInterval, // 1 day
|
|
43
|
+
};
|
|
44
|
+
this._longIntervalMetricReader = new PeriodicExportingMetricReader(longIntervalMetricReaderOptions);
|
|
45
|
+
this._longIntervalStatsbeatMeterProvider.addMetricReader(this._longIntervalMetricReader);
|
|
46
|
+
this._longIntervalStatsbeatMeter = this._longIntervalStatsbeatMeterProvider.getMeter("Azure Monitor Long Interval Statsbeat");
|
|
47
|
+
// Assign Common Properties
|
|
48
|
+
this._runtimeVersion = process.version;
|
|
49
|
+
this._language = STATSBEAT_LANGUAGE;
|
|
50
|
+
this._version = ai.packageVersion;
|
|
51
|
+
this._cikey = options.instrumentationKey;
|
|
52
|
+
this._featureStatsbeatGauge = this._longIntervalStatsbeatMeter.createObservableGauge(StatsbeatCounter.FEATURE);
|
|
53
|
+
this._attachStatsbeatGauge = this._longIntervalStatsbeatMeter.createObservableGauge(StatsbeatCounter.ATTACH);
|
|
54
|
+
this._commonProperties = {
|
|
55
|
+
os: super._os,
|
|
56
|
+
rp: super._resourceProvider,
|
|
57
|
+
cikey: this._cikey,
|
|
58
|
+
runtimeVersion: this._runtimeVersion,
|
|
59
|
+
language: this._language,
|
|
60
|
+
version: this._version,
|
|
61
|
+
attach: this._attach,
|
|
62
|
+
};
|
|
63
|
+
this._attachProperties = {
|
|
64
|
+
rpId: super._resourceIdentifier,
|
|
65
|
+
};
|
|
66
|
+
this._isInitialized = true;
|
|
67
|
+
this._initialize();
|
|
68
|
+
}
|
|
69
|
+
async _initialize() {
|
|
70
|
+
try {
|
|
71
|
+
await this._getResourceProvider();
|
|
72
|
+
// Add long interval observable callbacks
|
|
73
|
+
this._attachStatsbeatGauge.addCallback(this._attachCallback.bind(this));
|
|
74
|
+
this._longIntervalStatsbeatMeter.addBatchObservableCallback(this._featureCallback.bind(this), [this._featureStatsbeatGauge]);
|
|
75
|
+
// Export Feature/Attach Statsbeat once upon app initialization
|
|
76
|
+
this._longIntervalAzureExporter.export((await this._longIntervalMetricReader.collect()).resourceMetrics, (result) => {
|
|
77
|
+
if (result.code !== ExportResultCode.SUCCESS) {
|
|
78
|
+
diag.error(`LongIntervalStatsbeat: metrics export failed (error ${result.error})`);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
diag.debug("Call to get the resource provider failed.");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
_featureCallback(observableResult) {
|
|
87
|
+
let attributes;
|
|
88
|
+
if (this._instrumentation) {
|
|
89
|
+
attributes = Object.assign(Object.assign({}, this._commonProperties), { feature: this._instrumentation, type: StatsbeatFeatureType.INSTRUMENTATION });
|
|
90
|
+
observableResult.observe(this._featureStatsbeatGauge, 1, Object.assign({}, attributes));
|
|
91
|
+
}
|
|
92
|
+
if (this._feature) {
|
|
93
|
+
attributes = Object.assign(Object.assign({}, this._commonProperties), { feature: this._feature, type: StatsbeatFeatureType.FEATURE });
|
|
94
|
+
observableResult.observe(this._featureStatsbeatGauge, 1, Object.assign({}, attributes));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
_attachCallback(observableResult) {
|
|
98
|
+
let attributes = Object.assign(Object.assign({}, this._commonProperties), this._attachProperties);
|
|
99
|
+
observableResult.observe(1, attributes);
|
|
100
|
+
}
|
|
101
|
+
isInitialized() {
|
|
102
|
+
return this._isInitialized;
|
|
103
|
+
}
|
|
104
|
+
shutdown() {
|
|
105
|
+
this._longIntervalStatsbeatMeterProvider.shutdown();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Singleton LongIntervalStatsbeatMetrics instance.
|
|
110
|
+
* @internal
|
|
111
|
+
*/
|
|
112
|
+
export function getInstance(options) {
|
|
113
|
+
if (!instance) {
|
|
114
|
+
instance = new LongIntervalStatsbeatMetrics(options);
|
|
115
|
+
}
|
|
116
|
+
return instance;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=longIntervalStatsbeatMetrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"longIntervalStatsbeatMetrics.js","sourceRoot":"","sources":["../../../../src/export/statsbeat/longIntervalStatsbeatMetrics.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n diag,\n BatchObservableResult,\n ObservableGauge,\n ObservableResult,\n Meter,\n} from \"@opentelemetry/api\";\nimport { ExportResult, ExportResultCode } from \"@opentelemetry/core\";\nimport {\n MeterProvider,\n PeriodicExportingMetricReader,\n PeriodicExportingMetricReaderOptions,\n} from \"@opentelemetry/sdk-metrics\";\nimport { AzureMonitorExporterOptions, AzureMonitorStatsbeatExporter } from \"../../index\";\nimport * as ai from \"../../utils/constants/applicationinsights\";\nimport { StatsbeatMetrics } from \"./statsbeatMetrics\";\nimport {\n StatsbeatCounter,\n STATSBEAT_LANGUAGE,\n CommonStatsbeatProperties,\n AttachStatsbeatProperties,\n StatsbeatFeatureType,\n StatsbeatOptions,\n} from \"./types\";\n\nlet instance: LongIntervalStatsbeatMetrics | null = null;\n\n/**\n * Long Interval Statsbeat Metrics\n * @internal\n */\nclass LongIntervalStatsbeatMetrics extends StatsbeatMetrics {\n private _AZURE_MONITOR_STATSBEAT_FEATURES = process.env.AZURE_MONITOR_STATSBEAT_FEATURES;\n private _statsCollectionLongInterval: number = 86400000; // 1 day\n private _isInitialized: boolean = false;\n\n // Custom dimensions\n private _cikey: string;\n private _runtimeVersion: string;\n private _language: string;\n private _version: string;\n private _attach: string = \"sdk\";\n\n private _commonProperties: CommonStatsbeatProperties;\n private _attachProperties: AttachStatsbeatProperties;\n\n private _feature: number = 0;\n private _instrumentation: number = 0;\n\n private _longIntervalStatsbeatMeterProvider: MeterProvider;\n private _longIntervalAzureExporter: AzureMonitorStatsbeatExporter;\n private _longIntervalMetricReader: PeriodicExportingMetricReader;\n private _longIntervalStatsbeatMeter: Meter;\n\n // Network Attributes\n private _connectionString: string;\n\n // Observable Gauges\n private _featureStatsbeatGauge: ObservableGauge;\n private _attachStatsbeatGauge: ObservableGauge;\n\n constructor(options: StatsbeatOptions) {\n super();\n this._connectionString = super._getConnectionString(options.endpointUrl);\n const exporterConfig: AzureMonitorExporterOptions = {\n connectionString: this._connectionString,\n };\n\n if (this._AZURE_MONITOR_STATSBEAT_FEATURES) {\n try {\n this._feature = JSON.parse(this._AZURE_MONITOR_STATSBEAT_FEATURES).feature;\n this._instrumentation = JSON.parse(this._AZURE_MONITOR_STATSBEAT_FEATURES).instrumentation;\n } catch (error) {\n diag.error(\n `LongIntervalStatsbeat: Failed to parse features/instrumentations (error ${error})`\n );\n }\n }\n\n this._longIntervalStatsbeatMeterProvider = new MeterProvider();\n this._longIntervalAzureExporter = new AzureMonitorStatsbeatExporter(exporterConfig);\n\n // Export Long Interval Statsbeats every day\n const longIntervalMetricReaderOptions: PeriodicExportingMetricReaderOptions = {\n exporter: this._longIntervalAzureExporter,\n exportIntervalMillis:\n Number(process.env.LONG_INTERVAL_EXPORT_MILLIS) || this._statsCollectionLongInterval, // 1 day\n };\n\n this._longIntervalMetricReader = new PeriodicExportingMetricReader(\n longIntervalMetricReaderOptions\n );\n this._longIntervalStatsbeatMeterProvider.addMetricReader(this._longIntervalMetricReader);\n this._longIntervalStatsbeatMeter = this._longIntervalStatsbeatMeterProvider.getMeter(\n \"Azure Monitor Long Interval Statsbeat\"\n );\n\n // Assign Common Properties\n this._runtimeVersion = process.version;\n this._language = STATSBEAT_LANGUAGE;\n this._version = ai.packageVersion;\n this._cikey = options.instrumentationKey;\n\n this._featureStatsbeatGauge = this._longIntervalStatsbeatMeter.createObservableGauge(\n StatsbeatCounter.FEATURE\n );\n this._attachStatsbeatGauge = this._longIntervalStatsbeatMeter.createObservableGauge(\n StatsbeatCounter.ATTACH\n );\n\n this._commonProperties = {\n os: super._os,\n rp: super._resourceProvider,\n cikey: this._cikey,\n runtimeVersion: this._runtimeVersion,\n language: this._language,\n version: this._version,\n attach: this._attach,\n };\n\n this._attachProperties = {\n rpId: super._resourceIdentifier,\n };\n\n this._isInitialized = true;\n this._initialize();\n }\n\n private async _initialize() {\n try {\n await this._getResourceProvider();\n\n // Add long interval observable callbacks\n this._attachStatsbeatGauge.addCallback(this._attachCallback.bind(this));\n this._longIntervalStatsbeatMeter.addBatchObservableCallback(\n this._featureCallback.bind(this),\n [this._featureStatsbeatGauge]\n );\n\n // Export Feature/Attach Statsbeat once upon app initialization\n this._longIntervalAzureExporter.export(\n (await this._longIntervalMetricReader.collect()).resourceMetrics,\n (result: ExportResult) => {\n if (result.code !== ExportResultCode.SUCCESS) {\n diag.error(`LongIntervalStatsbeat: metrics export failed (error ${result.error})`);\n }\n }\n );\n } catch (error) {\n diag.debug(\"Call to get the resource provider failed.\");\n }\n }\n\n private _featureCallback(observableResult: BatchObservableResult) {\n let attributes;\n if (this._instrumentation) {\n attributes = {\n ...this._commonProperties,\n feature: this._instrumentation,\n type: StatsbeatFeatureType.INSTRUMENTATION,\n };\n observableResult.observe(this._featureStatsbeatGauge, 1, { ...attributes });\n }\n\n if (this._feature) {\n attributes = {\n ...this._commonProperties,\n feature: this._feature,\n type: StatsbeatFeatureType.FEATURE,\n };\n observableResult.observe(this._featureStatsbeatGauge, 1, { ...attributes });\n }\n }\n\n private _attachCallback(observableResult: ObservableResult) {\n let attributes = { ...this._commonProperties, ...this._attachProperties };\n observableResult.observe(1, attributes);\n }\n\n public isInitialized() {\n return this._isInitialized;\n }\n\n public shutdown() {\n this._longIntervalStatsbeatMeterProvider.shutdown();\n }\n}\n\n/**\n * Singleton LongIntervalStatsbeatMetrics instance.\n * @internal\n */\nexport function getInstance(options: StatsbeatOptions): LongIntervalStatsbeatMetrics {\n if (!instance) {\n instance = new LongIntervalStatsbeatMetrics(options);\n }\n return instance;\n}\n"]}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT license.
|
|
3
|
+
import { diag, } from "@opentelemetry/api";
|
|
4
|
+
import { MeterProvider, PeriodicExportingMetricReader, } from "@opentelemetry/sdk-metrics";
|
|
5
|
+
import { AzureMonitorStatsbeatExporter } from "../../index";
|
|
6
|
+
import * as ai from "../../utils/constants/applicationinsights";
|
|
7
|
+
import { StatsbeatMetrics } from "./statsbeatMetrics";
|
|
8
|
+
import { StatsbeatCounter, STATSBEAT_LANGUAGE, NetworkStatsbeat, } from "./types";
|
|
9
|
+
export class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
super();
|
|
12
|
+
this._isInitialized = false;
|
|
13
|
+
this._statsCollectionShortInterval = 900000; // 15 minutes
|
|
14
|
+
this._networkStatsbeatCollection = [];
|
|
15
|
+
this._attach = "sdk";
|
|
16
|
+
this._connectionString = super._getConnectionString(options.endpointUrl);
|
|
17
|
+
this._networkStatsbeatMeterProvider = new MeterProvider();
|
|
18
|
+
const exporterConfig = {
|
|
19
|
+
connectionString: this._connectionString,
|
|
20
|
+
};
|
|
21
|
+
this._networkAzureExporter = new AzureMonitorStatsbeatExporter(exporterConfig);
|
|
22
|
+
// Exports Network Statsbeat every 15 minutes
|
|
23
|
+
const networkMetricReaderOptions = {
|
|
24
|
+
exporter: this._networkAzureExporter,
|
|
25
|
+
exportIntervalMillis: options.networkCollectionInterval || this._statsCollectionShortInterval, // 15 minutes
|
|
26
|
+
};
|
|
27
|
+
this._networkMetricReader = new PeriodicExportingMetricReader(networkMetricReaderOptions);
|
|
28
|
+
this._networkStatsbeatMeterProvider.addMetricReader(this._networkMetricReader);
|
|
29
|
+
this._networkStatsbeatMeter = this._networkStatsbeatMeterProvider.getMeter("Azure Monitor Network Statsbeat");
|
|
30
|
+
this._endpointUrl = options.endpointUrl;
|
|
31
|
+
this._runtimeVersion = process.version;
|
|
32
|
+
this._language = STATSBEAT_LANGUAGE;
|
|
33
|
+
this._version = ai.packageVersion;
|
|
34
|
+
this._host = this._getShortHost(options.endpointUrl);
|
|
35
|
+
this._cikey = options.instrumentationKey;
|
|
36
|
+
this._successCountGauge = this._networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.SUCCESS_COUNT);
|
|
37
|
+
this._failureCountGauge = this._networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.FAILURE_COUNT);
|
|
38
|
+
this._retryCountGauge = this._networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.RETRY_COUNT);
|
|
39
|
+
this._throttleCountGauge = this._networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.THROTTLE_COUNT);
|
|
40
|
+
this._exceptionCountGauge = this._networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.EXCEPTION_COUNT);
|
|
41
|
+
this._averageDurationGauge = this._networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.AVERAGE_DURATION);
|
|
42
|
+
this._commonProperties = {
|
|
43
|
+
os: super._os,
|
|
44
|
+
rp: super._resourceProvider,
|
|
45
|
+
cikey: this._cikey,
|
|
46
|
+
runtimeVersion: this._runtimeVersion,
|
|
47
|
+
language: this._language,
|
|
48
|
+
version: this._version,
|
|
49
|
+
attach: this._attach,
|
|
50
|
+
};
|
|
51
|
+
this._networkProperties = {
|
|
52
|
+
endpoint: this._endpointUrl,
|
|
53
|
+
host: this._host,
|
|
54
|
+
};
|
|
55
|
+
this._isInitialized = true;
|
|
56
|
+
this._initialize();
|
|
57
|
+
}
|
|
58
|
+
isInitialized() {
|
|
59
|
+
return this._isInitialized;
|
|
60
|
+
}
|
|
61
|
+
shutdown() {
|
|
62
|
+
this._networkStatsbeatMeterProvider.shutdown();
|
|
63
|
+
}
|
|
64
|
+
async _initialize() {
|
|
65
|
+
try {
|
|
66
|
+
await super._getResourceProvider();
|
|
67
|
+
// Add network observable callbacks
|
|
68
|
+
this._successCountGauge.addCallback(this._successCallback.bind(this));
|
|
69
|
+
this._networkStatsbeatMeter.addBatchObservableCallback(this._failureCallback.bind(this), [
|
|
70
|
+
this._failureCountGauge,
|
|
71
|
+
]);
|
|
72
|
+
this._networkStatsbeatMeter.addBatchObservableCallback(this._retryCallback.bind(this), [
|
|
73
|
+
this._retryCountGauge,
|
|
74
|
+
]);
|
|
75
|
+
this._networkStatsbeatMeter.addBatchObservableCallback(this._throttleCallback.bind(this), [
|
|
76
|
+
this._throttleCountGauge,
|
|
77
|
+
]);
|
|
78
|
+
this._networkStatsbeatMeter.addBatchObservableCallback(this._exceptionCallback.bind(this), [
|
|
79
|
+
this._exceptionCountGauge,
|
|
80
|
+
]);
|
|
81
|
+
this._averageDurationGauge.addCallback(this._durationCallback.bind(this));
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
diag.debug("Call to get the resource provider failed.");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Observable gauge callbacks
|
|
88
|
+
_successCallback(observableResult) {
|
|
89
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
90
|
+
let attributes = Object.assign(Object.assign({}, this._commonProperties), this._networkProperties);
|
|
91
|
+
observableResult.observe(counter.totalSuccesfulRequestCount, attributes);
|
|
92
|
+
counter.totalSuccesfulRequestCount = 0;
|
|
93
|
+
}
|
|
94
|
+
_failureCallback(observableResult) {
|
|
95
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
96
|
+
/*
|
|
97
|
+
Takes the failureCountGauge, value (of the counter), and attributes
|
|
98
|
+
create a unqiue counter based on statusCode as well
|
|
99
|
+
append statusCode to attributes so the newly created attributes are unique.
|
|
100
|
+
*/
|
|
101
|
+
let attributes = Object.assign(Object.assign(Object.assign({}, this._networkProperties), this._commonProperties), { statusCode: 0 });
|
|
102
|
+
// For each { statusCode -> count } mapping, call observe, passing the count and attributes that include the statusCode
|
|
103
|
+
for (let i = 0; i < counter.totalFailedRequestCount.length; i++) {
|
|
104
|
+
attributes.statusCode = counter.totalFailedRequestCount[i].statusCode;
|
|
105
|
+
observableResult.observe(this._failureCountGauge, counter.totalFailedRequestCount[i].count, Object.assign({}, attributes));
|
|
106
|
+
counter.totalFailedRequestCount[i].count = 0;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
_retryCallback(observableResult) {
|
|
110
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
111
|
+
let attributes = Object.assign(Object.assign(Object.assign({}, this._networkProperties), this._commonProperties), { statusCode: 0 });
|
|
112
|
+
for (let i = 0; i < counter.retryCount.length; i++) {
|
|
113
|
+
attributes.statusCode = counter.retryCount[i].statusCode;
|
|
114
|
+
observableResult.observe(this._retryCountGauge, counter.retryCount[i].count, Object.assign({}, attributes));
|
|
115
|
+
counter.retryCount[i].count = 0;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
_throttleCallback(observableResult) {
|
|
119
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
120
|
+
let attributes = Object.assign(Object.assign(Object.assign({}, this._networkProperties), this._commonProperties), { statusCode: 0 });
|
|
121
|
+
for (let i = 0; i < counter.throttleCount.length; i++) {
|
|
122
|
+
attributes.statusCode = counter.throttleCount[i].statusCode;
|
|
123
|
+
observableResult.observe(this._throttleCountGauge, counter.throttleCount[i].count, Object.assign({}, attributes));
|
|
124
|
+
counter.throttleCount[i].count = 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
_exceptionCallback(observableResult) {
|
|
128
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
129
|
+
let attributes = Object.assign(Object.assign(Object.assign({}, this._networkProperties), this._commonProperties), { exceptionType: "" });
|
|
130
|
+
for (let i = 0; i < counter.exceptionCount.length; i++) {
|
|
131
|
+
attributes.exceptionType = counter.exceptionCount[i].exceptionType;
|
|
132
|
+
observableResult.observe(this._exceptionCountGauge, counter.exceptionCount[i].count, Object.assign({}, attributes));
|
|
133
|
+
counter.exceptionCount[i].count = 0;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
_durationCallback(observableResult) {
|
|
137
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
138
|
+
let attributes = Object.assign(Object.assign({}, this._networkProperties), this._commonProperties);
|
|
139
|
+
for (let i = 0; i < this._networkStatsbeatCollection.length; i++) {
|
|
140
|
+
let currentCounter = this._networkStatsbeatCollection[i];
|
|
141
|
+
currentCounter.time = Number(new Date());
|
|
142
|
+
let intervalRequests = currentCounter.totalRequestCount - currentCounter.lastRequestCount || 0;
|
|
143
|
+
currentCounter.averageRequestExecutionTime =
|
|
144
|
+
(currentCounter.intervalRequestExecutionTime -
|
|
145
|
+
currentCounter.lastIntervalRequestExecutionTime) /
|
|
146
|
+
intervalRequests || 0;
|
|
147
|
+
currentCounter.lastIntervalRequestExecutionTime = currentCounter.intervalRequestExecutionTime; // reset
|
|
148
|
+
currentCounter.lastRequestCount = currentCounter.totalRequestCount;
|
|
149
|
+
currentCounter.lastTime = currentCounter.time;
|
|
150
|
+
}
|
|
151
|
+
observableResult.observe(counter.averageRequestExecutionTime, attributes);
|
|
152
|
+
counter.averageRequestExecutionTime = 0;
|
|
153
|
+
}
|
|
154
|
+
// Public methods to increase counters
|
|
155
|
+
countSuccess(duration) {
|
|
156
|
+
if (!this._isInitialized) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
160
|
+
counter.totalRequestCount++;
|
|
161
|
+
counter.totalSuccesfulRequestCount++;
|
|
162
|
+
counter.intervalRequestExecutionTime += duration;
|
|
163
|
+
}
|
|
164
|
+
countFailure(duration, statusCode) {
|
|
165
|
+
if (!this._isInitialized) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
169
|
+
let currentStatusCounter = counter.totalFailedRequestCount.find((statusCounter) => statusCode === statusCounter.statusCode);
|
|
170
|
+
if (currentStatusCounter) {
|
|
171
|
+
currentStatusCounter.count++;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
counter.totalFailedRequestCount.push({ statusCode: statusCode, count: 1 });
|
|
175
|
+
}
|
|
176
|
+
counter.totalRequestCount++;
|
|
177
|
+
counter.intervalRequestExecutionTime += duration;
|
|
178
|
+
}
|
|
179
|
+
countRetry(statusCode) {
|
|
180
|
+
if (!this._isInitialized) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
184
|
+
let currentStatusCounter = counter.retryCount.find((statusCounter) => statusCode === statusCounter.statusCode);
|
|
185
|
+
if (currentStatusCounter) {
|
|
186
|
+
currentStatusCounter.count++;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
counter.retryCount.push({ statusCode: statusCode, count: 1 });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
countThrottle(statusCode) {
|
|
193
|
+
if (!this._isInitialized) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
197
|
+
let currentStatusCounter = counter.throttleCount.find((statusCounter) => statusCode === statusCounter.statusCode);
|
|
198
|
+
if (currentStatusCounter) {
|
|
199
|
+
currentStatusCounter.count++;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
counter.throttleCount.push({ statusCode: statusCode, count: 1 });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
countException(exceptionType) {
|
|
206
|
+
if (!this._isInitialized) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
let counter = this._getNetworkStatsbeatCounter(this._endpointUrl, this._host);
|
|
210
|
+
let currentErrorCounter = counter.exceptionCount.find((exceptionCounter) => exceptionType.name === exceptionCounter.exceptionType);
|
|
211
|
+
if (currentErrorCounter) {
|
|
212
|
+
currentErrorCounter.count++;
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
counter.exceptionCount.push({ exceptionType: exceptionType.name, count: 1 });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Gets a networkStatsbeat counter if one exists for the given endpoint
|
|
219
|
+
_getNetworkStatsbeatCounter(endpoint, host) {
|
|
220
|
+
// Check if the counter is available
|
|
221
|
+
for (let i = 0; i < this._networkStatsbeatCollection.length; i++) {
|
|
222
|
+
// Same object
|
|
223
|
+
if (endpoint === this._networkStatsbeatCollection[i].endpoint &&
|
|
224
|
+
host === this._networkStatsbeatCollection[i].host) {
|
|
225
|
+
return this._networkStatsbeatCollection[i];
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Create a new counter if not found
|
|
229
|
+
let newCounter = new NetworkStatsbeat(endpoint, host);
|
|
230
|
+
this._networkStatsbeatCollection.push(newCounter);
|
|
231
|
+
return newCounter;
|
|
232
|
+
}
|
|
233
|
+
_getShortHost(originalHost) {
|
|
234
|
+
let shortHost = originalHost;
|
|
235
|
+
try {
|
|
236
|
+
let hostRegex = new RegExp(/^https?:\/\/(?:www\.)?([^\/.-]+)/);
|
|
237
|
+
let res = hostRegex.exec(originalHost);
|
|
238
|
+
if (res != null && res.length > 1) {
|
|
239
|
+
shortHost = res[1];
|
|
240
|
+
}
|
|
241
|
+
shortHost = shortHost.replace(".in.applicationinsights.azure.com", "");
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
diag.debug("Failed to get the short host name.");
|
|
245
|
+
}
|
|
246
|
+
return shortHost;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=networkStatsbeatMetrics.js.map
|