@azure/monitor-opentelemetry-exporter 1.0.0-beta.35 → 1.0.0-beta.37
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/dist/commonjs/Declarations/Constants.d.ts +10 -0
- package/dist/commonjs/Declarations/Constants.d.ts.map +1 -1
- package/dist/commonjs/Declarations/Constants.js +11 -1
- package/dist/commonjs/Declarations/Constants.js.map +1 -1
- package/dist/commonjs/Declarations/Contracts/Constants.d.ts +1 -1
- package/dist/commonjs/Declarations/Contracts/Constants.d.ts.map +1 -1
- package/dist/commonjs/Declarations/Contracts/Constants.js.map +1 -1
- package/dist/commonjs/export/metric.d.ts.map +1 -1
- package/dist/commonjs/export/metric.js +1 -1
- package/dist/commonjs/export/metric.js.map +1 -1
- package/dist/commonjs/export/statsbeat/customerSDKStats.d.ts +2 -2
- package/dist/commonjs/export/statsbeat/customerSDKStats.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/customerSDKStats.js +11 -9
- package/dist/commonjs/export/statsbeat/customerSDKStats.js.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatExporter.d.ts +5 -0
- package/dist/commonjs/export/statsbeat/statsbeatExporter.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatExporter.js +19 -5
- package/dist/commonjs/export/statsbeat/statsbeatExporter.js.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatMetrics.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatMetrics.js +3 -2
- package/dist/commonjs/export/statsbeat/statsbeatMetrics.js.map +1 -1
- package/dist/commonjs/export/trace.d.ts +1 -0
- package/dist/commonjs/export/trace.d.ts.map +1 -1
- package/dist/commonjs/export/trace.js +9 -1
- package/dist/commonjs/export/trace.js.map +1 -1
- package/dist/commonjs/generated/applicationInsightsClient.js +1 -1
- package/dist/commonjs/generated/applicationInsightsClient.js.map +1 -1
- package/dist/commonjs/generated/models/index.d.ts.map +1 -1
- package/dist/commonjs/generated/models/index.js.map +1 -1
- package/dist/commonjs/generated/models/mappers.js +11 -11
- package/dist/commonjs/generated/models/mappers.js.map +1 -1
- package/dist/commonjs/platform/nodejs/baseSender.d.ts +1 -0
- package/dist/commonjs/platform/nodejs/baseSender.d.ts.map +1 -1
- package/dist/commonjs/platform/nodejs/baseSender.js +35 -16
- package/dist/commonjs/platform/nodejs/baseSender.js.map +1 -1
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.d.ts +15 -0
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.d.ts.map +1 -1
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.js +65 -2
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.js.map +1 -1
- package/dist/commonjs/tsdoc-metadata.json +1 -1
- package/dist/commonjs/utils/common.d.ts +2 -2
- package/dist/commonjs/utils/common.d.ts.map +1 -1
- package/dist/commonjs/utils/common.js +16 -11
- package/dist/commonjs/utils/common.js.map +1 -1
- package/dist/commonjs/utils/constants/applicationinsights.d.ts +1 -1
- package/dist/commonjs/utils/constants/applicationinsights.js +1 -1
- package/dist/commonjs/utils/constants/applicationinsights.js.map +1 -1
- package/dist/commonjs/utils/logUtils.js +2 -2
- package/dist/commonjs/utils/logUtils.js.map +1 -1
- package/dist/esm/Declarations/Constants.d.ts +10 -0
- package/dist/esm/Declarations/Constants.d.ts.map +1 -1
- package/dist/esm/Declarations/Constants.js +10 -0
- package/dist/esm/Declarations/Constants.js.map +1 -1
- package/dist/esm/Declarations/Contracts/Constants.d.ts +1 -1
- package/dist/esm/Declarations/Contracts/Constants.d.ts.map +1 -1
- package/dist/esm/Declarations/Contracts/Constants.js.map +1 -1
- package/dist/esm/export/metric.d.ts.map +1 -1
- package/dist/esm/export/metric.js +1 -1
- package/dist/esm/export/metric.js.map +1 -1
- package/dist/esm/export/statsbeat/customerSDKStats.d.ts +2 -2
- package/dist/esm/export/statsbeat/customerSDKStats.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/customerSDKStats.js +11 -9
- package/dist/esm/export/statsbeat/customerSDKStats.js.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatExporter.d.ts +5 -0
- package/dist/esm/export/statsbeat/statsbeatExporter.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatExporter.js +19 -5
- package/dist/esm/export/statsbeat/statsbeatExporter.js.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatMetrics.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatMetrics.js +3 -2
- package/dist/esm/export/statsbeat/statsbeatMetrics.js.map +1 -1
- package/dist/esm/export/trace.d.ts +1 -0
- package/dist/esm/export/trace.d.ts.map +1 -1
- package/dist/esm/export/trace.js +9 -1
- package/dist/esm/export/trace.js.map +1 -1
- package/dist/esm/generated/applicationInsightsClient.js +1 -1
- package/dist/esm/generated/applicationInsightsClient.js.map +1 -1
- package/dist/esm/generated/models/index.d.ts.map +1 -1
- package/dist/esm/generated/models/index.js.map +1 -1
- package/dist/esm/generated/models/mappers.js +11 -11
- package/dist/esm/generated/models/mappers.js.map +1 -1
- package/dist/esm/platform/nodejs/baseSender.d.ts +1 -0
- package/dist/esm/platform/nodejs/baseSender.d.ts.map +1 -1
- package/dist/esm/platform/nodejs/baseSender.js +36 -17
- package/dist/esm/platform/nodejs/baseSender.js.map +1 -1
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.d.ts +15 -0
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.d.ts.map +1 -1
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.js +66 -4
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.js.map +1 -1
- package/dist/esm/utils/common.d.ts +2 -2
- package/dist/esm/utils/common.d.ts.map +1 -1
- package/dist/esm/utils/common.js +17 -12
- package/dist/esm/utils/common.js.map +1 -1
- package/dist/esm/utils/constants/applicationinsights.d.ts +1 -1
- package/dist/esm/utils/constants/applicationinsights.js +1 -1
- package/dist/esm/utils/constants/applicationinsights.js.map +1 -1
- package/dist/esm/utils/logUtils.js +2 -2
- package/dist/esm/utils/logUtils.js.map +1 -1
- package/package.json +18 -14
|
@@ -12,7 +12,6 @@ const longIntervalStatsbeatMetrics_js_1 = require("../../export/statsbeat/longIn
|
|
|
12
12
|
const types_js_2 = require("../../export/statsbeat/types.js");
|
|
13
13
|
const breezeUtils_js_1 = require("../../utils/breezeUtils.js");
|
|
14
14
|
const Constants_js_1 = require("../../Declarations/Constants.js");
|
|
15
|
-
const customerSDKStats_js_1 = require("../../export/statsbeat/customerSDKStats.js");
|
|
16
15
|
const DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60_000;
|
|
17
16
|
/**
|
|
18
17
|
* Base sender class
|
|
@@ -55,12 +54,24 @@ class BaseSender {
|
|
|
55
54
|
api_1.diag.warn(`Invalid value for APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL environment variable: '${envValue}'. Expected a positive number (seconds). Using default export interval.`);
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
// Initialize customer SDK stats metrics asynchronously to avoid circular dependency
|
|
58
|
+
// Only initialize if not already set (e.g., by tests)
|
|
59
|
+
if (!this.customerSDKStatsMetrics) {
|
|
60
|
+
import("../../export/statsbeat/customerSDKStats.js")
|
|
61
|
+
.then((module) => module.CustomerSDKStatsMetrics.getInstance({
|
|
62
|
+
instrumentationKey: options.instrumentationKey,
|
|
63
|
+
endpointUrl: options.endpointUrl,
|
|
64
|
+
disableOfflineStorage: this.disableOfflineStorage,
|
|
65
|
+
networkCollectionInterval: exportInterval,
|
|
66
|
+
}))
|
|
67
|
+
.then((metrics) => {
|
|
68
|
+
this.customerSDKStatsMetrics = metrics;
|
|
69
|
+
return;
|
|
70
|
+
})
|
|
71
|
+
.catch((error) => {
|
|
72
|
+
api_1.diag.warn("Failed to initialize customer SDK stats metrics:", error);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
this.persister = new index_js_1.FileSystemPersist(options.instrumentationKey, options.exporterOptions, this.customerSDKStatsMetrics);
|
|
@@ -152,9 +163,9 @@ class BaseSender {
|
|
|
152
163
|
const filteredSuccessfulEnvelopes = successfulEnvelopes.filter(Boolean);
|
|
153
164
|
this.customerSDKStatsMetrics?.countDroppedItems(filteredSuccessfulEnvelopes, statusCode);
|
|
154
165
|
}
|
|
155
|
-
return {
|
|
166
|
+
return this.buildExportResult({
|
|
156
167
|
code: core_1.ExportResultCode.FAILED,
|
|
157
|
-
};
|
|
168
|
+
});
|
|
158
169
|
}
|
|
159
170
|
else {
|
|
160
171
|
// calls resultCallback(ExportResult) based on result of persister.push
|
|
@@ -178,9 +189,9 @@ class BaseSender {
|
|
|
178
189
|
this.incrementStatsbeatFailure();
|
|
179
190
|
this.customerSDKStatsMetrics?.countDroppedItems(envelopes, types_js_2.DropCode.CLIENT_EXCEPTION);
|
|
180
191
|
}
|
|
181
|
-
return {
|
|
192
|
+
return this.buildExportResult({
|
|
182
193
|
code: core_1.ExportResultCode.FAILED,
|
|
183
|
-
};
|
|
194
|
+
});
|
|
184
195
|
}
|
|
185
196
|
}
|
|
186
197
|
catch (error) {
|
|
@@ -208,7 +219,7 @@ class BaseSender {
|
|
|
208
219
|
this.networkStatsbeatMetrics?.countException(redirectError);
|
|
209
220
|
this.customerSDKStatsMetrics?.countDroppedItems(envelopes, types_js_2.DropCode.CLIENT_EXCEPTION, redirectError.message, types_js_1.ExceptionType.CLIENT_EXCEPTION);
|
|
210
221
|
}
|
|
211
|
-
return { code: core_1.ExportResultCode.FAILED, error: redirectError };
|
|
222
|
+
return this.buildExportResult({ code: core_1.ExportResultCode.FAILED, error: redirectError });
|
|
212
223
|
}
|
|
213
224
|
}
|
|
214
225
|
else if (restError.statusCode &&
|
|
@@ -250,7 +261,7 @@ class BaseSender {
|
|
|
250
261
|
this.customerSDKStatsMetrics?.countDroppedItems(envelopes, types_js_2.DropCode.CLIENT_EXCEPTION, restError.message);
|
|
251
262
|
api_1.diag.error("Envelopes could not be exported and are not retriable. Error message:", restError.message);
|
|
252
263
|
}
|
|
253
|
-
return { code: core_1.ExportResultCode.FAILED, error: restError };
|
|
264
|
+
return this.buildExportResult({ code: core_1.ExportResultCode.FAILED, error: restError });
|
|
254
265
|
}
|
|
255
266
|
}
|
|
256
267
|
/**
|
|
@@ -261,10 +272,10 @@ class BaseSender {
|
|
|
261
272
|
const success = await this.persister.push(envelopes);
|
|
262
273
|
return success
|
|
263
274
|
? { code: core_1.ExportResultCode.SUCCESS }
|
|
264
|
-
: {
|
|
275
|
+
: this.buildExportResult({
|
|
265
276
|
code: core_1.ExportResultCode.FAILED,
|
|
266
277
|
error: new Error("Failed to persist envelope in disk."),
|
|
267
|
-
};
|
|
278
|
+
});
|
|
268
279
|
}
|
|
269
280
|
catch (ex) {
|
|
270
281
|
if (!this.isStatsbeatSender) {
|
|
@@ -273,7 +284,7 @@ class BaseSender {
|
|
|
273
284
|
this.customerSDKStatsMetrics?.countDroppedItems(envelopes, types_js_2.DropCode.CLIENT_STORAGE_DISABLED);
|
|
274
285
|
}
|
|
275
286
|
}
|
|
276
|
-
return { code: core_1.ExportResultCode.FAILED, error: ex };
|
|
287
|
+
return this.buildExportResult({ code: core_1.ExportResultCode.FAILED, error: ex });
|
|
277
288
|
}
|
|
278
289
|
}
|
|
279
290
|
/**
|
|
@@ -321,6 +332,14 @@ class BaseSender {
|
|
|
321
332
|
}
|
|
322
333
|
return false;
|
|
323
334
|
}
|
|
335
|
+
// Silence noisy failures from statsbeat OTel metric readers unless logging is explicitly enabled
|
|
336
|
+
buildExportResult(result) {
|
|
337
|
+
const shouldSurfaceStatsbeatFailures = !!process.env[Constants_js_1.ENV_APPLICATIONINSIGHTS_SDK_STATS_LOGGING];
|
|
338
|
+
if (this.isStatsbeatSender && result.code === core_1.ExportResultCode.FAILED) {
|
|
339
|
+
return shouldSurfaceStatsbeatFailures ? result : { code: core_1.ExportResultCode.SUCCESS };
|
|
340
|
+
}
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
324
343
|
}
|
|
325
344
|
exports.BaseSender = BaseSender;
|
|
326
345
|
//# sourceMappingURL=baseSender.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseSender.js","sourceRoot":"","sources":["../../../../src/platform/nodejs/baseSender.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 type { PersistentStorage, SenderResult } from \"../../types.js\";\nimport { ExceptionType } from \"../../export/statsbeat/types.js\";\nimport type { AzureMonitorExporterOptions } from \"../../config.js\";\nimport { FileSystemPersist } from \"./persist/index.js\";\nimport type { ExportResult } from \"@opentelemetry/core\";\nimport { ExportResultCode } from \"@opentelemetry/core\";\nimport { NetworkStatsbeatMetrics } from \"../../export/statsbeat/networkStatsbeatMetrics.js\";\nimport { LongIntervalStatsbeatMetrics } from \"../../export/statsbeat/longIntervalStatsbeatMetrics.js\";\nimport type { RestError } from \"@azure/core-rest-pipeline\";\nimport {\n DropCode,\n RetryCode,\n MAX_STATSBEAT_FAILURES,\n isStatsbeatShutdownStatus,\n} from \"../../export/statsbeat/types.js\";\nimport type { BreezeResponse } from \"../../utils/breezeUtils.js\";\nimport { isRetriable } from \"../../utils/breezeUtils.js\";\nimport type { TelemetryItem as Envelope } from \"../../generated/index.js\";\nimport {\n ENV_APPLICATIONINSIGHTS_SDKSTATS_ENABLED_PREVIEW,\n ENV_APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL,\n RetriableRestErrorTypes,\n} from \"../../Declarations/Constants.js\";\nimport { CustomerSDKStatsMetrics } from \"../../export/statsbeat/customerSDKStats.js\";\n\nconst DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60_000;\n\n/**\n * Base sender class\n * @internal\n */\nexport abstract class BaseSender {\n private readonly persister: PersistentStorage;\n private numConsecutiveRedirects: number;\n private retryTimer: NodeJS.Timeout | null;\n private networkStatsbeatMetrics: NetworkStatsbeatMetrics | undefined;\n private customerSDKStatsMetrics: CustomerSDKStatsMetrics | undefined;\n private longIntervalStatsbeatMetrics;\n private statsbeatFailureCount: number = 0;\n private batchSendRetryIntervalMs: number = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;\n private isStatsbeatSender: boolean;\n private disableOfflineStorage: boolean;\n\n constructor(options: {\n endpointUrl: string;\n instrumentationKey: string;\n trackStatsbeat: boolean;\n exporterOptions: AzureMonitorExporterOptions;\n aadAudience?: string;\n isStatsbeatSender?: boolean;\n }) {\n this.numConsecutiveRedirects = 0;\n this.disableOfflineStorage = options.exporterOptions.disableOfflineStorage || false;\n if (options.trackStatsbeat) {\n this.networkStatsbeatMetrics = NetworkStatsbeatMetrics.getInstance({\n instrumentationKey: options.instrumentationKey,\n endpointUrl: options.endpointUrl,\n disableOfflineStorage: this.disableOfflineStorage,\n });\n this.longIntervalStatsbeatMetrics = LongIntervalStatsbeatMetrics.getInstance({\n instrumentationKey: options.instrumentationKey,\n endpointUrl: options.endpointUrl,\n disableOfflineStorage: this.disableOfflineStorage,\n });\n if (process.env[ENV_APPLICATIONINSIGHTS_SDKSTATS_ENABLED_PREVIEW]) {\n let exportInterval: number | undefined;\n if (process.env[ENV_APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL]) {\n const envValue = process.env[ENV_APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL];\n const exportIntervalSeconds = parseInt(envValue, 10);\n if (!isNaN(exportIntervalSeconds) && exportIntervalSeconds > 0) {\n exportInterval = exportIntervalSeconds * 1000; // Convert seconds to milliseconds\n } else {\n diag.warn(\n `Invalid value for APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL environment variable: '${envValue}'. Expected a positive number (seconds). Using default export interval.`,\n );\n }\n }\n this.customerSDKStatsMetrics = CustomerSDKStatsMetrics.getInstance({\n instrumentationKey: options.instrumentationKey,\n endpointUrl: options.endpointUrl,\n disableOfflineStorage: this.disableOfflineStorage,\n networkCollectionInterval: exportInterval,\n });\n }\n }\n this.persister = new FileSystemPersist(\n options.instrumentationKey,\n options.exporterOptions,\n this.customerSDKStatsMetrics,\n );\n this.retryTimer = null;\n this.isStatsbeatSender = options.isStatsbeatSender || false;\n }\n\n abstract send(payload: unknown[]): Promise<SenderResult>;\n abstract shutdown(): Promise<void>;\n abstract handlePermanentRedirect(location: string | undefined): void;\n\n /**\n * Export envelopes\n */\n public 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.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 exporting statsbeat and statsbeat is not disabled -- count success\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countSuccess(duration);\n this.customerSDKStatsMetrics?.countSuccessfulItems(envelopes);\n }\n return { code: ExportResultCode.SUCCESS };\n } else if (statusCode && isRetriable(statusCode)) {\n // Failed -- persist failed data\n if (statusCode === 429 || statusCode === 439) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countThrottle(statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, statusCode);\n }\n return {\n code: ExportResultCode.SUCCESS,\n };\n }\n if (result) {\n diag.info(result);\n const breezeResponse = JSON.parse(result) as BreezeResponse;\n const filteredEnvelopes: Envelope[] = [];\n // Create a list of successful envelopes by filtering out the failed ones for customer SDK Stats\n const successfulEnvelopes: Envelope[] = [...envelopes];\n\n // If we have a partial success, count the succeeded envelopes\n if (breezeResponse.itemsAccepted > 0 && statusCode === 206 && !this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countSuccess(duration);\n }\n // Figure out if we need to either retry or count failures\n if (breezeResponse.errors) {\n breezeResponse.errors.forEach((error) => {\n // Mark as undefined so we don't process them in countSuccessfulEnvelopes\n successfulEnvelopes[error.index] = undefined as unknown as Envelope;\n\n // Add to retry list if status code is retriable\n if (error.statusCode && isRetriable(error.statusCode)) {\n filteredEnvelopes.push(envelopes[error.index]);\n }\n });\n }\n\n // If we have a partial success, count the succeeded envelopes\n if (breezeResponse.itemsAccepted > 0) {\n // Count only the successful envelopes (non-undefined)\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countSuccess(duration);\n this.customerSDKStatsMetrics?.countSuccessfulItems(envelopes);\n }\n }\n if (filteredEnvelopes.length > 0) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countRetry(statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, statusCode);\n }\n // calls resultCallback(ExportResult) based on result of persister.push\n return await this.persist(filteredEnvelopes);\n }\n // Failed -- not retriable\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countFailure(duration, statusCode);\n // Count dropped items for customer SDK Stats for non-retriable status codes\n const filteredSuccessfulEnvelopes = successfulEnvelopes.filter(Boolean);\n this.customerSDKStatsMetrics?.countDroppedItems(\n filteredSuccessfulEnvelopes,\n statusCode,\n );\n }\n return {\n code: ExportResultCode.FAILED,\n };\n } else {\n // calls resultCallback(ExportResult) based on result of persister.push\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countRetry(statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, statusCode);\n }\n return await this.persist(envelopes);\n }\n } else {\n // Failed -- not retriable\n if (this.networkStatsbeatMetrics && !this.isStatsbeatSender) {\n if (statusCode) {\n this.networkStatsbeatMetrics.countFailure(duration, statusCode);\n this.customerSDKStatsMetrics?.countDroppedItems(envelopes, statusCode);\n }\n } else {\n // Handles all other status codes or client exceptions for Statsbeat\n this.incrementStatsbeatFailure();\n this.customerSDKStatsMetrics?.countDroppedItems(envelopes, DropCode.CLIENT_EXCEPTION);\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.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 const redirectError = new Error(\"Circular redirect\");\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countException(redirectError);\n this.customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_EXCEPTION,\n redirectError.message,\n ExceptionType.CLIENT_EXCEPTION,\n );\n }\n return { code: ExportResultCode.FAILED, error: redirectError };\n }\n } else if (\n restError.statusCode &&\n isRetriable(restError.statusCode) &&\n !this.isStatsbeatSender\n ) {\n this.networkStatsbeatMetrics?.countRetry(restError.statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, restError.statusCode);\n return this.persist(envelopes);\n } else if (\n restError.statusCode === 400 &&\n restError.message.includes(\"Invalid instrumentation key\")\n ) {\n // Invalid instrumentation key, shutdown statsbeat, fail silently\n this.shutdownStatsbeat();\n return { code: ExportResultCode.SUCCESS };\n } else if (\n restError.statusCode &&\n this.isStatsbeatSender &&\n isStatsbeatShutdownStatus(restError.statusCode)\n ) {\n // If the status code is a shutdown status code for statsbeat, shutdown statsbeat and fail silently\n this.incrementStatsbeatFailure();\n return { code: ExportResultCode.SUCCESS };\n }\n\n // For retriable REST errors\n if (this.isRetriableRestError(restError) && !this.isStatsbeatSender) {\n if (this.customerSDKStatsMetrics?.isTimeoutError(restError) && !this.isStatsbeatSender) {\n this.customerSDKStatsMetrics?.countRetryItems(\n envelopes,\n RetryCode.CLIENT_TIMEOUT,\n \"timeout_exception\",\n ExceptionType.TIMEOUT_EXCEPTION,\n );\n diag.error(\"Request timed out. Error message:\", restError.message);\n } else if (restError.statusCode) {\n this.networkStatsbeatMetrics?.countRetry(restError.statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, restError.statusCode);\n }\n diag.error(\n \"Retrying due to transient client side error. Error message:\",\n restError.message,\n );\n return this.persist(envelopes);\n }\n // For non-retriable REST errors or client exceptions\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countException(restError);\n this.customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_EXCEPTION,\n restError.message,\n );\n diag.error(\n \"Envelopes could not be exported and are not retriable. Error message:\",\n restError.message,\n );\n }\n return { code: ExportResultCode.FAILED, error: restError };\n }\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 if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countWriteFailure();\n if (this.disableOfflineStorage && envelopes) {\n this.customerSDKStatsMetrics?.countDroppedItems(\n envelopes as Envelope[],\n DropCode.CLIENT_STORAGE_DISABLED,\n );\n }\n }\n return { code: ExportResultCode.FAILED, error: ex };\n }\n }\n\n /**\n * Disable collection of statsbeat metrics after max failures\n */\n private incrementStatsbeatFailure(): void {\n this.statsbeatFailureCount++;\n if (this.statsbeatFailureCount > MAX_STATSBEAT_FAILURES) {\n this.shutdownStatsbeat();\n }\n }\n\n /**\n * Shutdown statsbeat metrics\n */\n private shutdownStatsbeat(): void {\n if (this.networkStatsbeatMetrics) {\n this.networkStatsbeatMetrics.shutdown();\n }\n if (this.longIntervalStatsbeatMetrics) {\n this.longIntervalStatsbeatMetrics?.shutdown();\n }\n if (this.customerSDKStatsMetrics) {\n this.customerSDKStatsMetrics.shutdown();\n }\n this.statsbeatFailureCount = 0;\n }\n\n private async sendFirstPersistedFile(): Promise<void> {\n const envelopes = (await this.persister.shift()) as Envelope[] | null;\n try {\n if (envelopes) {\n await this.send(envelopes);\n }\n } catch (err: any) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countReadFailure();\n }\n diag.warn(`Failed to fetch persisted file`, err);\n }\n }\n\n private isRetriableRestError(error: RestError): boolean {\n const restErrorTypes: string[] = Object.values(RetriableRestErrorTypes);\n if (error && error.code && restErrorTypes.includes(error.code)) {\n return true;\n }\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"baseSender.js","sourceRoot":"","sources":["../../../../src/platform/nodejs/baseSender.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 type { PersistentStorage, SenderResult } from \"../../types.js\";\nimport { ExceptionType } from \"../../export/statsbeat/types.js\";\nimport type { AzureMonitorExporterOptions } from \"../../config.js\";\nimport { FileSystemPersist } from \"./persist/index.js\";\nimport type { ExportResult } from \"@opentelemetry/core\";\nimport { ExportResultCode } from \"@opentelemetry/core\";\nimport { NetworkStatsbeatMetrics } from \"../../export/statsbeat/networkStatsbeatMetrics.js\";\nimport { LongIntervalStatsbeatMetrics } from \"../../export/statsbeat/longIntervalStatsbeatMetrics.js\";\nimport type { RestError } from \"@azure/core-rest-pipeline\";\nimport {\n DropCode,\n RetryCode,\n MAX_STATSBEAT_FAILURES,\n isStatsbeatShutdownStatus,\n} from \"../../export/statsbeat/types.js\";\nimport type { BreezeResponse } from \"../../utils/breezeUtils.js\";\nimport { isRetriable } from \"../../utils/breezeUtils.js\";\nimport type { TelemetryItem as Envelope } from \"../../generated/index.js\";\nimport {\n ENV_APPLICATIONINSIGHTS_SDKSTATS_ENABLED_PREVIEW,\n ENV_APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL,\n ENV_APPLICATIONINSIGHTS_SDK_STATS_LOGGING,\n RetriableRestErrorTypes,\n} from \"../../Declarations/Constants.js\";\nimport { CustomerSDKStatsMetrics } from \"../../export/statsbeat/customerSDKStats.js\";\n\nconst DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60_000;\n\n/**\n * Base sender class\n * @internal\n */\nexport abstract class BaseSender {\n private readonly persister: PersistentStorage;\n private numConsecutiveRedirects: number;\n private retryTimer: NodeJS.Timeout | null;\n private networkStatsbeatMetrics: NetworkStatsbeatMetrics | undefined;\n private customerSDKStatsMetrics: CustomerSDKStatsMetrics | undefined;\n private longIntervalStatsbeatMetrics;\n private statsbeatFailureCount: number = 0;\n private batchSendRetryIntervalMs: number = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;\n private isStatsbeatSender: boolean;\n private disableOfflineStorage: boolean;\n\n constructor(options: {\n endpointUrl: string;\n instrumentationKey: string;\n trackStatsbeat: boolean;\n exporterOptions: AzureMonitorExporterOptions;\n aadAudience?: string;\n isStatsbeatSender?: boolean;\n }) {\n this.numConsecutiveRedirects = 0;\n this.disableOfflineStorage = options.exporterOptions.disableOfflineStorage || false;\n if (options.trackStatsbeat) {\n this.networkStatsbeatMetrics = NetworkStatsbeatMetrics.getInstance({\n instrumentationKey: options.instrumentationKey,\n endpointUrl: options.endpointUrl,\n disableOfflineStorage: this.disableOfflineStorage,\n });\n this.longIntervalStatsbeatMetrics = LongIntervalStatsbeatMetrics.getInstance({\n instrumentationKey: options.instrumentationKey,\n endpointUrl: options.endpointUrl,\n disableOfflineStorage: this.disableOfflineStorage,\n });\n if (process.env[ENV_APPLICATIONINSIGHTS_SDKSTATS_ENABLED_PREVIEW]) {\n let exportInterval: number | undefined;\n if (process.env[ENV_APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL]) {\n const envValue = process.env[ENV_APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL];\n const exportIntervalSeconds = parseInt(envValue, 10);\n if (!isNaN(exportIntervalSeconds) && exportIntervalSeconds > 0) {\n exportInterval = exportIntervalSeconds * 1000; // Convert seconds to milliseconds\n } else {\n diag.warn(\n `Invalid value for APPLICATIONINSIGHTS_SDKSTATS_EXPORT_INTERVAL environment variable: '${envValue}'. Expected a positive number (seconds). Using default export interval.`,\n );\n }\n }\n // Initialize customer SDK stats metrics asynchronously to avoid circular dependency\n // Only initialize if not already set (e.g., by tests)\n if (!this.customerSDKStatsMetrics) {\n import(\"../../export/statsbeat/customerSDKStats.js\")\n .then((module) =>\n module.CustomerSDKStatsMetrics.getInstance({\n instrumentationKey: options.instrumentationKey,\n endpointUrl: options.endpointUrl,\n disableOfflineStorage: this.disableOfflineStorage,\n networkCollectionInterval: exportInterval,\n }),\n )\n .then((metrics) => {\n this.customerSDKStatsMetrics = metrics;\n return;\n })\n .catch((error) => {\n diag.warn(\"Failed to initialize customer SDK stats metrics:\", error);\n });\n }\n }\n }\n this.persister = new FileSystemPersist(\n options.instrumentationKey,\n options.exporterOptions,\n this.customerSDKStatsMetrics,\n );\n this.retryTimer = null;\n this.isStatsbeatSender = options.isStatsbeatSender || false;\n }\n\n abstract send(payload: unknown[]): Promise<SenderResult>;\n abstract shutdown(): Promise<void>;\n abstract handlePermanentRedirect(location: string | undefined): void;\n\n /**\n * Export envelopes\n */\n public 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.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 exporting statsbeat and statsbeat is not disabled -- count success\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countSuccess(duration);\n this.customerSDKStatsMetrics?.countSuccessfulItems(envelopes);\n }\n return { code: ExportResultCode.SUCCESS };\n } else if (statusCode && isRetriable(statusCode)) {\n // Failed -- persist failed data\n if (statusCode === 429 || statusCode === 439) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countThrottle(statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, statusCode);\n }\n return {\n code: ExportResultCode.SUCCESS,\n };\n }\n if (result) {\n diag.info(result);\n const breezeResponse = JSON.parse(result) as BreezeResponse;\n const filteredEnvelopes: Envelope[] = [];\n // Create a list of successful envelopes by filtering out the failed ones for customer SDK Stats\n const successfulEnvelopes: Envelope[] = [...envelopes];\n\n // If we have a partial success, count the succeeded envelopes\n if (breezeResponse.itemsAccepted > 0 && statusCode === 206 && !this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countSuccess(duration);\n }\n // Figure out if we need to either retry or count failures\n if (breezeResponse.errors) {\n breezeResponse.errors.forEach((error) => {\n // Mark as undefined so we don't process them in countSuccessfulEnvelopes\n successfulEnvelopes[error.index] = undefined as unknown as Envelope;\n\n // Add to retry list if status code is retriable\n if (error.statusCode && isRetriable(error.statusCode)) {\n filteredEnvelopes.push(envelopes[error.index]);\n }\n });\n }\n\n // If we have a partial success, count the succeeded envelopes\n if (breezeResponse.itemsAccepted > 0) {\n // Count only the successful envelopes (non-undefined)\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countSuccess(duration);\n this.customerSDKStatsMetrics?.countSuccessfulItems(envelopes);\n }\n }\n if (filteredEnvelopes.length > 0) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countRetry(statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, statusCode);\n }\n // calls resultCallback(ExportResult) based on result of persister.push\n return await this.persist(filteredEnvelopes);\n }\n // Failed -- not retriable\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countFailure(duration, statusCode);\n // Count dropped items for customer SDK Stats for non-retriable status codes\n const filteredSuccessfulEnvelopes = successfulEnvelopes.filter(Boolean);\n this.customerSDKStatsMetrics?.countDroppedItems(\n filteredSuccessfulEnvelopes,\n statusCode,\n );\n }\n return this.buildExportResult({\n code: ExportResultCode.FAILED,\n });\n } else {\n // calls resultCallback(ExportResult) based on result of persister.push\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countRetry(statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, statusCode);\n }\n return await this.persist(envelopes);\n }\n } else {\n // Failed -- not retriable\n if (this.networkStatsbeatMetrics && !this.isStatsbeatSender) {\n if (statusCode) {\n this.networkStatsbeatMetrics.countFailure(duration, statusCode);\n this.customerSDKStatsMetrics?.countDroppedItems(envelopes, statusCode);\n }\n } else {\n // Handles all other status codes or client exceptions for Statsbeat\n this.incrementStatsbeatFailure();\n this.customerSDKStatsMetrics?.countDroppedItems(envelopes, DropCode.CLIENT_EXCEPTION);\n }\n return this.buildExportResult({\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.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 const redirectError = new Error(\"Circular redirect\");\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countException(redirectError);\n this.customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_EXCEPTION,\n redirectError.message,\n ExceptionType.CLIENT_EXCEPTION,\n );\n }\n return this.buildExportResult({ code: ExportResultCode.FAILED, error: redirectError });\n }\n } else if (\n restError.statusCode &&\n isRetriable(restError.statusCode) &&\n !this.isStatsbeatSender\n ) {\n this.networkStatsbeatMetrics?.countRetry(restError.statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, restError.statusCode);\n return this.persist(envelopes);\n } else if (\n restError.statusCode === 400 &&\n restError.message.includes(\"Invalid instrumentation key\")\n ) {\n // Invalid instrumentation key, shutdown statsbeat, fail silently\n this.shutdownStatsbeat();\n return { code: ExportResultCode.SUCCESS };\n } else if (\n restError.statusCode &&\n this.isStatsbeatSender &&\n isStatsbeatShutdownStatus(restError.statusCode)\n ) {\n // If the status code is a shutdown status code for statsbeat, shutdown statsbeat and fail silently\n this.incrementStatsbeatFailure();\n return { code: ExportResultCode.SUCCESS };\n }\n\n // For retriable REST errors\n if (this.isRetriableRestError(restError) && !this.isStatsbeatSender) {\n if (this.customerSDKStatsMetrics?.isTimeoutError(restError) && !this.isStatsbeatSender) {\n this.customerSDKStatsMetrics?.countRetryItems(\n envelopes,\n RetryCode.CLIENT_TIMEOUT,\n \"timeout_exception\",\n ExceptionType.TIMEOUT_EXCEPTION,\n );\n diag.error(\"Request timed out. Error message:\", restError.message);\n } else if (restError.statusCode) {\n this.networkStatsbeatMetrics?.countRetry(restError.statusCode);\n this.customerSDKStatsMetrics?.countRetryItems(envelopes, restError.statusCode);\n }\n diag.error(\n \"Retrying due to transient client side error. Error message:\",\n restError.message,\n );\n return this.persist(envelopes);\n }\n // For non-retriable REST errors or client exceptions\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countException(restError);\n this.customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_EXCEPTION,\n restError.message,\n );\n diag.error(\n \"Envelopes could not be exported and are not retriable. Error message:\",\n restError.message,\n );\n }\n return this.buildExportResult({ code: ExportResultCode.FAILED, error: restError });\n }\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 : this.buildExportResult({\n code: ExportResultCode.FAILED,\n error: new Error(\"Failed to persist envelope in disk.\"),\n });\n } catch (ex: any) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countWriteFailure();\n if (this.disableOfflineStorage && envelopes) {\n this.customerSDKStatsMetrics?.countDroppedItems(\n envelopes as Envelope[],\n DropCode.CLIENT_STORAGE_DISABLED,\n );\n }\n }\n return this.buildExportResult({ code: ExportResultCode.FAILED, error: ex });\n }\n }\n\n /**\n * Disable collection of statsbeat metrics after max failures\n */\n private incrementStatsbeatFailure(): void {\n this.statsbeatFailureCount++;\n if (this.statsbeatFailureCount > MAX_STATSBEAT_FAILURES) {\n this.shutdownStatsbeat();\n }\n }\n\n /**\n * Shutdown statsbeat metrics\n */\n private shutdownStatsbeat(): void {\n if (this.networkStatsbeatMetrics) {\n this.networkStatsbeatMetrics.shutdown();\n }\n if (this.longIntervalStatsbeatMetrics) {\n this.longIntervalStatsbeatMetrics?.shutdown();\n }\n if (this.customerSDKStatsMetrics) {\n this.customerSDKStatsMetrics.shutdown();\n }\n this.statsbeatFailureCount = 0;\n }\n\n private async sendFirstPersistedFile(): Promise<void> {\n const envelopes = (await this.persister.shift()) as Envelope[] | null;\n try {\n if (envelopes) {\n await this.send(envelopes);\n }\n } catch (err: any) {\n if (!this.isStatsbeatSender) {\n this.networkStatsbeatMetrics?.countReadFailure();\n }\n diag.warn(`Failed to fetch persisted file`, err);\n }\n }\n\n private isRetriableRestError(error: RestError): boolean {\n const restErrorTypes: string[] = Object.values(RetriableRestErrorTypes);\n if (error && error.code && restErrorTypes.includes(error.code)) {\n return true;\n }\n return false;\n }\n\n // Silence noisy failures from statsbeat OTel metric readers unless logging is explicitly enabled\n private buildExportResult(result: ExportResult): ExportResult {\n const shouldSurfaceStatsbeatFailures = !!process.env[ENV_APPLICATIONINSIGHTS_SDK_STATS_LOGGING];\n if (this.isStatsbeatSender && result.code === ExportResultCode.FAILED) {\n return shouldSurfaceStatsbeatFailures ? result : { code: ExportResultCode.SUCCESS };\n }\n return result;\n }\n}\n"]}
|
|
@@ -34,4 +34,19 @@ export declare class FileSystemPersist implements PersistentStorage {
|
|
|
34
34
|
private _storeToDisk;
|
|
35
35
|
private _fileCleanupTask;
|
|
36
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Return the deterministic local storage path for a given instrumentation key.
|
|
39
|
+
*
|
|
40
|
+
* On shared Linux hosts the first user to create `/tmp/Microsoft/AzureMonitor` can
|
|
41
|
+
* block others because the directory inherits that user's `umask`. This is avoided by
|
|
42
|
+
* inserting a hash of the instrumentation key, user name, process name, and
|
|
43
|
+
* application directory, giving each user their own subdirectory, e.g.
|
|
44
|
+
* `/tmp/Microsoft-AzureMonitor-1234...../opentelemetry-nodejs-<ikey>`.
|
|
45
|
+
*
|
|
46
|
+
* @param instrumentationKey - Application Insights instrumentation key.
|
|
47
|
+
* @param storageDirectory - Optional custom storage directory path. If not provided, system temp directory is used.
|
|
48
|
+
* @returns Absolute path to the storage directory.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
export declare function getStorageDirectory(instrumentationKey: string, storageDirectory: string | undefined): string;
|
|
37
52
|
//# sourceMappingURL=fileSystemPersist.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSystemPersist.d.ts","sourceRoot":"","sources":["../../../../../src/platform/nodejs/persist/fileSystemPersist.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fileSystemPersist.d.ts","sourceRoot":"","sources":["../../../../../src/platform/nodejs/persist/fileSystemPersist.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAG3D,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAC;AAEtE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+CAA+C,CAAC;AAI7F;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,iBAAiB;IAevD,OAAO,CAAC,QAAQ,CAAC;IACjB,OAAO,CAAC,wBAAwB,CAAC;IAfnC,MAAM,CAAC,cAAc,SAA2B;IAChD,MAAM,CAAC,eAAe,SAAc;IAEpC,oBAAoB,SAA2B;IAC/C,cAAc,SAAkB;IAChC,cAAc,EAAE,MAAM,CAAc;IAEpC,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,mBAAmB,CAAS;gBAGlC,kBAAkB,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,2BAA2B,YAAA,EACtC,wBAAwB,CAAC,EAAE,uBAAuB,YAAA;IAuC5D,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBlC,KAAK,IAAI,OAAO,CAAC,OAAO,CAAC;IAkB/B;;;OAGG;YACW,mBAAmB;IA8BjC;;;;;OAKG;YACW,YAAY;YAwDZ,gBAAgB;CA+B/B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,kBAAkB,EAAE,MAAM,EAC1B,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,CA+CR"}
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
// Licensed under the MIT License.
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.FileSystemPersist = void 0;
|
|
6
|
+
exports.getStorageDirectory = getStorageDirectory;
|
|
6
7
|
const node_os_1 = require("node:os");
|
|
7
8
|
const node_path_1 = require("node:path");
|
|
9
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
10
|
const api_1 = require("@opentelemetry/api");
|
|
9
11
|
const fileAccessControl_js_1 = require("./fileAccessControl.js");
|
|
10
12
|
const fileSystemHelpers_js_1 = require("./fileSystemHelpers.js");
|
|
@@ -17,7 +19,7 @@ const types_js_1 = require("../../../export/statsbeat/types.js");
|
|
|
17
19
|
class FileSystemPersist {
|
|
18
20
|
_options;
|
|
19
21
|
_customerSDKStatsMetrics;
|
|
20
|
-
static TEMPDIR_PREFIX = "
|
|
22
|
+
static TEMPDIR_PREFIX = "opentelemetry-nodejs-";
|
|
21
23
|
static FILENAME_SUFFIX = ".ai.json";
|
|
22
24
|
fileRetemptionPeriod = 2 * 24 * 60 * 60 * 1000; // 2 days
|
|
23
25
|
cleanupTimeOut = 60 * 60 * 1000; // 1 hour
|
|
@@ -45,7 +47,7 @@ class FileSystemPersist {
|
|
|
45
47
|
api_1.diag.error(`No instrumentation key was provided to FileSystemPersister. Files will not be persisted`);
|
|
46
48
|
}
|
|
47
49
|
if (this._enabled) {
|
|
48
|
-
this._tempDirectory = (
|
|
50
|
+
this._tempDirectory = getStorageDirectory(this._instrumentationKey, this._options?.storageDirectory);
|
|
49
51
|
// Starts file cleanup task
|
|
50
52
|
if (!this._fileCleanupTimer) {
|
|
51
53
|
this._fileCleanupTimer = setTimeout(() => {
|
|
@@ -202,4 +204,65 @@ class FileSystemPersist {
|
|
|
202
204
|
}
|
|
203
205
|
}
|
|
204
206
|
exports.FileSystemPersist = FileSystemPersist;
|
|
207
|
+
/**
|
|
208
|
+
* Return the deterministic local storage path for a given instrumentation key.
|
|
209
|
+
*
|
|
210
|
+
* On shared Linux hosts the first user to create `/tmp/Microsoft/AzureMonitor` can
|
|
211
|
+
* block others because the directory inherits that user's `umask`. This is avoided by
|
|
212
|
+
* inserting a hash of the instrumentation key, user name, process name, and
|
|
213
|
+
* application directory, giving each user their own subdirectory, e.g.
|
|
214
|
+
* `/tmp/Microsoft-AzureMonitor-1234...../opentelemetry-nodejs-<ikey>`.
|
|
215
|
+
*
|
|
216
|
+
* @param instrumentationKey - Application Insights instrumentation key.
|
|
217
|
+
* @param storageDirectory - Optional custom storage directory path. If not provided, system temp directory is used.
|
|
218
|
+
* @returns Absolute path to the storage directory.
|
|
219
|
+
* @internal
|
|
220
|
+
*/
|
|
221
|
+
function getStorageDirectory(instrumentationKey, storageDirectory) {
|
|
222
|
+
let userSegment;
|
|
223
|
+
let processName;
|
|
224
|
+
let applicationDirectory;
|
|
225
|
+
try {
|
|
226
|
+
const user = (0, node_os_1.userInfo)();
|
|
227
|
+
userSegment = user.username;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
userSegment = "";
|
|
231
|
+
}
|
|
232
|
+
if (process.title.length > 0) {
|
|
233
|
+
processName = process.title;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
processName = "";
|
|
237
|
+
}
|
|
238
|
+
const applicationDir = (0, node_path_1.dirname)(process.cwd() || process.argv[1]);
|
|
239
|
+
if (applicationDir) {
|
|
240
|
+
applicationDirectory = applicationDir;
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
applicationDirectory = "";
|
|
244
|
+
}
|
|
245
|
+
const hash_input = `${instrumentationKey}|${userSegment}|${processName}|${applicationDirectory}`;
|
|
246
|
+
let subDirectory;
|
|
247
|
+
try {
|
|
248
|
+
subDirectory = (0, node_crypto_1.createHash)("sha256").update(hash_input).digest("hex");
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
let hash = 5381;
|
|
252
|
+
for (let i = 0; i < hash_input.length; i++) {
|
|
253
|
+
const char = hash_input.charCodeAt(i);
|
|
254
|
+
hash = (hash << 5) + hash + char;
|
|
255
|
+
hash = hash & hash;
|
|
256
|
+
}
|
|
257
|
+
subDirectory = Math.abs(hash).toString(16);
|
|
258
|
+
}
|
|
259
|
+
let sharedRoot;
|
|
260
|
+
if (storageDirectory) {
|
|
261
|
+
sharedRoot = storageDirectory;
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
sharedRoot = (0, node_os_1.tmpdir)();
|
|
265
|
+
}
|
|
266
|
+
return (0, node_path_1.join)(sharedRoot, "Microsoft-AzureMonitor-" + subDirectory, FileSystemPersist.TEMPDIR_PREFIX + instrumentationKey);
|
|
267
|
+
}
|
|
205
268
|
//# sourceMappingURL=fileSystemPersist.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSystemPersist.js","sourceRoot":"","sources":["../../../../../src/platform/nodejs/persist/fileSystemPersist.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { tmpdir } from \"node:os\";\nimport { basename, join } from \"node:path\";\nimport { diag } from \"@opentelemetry/api\";\nimport type { PersistentStorage } from \"../../../types.js\";\nimport { FileAccessControl } from \"./fileAccessControl.js\";\nimport { confirmDirExists, getShallowDirectorySize } from \"./fileSystemHelpers.js\";\nimport type { AzureMonitorExporterOptions } from \"../../../config.js\";\nimport { readdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\";\nimport type { CustomerSDKStatsMetrics } from \"../../../export/statsbeat/customerSDKStats.js\";\nimport { DropCode, ExceptionType } from \"../../../export/statsbeat/types.js\";\nimport type { TelemetryItem as Envelope } from \"../../../generated/index.js\";\n\n/**\n * File system persist class.\n * @internal\n */\nexport class FileSystemPersist implements PersistentStorage {\n static TEMPDIR_PREFIX = \"ot-azure-exporter-\";\n static FILENAME_SUFFIX = \".ai.json\";\n\n fileRetemptionPeriod = 2 * 24 * 60 * 60 * 1000; // 2 days\n cleanupTimeOut = 60 * 60 * 1000; // 1 hour\n maxBytesOnDisk: number = 50_000_000; // ~50MB\n\n private _enabled: boolean;\n private _tempDirectory: string = \"\";\n private _fileCleanupTimer: NodeJS.Timeout | null = null;\n private _instrumentationKey: string;\n\n constructor(\n instrumentationKey: string,\n private _options?: AzureMonitorExporterOptions,\n private _customerSDKStatsMetrics?: CustomerSDKStatsMetrics,\n ) {\n this._instrumentationKey = instrumentationKey;\n if (this._options?.disableOfflineStorage) {\n this._enabled = false;\n return;\n }\n this._enabled = true;\n FileAccessControl.checkFileProtection();\n\n if (!FileAccessControl.OS_PROVIDES_FILE_PROTECTION) {\n this._enabled = false;\n diag.error(\n \"Sufficient file protection capabilities were not detected. Files will not be persisted\",\n );\n }\n\n if (!this._instrumentationKey) {\n this._enabled = false;\n diag.error(\n `No instrumentation key was provided to FileSystemPersister. Files will not be persisted`,\n );\n }\n if (this._enabled) {\n this._tempDirectory = join(\n this._options?.storageDirectory || tmpdir(),\n \"Microsoft\",\n \"AzureMonitor\",\n FileSystemPersist.TEMPDIR_PREFIX + this._instrumentationKey,\n );\n\n // Starts file cleanup task\n if (!this._fileCleanupTimer) {\n this._fileCleanupTimer = setTimeout(() => {\n this._fileCleanupTask();\n }, this.cleanupTimeOut);\n this._fileCleanupTimer.unref();\n }\n }\n }\n\n push(value: unknown[]): Promise<boolean> {\n if (this._enabled) {\n diag.debug(\"Pushing value to persistent storage\", value.toString());\n return this._storeToDisk(JSON.stringify(value), value as Envelope[]);\n }\n // Only return a false promise if the SDK isn't set to disable offline storage\n if (!this._options?.disableOfflineStorage) {\n return new Promise((resolve) => {\n resolve(false);\n });\n }\n return new Promise((resolve) => {\n resolve(true);\n });\n }\n\n async shift(): Promise<unknown> {\n if (this._enabled) {\n diag.debug(\"Searching for filesystem persisted files\");\n try {\n const buffer = await this._getFirstFileOnDisk();\n if (buffer) {\n return JSON.parse(buffer.toString(\"utf8\"));\n }\n } catch (e: any) {\n diag.debug(\"Failed to read persisted file\", e);\n }\n return null;\n }\n return new Promise((resolve) => {\n resolve(null);\n });\n }\n\n /**\n * Check for temp telemetry files\n * reads the first file if exist, deletes it and tries to send its load\n */\n private async _getFirstFileOnDisk(): Promise<Buffer | null> {\n try {\n const stats = await stat(this._tempDirectory);\n if (stats.isDirectory()) {\n const origFiles = await readdir(this._tempDirectory);\n const files = origFiles.filter((f) =>\n basename(f).includes(FileSystemPersist.FILENAME_SUFFIX),\n );\n if (files.length === 0) {\n return null;\n } else {\n const firstFile = files[0];\n const filePath = join(this._tempDirectory, firstFile);\n const payload = await readFile(filePath);\n // delete the file first to prevent double sending\n await unlink(filePath);\n return payload;\n }\n }\n return null;\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n // File does not exist -- return null instead of throwing\n return null;\n } else {\n throw e;\n }\n }\n }\n\n /**\n * Stores telemetry data to disk.\n * @param payload - The telemetry data to store.\n * @param envelopeLength -The length of the telemetry envelope.\n * @returns A promise that resolves to true if the data was stored successfully, false otherwise.\n */\n private async _storeToDisk(payload: string, envelopes: Envelope[]): Promise<boolean> {\n try {\n await confirmDirExists(this._tempDirectory);\n } catch (error: any) {\n // Check if error is due to permission/readonly issues\n if (error?.code === \"EACCES\" || error?.code === \"EPERM\") {\n this._customerSDKStatsMetrics?.countDroppedItems(envelopes, DropCode.CLIENT_READONLY);\n diag.warn(\n `Permission denied while checking/creating directory: ${this._tempDirectory}`,\n error?.message,\n );\n } else {\n diag.warn(`Error while checking/creating directory: `, error && error.message);\n }\n return false;\n }\n\n try {\n const size = await getShallowDirectorySize(this._tempDirectory);\n if (size > this.maxBytesOnDisk) {\n // If the directory size exceeds the max limit, we send customer SDK Stats and warn the user\n this._customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_PERSISTENCE_CAPACITY,\n );\n diag.warn(\n `Not saving data due to max size limit being met. Directory size in bytes is: ${size}`,\n );\n return false;\n }\n } catch (error: any) {\n diag.warn(`Error while checking size of persistence directory: `, error && error.message);\n return false;\n }\n\n const fileName = `${new Date().getTime()}${FileSystemPersist.FILENAME_SUFFIX}`;\n const fileFullPath = join(this._tempDirectory, fileName);\n\n // Mode 600 is w/r for creator and no read access for others\n diag.info(`saving data to disk at: ${fileFullPath}`);\n try {\n await writeFile(fileFullPath, payload, { mode: 0o600 });\n } catch (writeError: any) {\n // If the envelopes cannot be written to disk, we send customer SDK Stats and warn the user\n this._customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_EXCEPTION,\n writeError?.message,\n ExceptionType.STORAGE_EXCEPTION,\n );\n diag.warn(`Error writing file to persistent file storage`, writeError);\n return false;\n }\n return true;\n }\n\n private async _fileCleanupTask(): Promise<boolean> {\n try {\n const stats = await stat(this._tempDirectory);\n if (stats.isDirectory()) {\n const origFiles = await readdir(this._tempDirectory);\n const files = origFiles.filter((f) =>\n basename(f).includes(FileSystemPersist.FILENAME_SUFFIX),\n );\n if (files.length === 0) {\n return false;\n } else {\n files.forEach(async (file) => {\n // Check expiration\n const fileCreationDate: Date = new Date(\n parseInt(file.split(FileSystemPersist.FILENAME_SUFFIX)[0]),\n );\n const expired = new Date(+new Date() - this.fileRetemptionPeriod) > fileCreationDate;\n if (expired) {\n const filePath = join(this._tempDirectory, file);\n await unlink(filePath);\n }\n });\n return true;\n }\n }\n return false;\n } catch (error: any) {\n diag.info(`Failed cleanup of persistent file storage expired files`, error);\n return false;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"fileSystemPersist.js","sourceRoot":"","sources":["../../../../../src/platform/nodejs/persist/fileSystemPersist.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { tmpdir, userInfo } from \"node:os\";\nimport { basename, join, dirname } from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { diag } from \"@opentelemetry/api\";\nimport type { PersistentStorage } from \"../../../types.js\";\nimport { FileAccessControl } from \"./fileAccessControl.js\";\nimport { confirmDirExists, getShallowDirectorySize } from \"./fileSystemHelpers.js\";\nimport type { AzureMonitorExporterOptions } from \"../../../config.js\";\nimport { readdir, readFile, stat, unlink, writeFile } from \"node:fs/promises\";\nimport type { CustomerSDKStatsMetrics } from \"../../../export/statsbeat/customerSDKStats.js\";\nimport { DropCode, ExceptionType } from \"../../../export/statsbeat/types.js\";\nimport type { TelemetryItem as Envelope } from \"../../../generated/index.js\";\n\n/**\n * File system persist class.\n * @internal\n */\nexport class FileSystemPersist implements PersistentStorage {\n static TEMPDIR_PREFIX = \"opentelemetry-nodejs-\";\n static FILENAME_SUFFIX = \".ai.json\";\n\n fileRetemptionPeriod = 2 * 24 * 60 * 60 * 1000; // 2 days\n cleanupTimeOut = 60 * 60 * 1000; // 1 hour\n maxBytesOnDisk: number = 50_000_000; // ~50MB\n\n private _enabled: boolean;\n private _tempDirectory: string = \"\";\n private _fileCleanupTimer: NodeJS.Timeout | null = null;\n private _instrumentationKey: string;\n\n constructor(\n instrumentationKey: string,\n private _options?: AzureMonitorExporterOptions,\n private _customerSDKStatsMetrics?: CustomerSDKStatsMetrics,\n ) {\n this._instrumentationKey = instrumentationKey;\n if (this._options?.disableOfflineStorage) {\n this._enabled = false;\n return;\n }\n this._enabled = true;\n FileAccessControl.checkFileProtection();\n\n if (!FileAccessControl.OS_PROVIDES_FILE_PROTECTION) {\n this._enabled = false;\n diag.error(\n \"Sufficient file protection capabilities were not detected. Files will not be persisted\",\n );\n }\n\n if (!this._instrumentationKey) {\n this._enabled = false;\n diag.error(\n `No instrumentation key was provided to FileSystemPersister. Files will not be persisted`,\n );\n }\n if (this._enabled) {\n this._tempDirectory = getStorageDirectory(\n this._instrumentationKey,\n this._options?.storageDirectory,\n );\n\n // Starts file cleanup task\n if (!this._fileCleanupTimer) {\n this._fileCleanupTimer = setTimeout(() => {\n this._fileCleanupTask();\n }, this.cleanupTimeOut);\n this._fileCleanupTimer.unref();\n }\n }\n }\n\n push(value: unknown[]): Promise<boolean> {\n if (this._enabled) {\n diag.debug(\"Pushing value to persistent storage\", value.toString());\n return this._storeToDisk(JSON.stringify(value), value as Envelope[]);\n }\n // Only return a false promise if the SDK isn't set to disable offline storage\n if (!this._options?.disableOfflineStorage) {\n return new Promise((resolve) => {\n resolve(false);\n });\n }\n return new Promise((resolve) => {\n resolve(true);\n });\n }\n\n async shift(): Promise<unknown> {\n if (this._enabled) {\n diag.debug(\"Searching for filesystem persisted files\");\n try {\n const buffer = await this._getFirstFileOnDisk();\n if (buffer) {\n return JSON.parse(buffer.toString(\"utf8\"));\n }\n } catch (e: any) {\n diag.debug(\"Failed to read persisted file\", e);\n }\n return null;\n }\n return new Promise((resolve) => {\n resolve(null);\n });\n }\n\n /**\n * Check for temp telemetry files\n * reads the first file if exist, deletes it and tries to send its load\n */\n private async _getFirstFileOnDisk(): Promise<Buffer | null> {\n try {\n const stats = await stat(this._tempDirectory);\n if (stats.isDirectory()) {\n const origFiles = await readdir(this._tempDirectory);\n const files = origFiles.filter((f) =>\n basename(f).includes(FileSystemPersist.FILENAME_SUFFIX),\n );\n if (files.length === 0) {\n return null;\n } else {\n const firstFile = files[0];\n const filePath = join(this._tempDirectory, firstFile);\n const payload = await readFile(filePath);\n // delete the file first to prevent double sending\n await unlink(filePath);\n return payload;\n }\n }\n return null;\n } catch (e: any) {\n if (e.code === \"ENOENT\") {\n // File does not exist -- return null instead of throwing\n return null;\n } else {\n throw e;\n }\n }\n }\n\n /**\n * Stores telemetry data to disk.\n * @param payload - The telemetry data to store.\n * @param envelopeLength -The length of the telemetry envelope.\n * @returns A promise that resolves to true if the data was stored successfully, false otherwise.\n */\n private async _storeToDisk(payload: string, envelopes: Envelope[]): Promise<boolean> {\n try {\n await confirmDirExists(this._tempDirectory);\n } catch (error: any) {\n // Check if error is due to permission/readonly issues\n if (error?.code === \"EACCES\" || error?.code === \"EPERM\") {\n this._customerSDKStatsMetrics?.countDroppedItems(envelopes, DropCode.CLIENT_READONLY);\n diag.warn(\n `Permission denied while checking/creating directory: ${this._tempDirectory}`,\n error?.message,\n );\n } else {\n diag.warn(`Error while checking/creating directory: `, error && error.message);\n }\n return false;\n }\n\n try {\n const size = await getShallowDirectorySize(this._tempDirectory);\n if (size > this.maxBytesOnDisk) {\n // If the directory size exceeds the max limit, we send customer SDK Stats and warn the user\n this._customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_PERSISTENCE_CAPACITY,\n );\n diag.warn(\n `Not saving data due to max size limit being met. Directory size in bytes is: ${size}`,\n );\n return false;\n }\n } catch (error: any) {\n diag.warn(`Error while checking size of persistence directory: `, error && error.message);\n return false;\n }\n\n const fileName = `${new Date().getTime()}${FileSystemPersist.FILENAME_SUFFIX}`;\n const fileFullPath = join(this._tempDirectory, fileName);\n\n // Mode 600 is w/r for creator and no read access for others\n diag.info(`saving data to disk at: ${fileFullPath}`);\n try {\n await writeFile(fileFullPath, payload, { mode: 0o600 });\n } catch (writeError: any) {\n // If the envelopes cannot be written to disk, we send customer SDK Stats and warn the user\n this._customerSDKStatsMetrics?.countDroppedItems(\n envelopes,\n DropCode.CLIENT_EXCEPTION,\n writeError?.message,\n ExceptionType.STORAGE_EXCEPTION,\n );\n diag.warn(`Error writing file to persistent file storage`, writeError);\n return false;\n }\n return true;\n }\n\n private async _fileCleanupTask(): Promise<boolean> {\n try {\n const stats = await stat(this._tempDirectory);\n if (stats.isDirectory()) {\n const origFiles = await readdir(this._tempDirectory);\n const files = origFiles.filter((f) =>\n basename(f).includes(FileSystemPersist.FILENAME_SUFFIX),\n );\n if (files.length === 0) {\n return false;\n } else {\n files.forEach(async (file) => {\n // Check expiration\n const fileCreationDate: Date = new Date(\n parseInt(file.split(FileSystemPersist.FILENAME_SUFFIX)[0]),\n );\n const expired = new Date(+new Date() - this.fileRetemptionPeriod) > fileCreationDate;\n if (expired) {\n const filePath = join(this._tempDirectory, file);\n await unlink(filePath);\n }\n });\n return true;\n }\n }\n return false;\n } catch (error: any) {\n diag.info(`Failed cleanup of persistent file storage expired files`, error);\n return false;\n }\n }\n}\n\n/**\n * Return the deterministic local storage path for a given instrumentation key.\n *\n * On shared Linux hosts the first user to create `/tmp/Microsoft/AzureMonitor` can\n * block others because the directory inherits that user's `umask`. This is avoided by\n * inserting a hash of the instrumentation key, user name, process name, and\n * application directory, giving each user their own subdirectory, e.g.\n * `/tmp/Microsoft-AzureMonitor-1234...../opentelemetry-nodejs-<ikey>`.\n *\n * @param instrumentationKey - Application Insights instrumentation key.\n * @param storageDirectory - Optional custom storage directory path. If not provided, system temp directory is used.\n * @returns Absolute path to the storage directory.\n * @internal\n */\nexport function getStorageDirectory(\n instrumentationKey: string,\n storageDirectory: string | undefined,\n): string {\n let userSegment: string;\n let processName: string;\n let applicationDirectory: string;\n try {\n const user = userInfo();\n userSegment = user.username;\n } catch (error) {\n userSegment = \"\";\n }\n if (process.title.length > 0) {\n processName = process.title;\n } else {\n processName = \"\";\n }\n const applicationDir = dirname(process.cwd() || process.argv[1]);\n if (applicationDir) {\n applicationDirectory = applicationDir;\n } else {\n applicationDirectory = \"\";\n }\n const hash_input = `${instrumentationKey}|${userSegment}|${processName}|${applicationDirectory}`;\n\n let subDirectory: string;\n try {\n subDirectory = createHash(\"sha256\").update(hash_input).digest(\"hex\");\n } catch (error) {\n let hash = 5381;\n for (let i = 0; i < hash_input.length; i++) {\n const char = hash_input.charCodeAt(i);\n hash = (hash << 5) + hash + char;\n hash = hash & hash;\n }\n subDirectory = Math.abs(hash).toString(16);\n }\n\n let sharedRoot: string;\n if (storageDirectory) {\n sharedRoot = storageDirectory;\n } else {\n sharedRoot = tmpdir();\n }\n return join(\n sharedRoot,\n \"Microsoft-AzureMonitor-\" + subDirectory,\n FileSystemPersist.TEMPDIR_PREFIX + instrumentationKey,\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Tags } from "../types.js";
|
|
2
2
|
import type { TelemetryItem as Envelope } from "../generated/index.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type Resource } from "@opentelemetry/resources";
|
|
4
4
|
import type { Attributes, HrTime } from "@opentelemetry/api";
|
|
5
5
|
import type { AnyValue } from "@opentelemetry/api-logs";
|
|
6
6
|
export declare function hrTimeToDate(hrTime: HrTime): Date;
|
|
@@ -8,7 +8,7 @@ export declare function createTagsFromResource(resource: Resource): Tags;
|
|
|
8
8
|
export declare function isSqlDB(dbSystem: string): boolean;
|
|
9
9
|
export declare function getUrl(attributes: Attributes): string;
|
|
10
10
|
export declare function getDependencyTarget(attributes: Attributes): string;
|
|
11
|
-
export declare function createResourceMetricEnvelope(resource: Resource, instrumentationKey: string): Envelope | undefined;
|
|
11
|
+
export declare function createResourceMetricEnvelope(resource: Resource, instrumentationKey: string, applicationId?: string): Envelope | undefined;
|
|
12
12
|
export declare function serializeAttribute(value: AnyValue): string;
|
|
13
13
|
export declare function shouldCreateResourceMetric(): boolean;
|
|
14
14
|
export declare function isSyntheticSource(attributes: Attributes): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/utils/common.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAmC,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAe,MAAM,uBAAuB,CAAC;AAEpF,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/utils/common.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAmC,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,IAAI,QAAQ,EAAe,MAAM,uBAAuB,CAAC;AAEpF,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAgBxD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEjD;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAkB/D;AAmED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAYjD;AAED,wBAAgB,MAAM,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAkCrD;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAqBlE;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,QAAQ,EAClB,kBAAkB,EAAE,MAAM,EAC1B,aAAa,CAAC,EAAE,MAAM,GACrB,QAAQ,GAAG,SAAS,CA8CtB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAsB1D;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAEjE"}
|
|
@@ -26,17 +26,18 @@ function hrTimeToDate(hrTime) {
|
|
|
26
26
|
function createTagsFromResource(resource) {
|
|
27
27
|
const context = (0, index_js_1.getInstance)();
|
|
28
28
|
const tags = { ...context.tags };
|
|
29
|
-
|
|
29
|
+
const attributes = resource?.attributes;
|
|
30
|
+
if (attributes) {
|
|
30
31
|
tags[index_js_2.KnownContextTagKeys.AiCloudRole] = getCloudRole(resource);
|
|
31
32
|
tags[index_js_2.KnownContextTagKeys.AiCloudRoleInstance] = getCloudRoleInstance(resource);
|
|
32
|
-
if (
|
|
33
|
-
tags[index_js_2.KnownContextTagKeys.AiDeviceId] = String(
|
|
33
|
+
if (attributes[semantic_conventions_1.SEMRESATTRS_DEVICE_ID]) {
|
|
34
|
+
tags[index_js_2.KnownContextTagKeys.AiDeviceId] = String(attributes[semantic_conventions_1.SEMRESATTRS_DEVICE_ID]);
|
|
34
35
|
}
|
|
35
|
-
if (
|
|
36
|
-
tags[index_js_2.KnownContextTagKeys.AiDeviceModel] = String(
|
|
36
|
+
if (attributes[semantic_conventions_1.SEMRESATTRS_DEVICE_MODEL_NAME]) {
|
|
37
|
+
tags[index_js_2.KnownContextTagKeys.AiDeviceModel] = String(attributes[semantic_conventions_1.SEMRESATTRS_DEVICE_MODEL_NAME]);
|
|
37
38
|
}
|
|
38
|
-
if (
|
|
39
|
-
tags[index_js_2.KnownContextTagKeys.AiApplicationVer] = String(
|
|
39
|
+
if (attributes[semantic_conventions_1.SEMRESATTRS_SERVICE_VERSION]) {
|
|
40
|
+
tags[index_js_2.KnownContextTagKeys.AiApplicationVer] = String(attributes[semantic_conventions_1.SEMRESATTRS_SERVICE_VERSION]);
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
return tags;
|
|
@@ -182,17 +183,21 @@ function getDependencyTarget(attributes) {
|
|
|
182
183
|
}
|
|
183
184
|
return "";
|
|
184
185
|
}
|
|
185
|
-
function createResourceMetricEnvelope(resource, instrumentationKey) {
|
|
186
|
-
|
|
186
|
+
function createResourceMetricEnvelope(resource, instrumentationKey, applicationId) {
|
|
187
|
+
const attributes = resource.attributes;
|
|
188
|
+
if (attributes) {
|
|
187
189
|
const tags = createTagsFromResource(resource);
|
|
188
190
|
const resourceAttributes = {};
|
|
189
|
-
|
|
191
|
+
if (applicationId && !attributes[Constants_js_1.APPLICATION_ID_RESOURCE_KEY]) {
|
|
192
|
+
resourceAttributes[Constants_js_1.APPLICATION_ID_RESOURCE_KEY] = applicationId;
|
|
193
|
+
}
|
|
194
|
+
for (const key of Object.keys(attributes)) {
|
|
190
195
|
// Avoid duplication ignoring fields already mapped.
|
|
191
196
|
if (!(key.startsWith("_MS.") ||
|
|
192
197
|
key === semantic_conventions_1.ATTR_TELEMETRY_SDK_VERSION ||
|
|
193
198
|
key === semantic_conventions_1.ATTR_TELEMETRY_SDK_LANGUAGE ||
|
|
194
199
|
key === semantic_conventions_1.ATTR_TELEMETRY_SDK_NAME)) {
|
|
195
|
-
resourceAttributes[key] =
|
|
200
|
+
resourceAttributes[key] = attributes[key];
|
|
196
201
|
}
|
|
197
202
|
}
|
|
198
203
|
// Only send event when resource attributes are available
|