@azure/monitor-opentelemetry-exporter 1.0.0-beta.10 → 1.0.0-beta.11

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.
@@ -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 { StatsbeatMetrics } from "./statsbeat/statsbeatMetrics";
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._statsbeatMetrics = new StatsbeatMetrics({
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._statsbeatMetrics) === null || _a === void 0 ? void 0 : _a.countSuccess(duration);
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._statsbeatMetrics) === null || _b === void 0 ? void 0 : _b.countThrottle(statusCode);
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._statsbeatMetrics) === null || _c === void 0 ? void 0 : _c.countRetry(statusCode);
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._statsbeatMetrics) === null || _d === void 0 ? void 0 : _d.countFailure(duration, statusCode);
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._statsbeatMetrics) === null || _e === void 0 ? void 0 : _e.countRetry(statusCode);
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._statsbeatMetrics) {
150
+ if (this._networkStatsbeatMetrics) {
146
151
  if (statusCode) {
147
- this._statsbeatMetrics.countFailure(duration, statusCode);
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._statsbeatMetrics) === null || _f === void 0 ? void 0 : _f.countException(redirectError);
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._statsbeatMetrics) === null || _g === void 0 ? void 0 : _g.countRetry(restError.statusCode);
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._statsbeatMetrics) === null || _h === void 0 ? void 0 : _h.countRetry(restError.statusCode);
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._statsbeatMetrics) === null || _j === void 0 ? void 0 : _j.countException(restError);
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._statsbeatMetrics) === null || _a === void 0 ? void 0 : _a.shutdown();
206
- this._statsbeatMetrics = undefined;
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