@azure/monitor-opentelemetry-exporter 1.0.0-beta.16 → 1.0.0-beta.17
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/index.js +428 -376
- package/dist-esm/src/Declarations/Contracts/Constants.js.map +1 -1
- package/dist-esm/src/export/base.js +10 -4
- package/dist-esm/src/export/base.js.map +1 -1
- package/dist-esm/src/export/log.js +10 -4
- package/dist-esm/src/export/log.js.map +1 -1
- package/dist-esm/src/export/metric.js +11 -5
- package/dist-esm/src/export/metric.js.map +1 -1
- package/dist-esm/src/export/statsbeat/longIntervalStatsbeatMetrics.js +53 -54
- package/dist-esm/src/export/statsbeat/longIntervalStatsbeatMetrics.js.map +1 -1
- package/dist-esm/src/export/statsbeat/networkStatsbeatMetrics.js +101 -104
- package/dist-esm/src/export/statsbeat/networkStatsbeatMetrics.js.map +1 -1
- package/dist-esm/src/export/statsbeat/statsbeatExporter.js +7 -2
- package/dist-esm/src/export/statsbeat/statsbeatExporter.js.map +1 -1
- package/dist-esm/src/export/statsbeat/statsbeatMetrics.js +20 -20
- package/dist-esm/src/export/statsbeat/statsbeatMetrics.js.map +1 -1
- package/dist-esm/src/export/statsbeat/types.js +8 -6
- package/dist-esm/src/export/statsbeat/types.js.map +1 -1
- package/dist-esm/src/export/trace.js +14 -8
- package/dist-esm/src/export/trace.js.map +1 -1
- package/dist-esm/src/generated/applicationInsightsClient.js +1 -1
- package/dist-esm/src/generated/applicationInsightsClient.js.map +1 -1
- package/dist-esm/src/platform/nodejs/baseSender.js +52 -52
- package/dist-esm/src/platform/nodejs/baseSender.js.map +1 -1
- package/dist-esm/src/platform/nodejs/context/context.js +3 -3
- package/dist-esm/src/platform/nodejs/context/context.js.map +1 -1
- package/dist-esm/src/platform/nodejs/httpSender.js +22 -21
- package/dist-esm/src/platform/nodejs/httpSender.js.map +1 -1
- package/dist-esm/src/platform/nodejs/persist/fileAccessControl.js +5 -5
- package/dist-esm/src/platform/nodejs/persist/fileAccessControl.js.map +1 -1
- package/dist-esm/src/sampling.js +17 -17
- package/dist-esm/src/sampling.js.map +1 -1
- package/dist-esm/src/utils/common.js +5 -5
- package/dist-esm/src/utils/common.js.map +1 -1
- package/dist-esm/src/utils/connectionStringParser.js +11 -1
- package/dist-esm/src/utils/connectionStringParser.js.map +1 -1
- package/dist-esm/src/utils/constants/applicationinsights.js +1 -1
- package/dist-esm/src/utils/constants/applicationinsights.js.map +1 -1
- package/dist-esm/src/utils/logUtils.js +8 -8
- package/dist-esm/src/utils/logUtils.js.map +1 -1
- package/dist-esm/src/utils/metricUtils.js +6 -6
- package/dist-esm/src/utils/metricUtils.js.map +1 -1
- package/dist-esm/src/utils/spanUtils.js +22 -21
- package/dist-esm/src/utils/spanUtils.js.map +1 -1
- package/package.json +22 -21
- package/types/monitor-opentelemetry-exporter.d.ts +16 -12
package/dist/index.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
var sdkTraceBase = require('@opentelemetry/sdk-trace-base');
|
|
6
4
|
var api = require('@opentelemetry/api');
|
|
7
5
|
var core = require('@opentelemetry/core');
|
|
@@ -16,10 +14,7 @@ var child_process = require('child_process');
|
|
|
16
14
|
var util = require('util');
|
|
17
15
|
var coreClient = require('@azure/core-client');
|
|
18
16
|
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
function _interopNamespace(e) {
|
|
22
|
-
if (e && e.__esModule) return e;
|
|
17
|
+
function _interopNamespaceDefault(e) {
|
|
23
18
|
var n = Object.create(null);
|
|
24
19
|
if (e) {
|
|
25
20
|
Object.keys(e).forEach(function (k) {
|
|
@@ -32,18 +27,16 @@ function _interopNamespace(e) {
|
|
|
32
27
|
}
|
|
33
28
|
});
|
|
34
29
|
}
|
|
35
|
-
n
|
|
30
|
+
n.default = e;
|
|
36
31
|
return Object.freeze(n);
|
|
37
32
|
}
|
|
38
33
|
|
|
39
|
-
var
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
var
|
|
44
|
-
var
|
|
45
|
-
var child_process__namespace = /*#__PURE__*/_interopNamespace(child_process);
|
|
46
|
-
var coreClient__namespace = /*#__PURE__*/_interopNamespace(coreClient);
|
|
34
|
+
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os$1);
|
|
35
|
+
var coreRestPipeline__namespace = /*#__PURE__*/_interopNamespaceDefault(coreRestPipeline);
|
|
36
|
+
var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs);
|
|
37
|
+
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
|
38
|
+
var child_process__namespace = /*#__PURE__*/_interopNamespaceDefault(child_process);
|
|
39
|
+
var coreClient__namespace = /*#__PURE__*/_interopNamespaceDefault(coreClient);
|
|
47
40
|
|
|
48
41
|
// Copyright (c) Microsoft Corporation.
|
|
49
42
|
// Licensed under the MIT license.
|
|
@@ -66,7 +59,7 @@ const TIME_SINCE_ENQUEUED = "timeSinceEnqueued";
|
|
|
66
59
|
* AzureMonitorTraceExporter version.
|
|
67
60
|
* @internal
|
|
68
61
|
*/
|
|
69
|
-
const packageVersion = "1.0.0-beta.
|
|
62
|
+
const packageVersion = "1.0.0-beta.17";
|
|
70
63
|
var DependencyTypes;
|
|
71
64
|
(function (DependencyTypes) {
|
|
72
65
|
DependencyTypes["InProc"] = "InProc";
|
|
@@ -97,26 +90,26 @@ const ApplicationInsightsEventBaseType = "EventData";
|
|
|
97
90
|
class ApplicationInsightsSampler {
|
|
98
91
|
/**
|
|
99
92
|
* Initializes a new instance of the ApplicationInsightsSampler class.
|
|
100
|
-
* @param samplingRatio Value in the range [0,1], 1 meaning all data will sampled and 0 all Tracing data will be sampled out.
|
|
93
|
+
* @param samplingRatio - Value in the range [0,1], 1 meaning all data will sampled and 0 all Tracing data will be sampled out.
|
|
101
94
|
*/
|
|
102
95
|
constructor(samplingRatio = 1) {
|
|
103
|
-
this.
|
|
104
|
-
if (this.
|
|
96
|
+
this.samplingRatio = samplingRatio;
|
|
97
|
+
if (this.samplingRatio > 1) {
|
|
105
98
|
throw new Error("Wrong sampling rate, data will not be sampled out");
|
|
106
99
|
}
|
|
107
|
-
this._sampleRate = Math.round(this.
|
|
100
|
+
this._sampleRate = Math.round(this.samplingRatio * 100);
|
|
108
101
|
}
|
|
109
102
|
/**
|
|
110
103
|
* Checks whether span needs to be created and tracked.
|
|
111
104
|
*
|
|
112
|
-
* @param context Parent Context which may contain a span.
|
|
113
|
-
* @param traceId of the span to be created. It can be different from the
|
|
105
|
+
* @param context - Parent Context which may contain a span.
|
|
106
|
+
* @param traceId - traceif of the span to be created. It can be different from the
|
|
114
107
|
* traceId in the {@link SpanContext}. Typically in situations when the
|
|
115
108
|
* span to be created starts a new trace.
|
|
116
|
-
* @param spanName of the span to be created.
|
|
117
|
-
* @param spanKind of the span to be created.
|
|
118
|
-
* @param attributes Initial set of SpanAttributes for the Span being constructed.
|
|
119
|
-
* @param links Collection of links that will be associated with the Span to
|
|
109
|
+
* @param spanName - Name of the span to be created.
|
|
110
|
+
* @param spanKind - Kind of the span to be created.
|
|
111
|
+
* @param attributes - Initial set of SpanAttributes for the Span being constructed.
|
|
112
|
+
* @param links - Collection of links that will be associated with the Span to
|
|
120
113
|
* be created. Typically useful for batch operations.
|
|
121
114
|
* @returns a {@link SamplingResult}.
|
|
122
115
|
*/
|
|
@@ -130,10 +123,10 @@ class ApplicationInsightsSampler {
|
|
|
130
123
|
// @ts-ignore
|
|
131
124
|
links) {
|
|
132
125
|
let isSampledIn = false;
|
|
133
|
-
if (this._sampleRate
|
|
126
|
+
if (this._sampleRate === 100) {
|
|
134
127
|
isSampledIn = true;
|
|
135
128
|
}
|
|
136
|
-
else if (this._sampleRate
|
|
129
|
+
else if (this._sampleRate === 0) {
|
|
137
130
|
isSampledIn = false;
|
|
138
131
|
}
|
|
139
132
|
else {
|
|
@@ -150,19 +143,19 @@ class ApplicationInsightsSampler {
|
|
|
150
143
|
* Return Sampler description
|
|
151
144
|
*/
|
|
152
145
|
toString() {
|
|
153
|
-
return `ApplicationInsightsSampler{${this.
|
|
146
|
+
return `ApplicationInsightsSampler{${this.samplingRatio}}`;
|
|
154
147
|
}
|
|
155
148
|
_getSamplingHashCode(input) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
149
|
+
const csharpMin = -2147483648;
|
|
150
|
+
const csharpMax = 2147483647;
|
|
151
|
+
let hash = 5381;
|
|
159
152
|
if (!input) {
|
|
160
153
|
return 0;
|
|
161
154
|
}
|
|
162
155
|
while (input.length < 8) {
|
|
163
156
|
input = input + input;
|
|
164
157
|
}
|
|
165
|
-
for (
|
|
158
|
+
for (let i = 0; i < input.length; i++) {
|
|
166
159
|
// JS doesn't respond to integer overflow by wrapping around. Simulate it with bitwise operators ( | 0)
|
|
167
160
|
hash = ((((hash << 5) + hash) | 0) + input.charCodeAt(i)) | 0;
|
|
168
161
|
}
|
|
@@ -263,6 +256,7 @@ var PerformanceCounter;
|
|
|
263
256
|
});
|
|
264
257
|
|
|
265
258
|
// Copyright (c) Microsoft Corporation.
|
|
259
|
+
// Licensed under the MIT license.
|
|
266
260
|
/**
|
|
267
261
|
* ConnectionString parser.
|
|
268
262
|
* @internal
|
|
@@ -318,16 +312,27 @@ class ConnectionStringParser {
|
|
|
318
312
|
newUrl = newUrl.replace("http://", "https://");
|
|
319
313
|
}
|
|
320
314
|
// Remove final slash if present
|
|
321
|
-
if (newUrl[newUrl.length - 1]
|
|
315
|
+
if (newUrl[newUrl.length - 1] === "/") {
|
|
322
316
|
newUrl = newUrl.slice(0, -1);
|
|
323
317
|
}
|
|
324
318
|
return newUrl;
|
|
325
319
|
}
|
|
320
|
+
static validateInstrumentationKey(iKey) {
|
|
321
|
+
if (iKey.startsWith("InstrumentationKey=")) {
|
|
322
|
+
const startIndex = iKey.indexOf("InstrumentationKey=") + "InstrumentationKey=".length;
|
|
323
|
+
const endIndex = iKey.indexOf(";", startIndex);
|
|
324
|
+
iKey = iKey.substring(startIndex, endIndex);
|
|
325
|
+
}
|
|
326
|
+
const UUID_Regex = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$";
|
|
327
|
+
const regexp = new RegExp(UUID_Regex);
|
|
328
|
+
return regexp.test(iKey);
|
|
329
|
+
}
|
|
326
330
|
}
|
|
327
331
|
ConnectionStringParser.FIELDS_SEPARATOR = ";";
|
|
328
332
|
ConnectionStringParser.FIELD_KEY_VALUE_SEPARATOR = "=";
|
|
329
333
|
|
|
330
334
|
// Copyright (c) Microsoft Corporation.
|
|
335
|
+
// Licensed under the MIT license.
|
|
331
336
|
/**
|
|
332
337
|
* Azure Monitor OpenTelemetry Trace Exporter.
|
|
333
338
|
*/
|
|
@@ -350,16 +355,17 @@ class AzureMonitorBaseExporter {
|
|
|
350
355
|
*Flag to determine if exporter will generate Statsbeat data
|
|
351
356
|
*/
|
|
352
357
|
this.trackStatsbeat = false;
|
|
353
|
-
this.
|
|
358
|
+
this.options = options;
|
|
354
359
|
this.instrumentationKey = "";
|
|
355
360
|
this.endpointUrl = DEFAULT_BREEZE_ENDPOINT;
|
|
356
|
-
const connectionString = this.
|
|
357
|
-
this.
|
|
361
|
+
const connectionString = this.options.connectionString || process.env[ENV_CONNECTION_STRING];
|
|
362
|
+
this.isStatsbeatExporter = isStatsbeatExporter ? isStatsbeatExporter : false;
|
|
358
363
|
if (connectionString) {
|
|
359
364
|
const parsedConnectionString = ConnectionStringParser.parse(connectionString);
|
|
360
365
|
this.instrumentationKey =
|
|
361
366
|
parsedConnectionString.instrumentationkey || this.instrumentationKey;
|
|
362
367
|
this.endpointUrl = ((_a = parsedConnectionString.ingestionendpoint) === null || _a === void 0 ? void 0 : _a.trim()) || this.endpointUrl;
|
|
368
|
+
this.aadAudience = parsedConnectionString.aadaudience;
|
|
363
369
|
}
|
|
364
370
|
// Instrumentation key is required
|
|
365
371
|
if (!this.instrumentationKey) {
|
|
@@ -367,12 +373,18 @@ class AzureMonitorBaseExporter {
|
|
|
367
373
|
api.diag.error(message);
|
|
368
374
|
throw new Error(message);
|
|
369
375
|
}
|
|
370
|
-
|
|
376
|
+
if (!ConnectionStringParser.validateInstrumentationKey(this.instrumentationKey)) {
|
|
377
|
+
const message = "Invalid instrumentation key was provided to the Azure Monitor Exporter";
|
|
378
|
+
api.diag.error(message);
|
|
379
|
+
throw new Error(message);
|
|
380
|
+
}
|
|
381
|
+
this.trackStatsbeat = !this.isStatsbeatExporter && !process.env[ENV_DISABLE_STATSBEAT];
|
|
371
382
|
api.diag.debug("AzureMonitorExporter was successfully setup");
|
|
372
383
|
}
|
|
373
384
|
}
|
|
374
385
|
|
|
375
386
|
// Copyright (c) Microsoft Corporation.
|
|
387
|
+
// Licensed under the MIT license.
|
|
376
388
|
class FileAccessControl {
|
|
377
389
|
// Check if file access control could be enabled
|
|
378
390
|
static checkFileProtection() {
|
|
@@ -410,7 +422,7 @@ class FileAccessControl {
|
|
|
410
422
|
FileAccessControl.ACLED_DIRECTORIES[directory] = false;
|
|
411
423
|
try {
|
|
412
424
|
// Restrict this directory to only current user and administrator access
|
|
413
|
-
|
|
425
|
+
const identity = await this._getACLIdentity();
|
|
414
426
|
await this._runICACLS(this._getACLArguments(directory, identity));
|
|
415
427
|
FileAccessControl.ACLED_DIRECTORIES[directory] = true;
|
|
416
428
|
}
|
|
@@ -442,7 +454,7 @@ class FileAccessControl {
|
|
|
442
454
|
}
|
|
443
455
|
static _runICACLS(args) {
|
|
444
456
|
return new Promise((resolve, reject) => {
|
|
445
|
-
|
|
457
|
+
const aclProc = child_process__namespace.spawn(FileAccessControl.ICACLS_PATH, args, {
|
|
446
458
|
windowsHide: true,
|
|
447
459
|
});
|
|
448
460
|
aclProc.on("error", (e) => reject(e));
|
|
@@ -459,7 +471,7 @@ class FileAccessControl {
|
|
|
459
471
|
static _runICACLSSync(args) {
|
|
460
472
|
// Some very old versions of Node (< 0.11) don't have this
|
|
461
473
|
if (child_process__namespace.spawnSync) {
|
|
462
|
-
|
|
474
|
+
const aclProc = child_process__namespace.spawnSync(FileAccessControl.ICACLS_PATH, args, {
|
|
463
475
|
windowsHide: true,
|
|
464
476
|
});
|
|
465
477
|
if (aclProc.error) {
|
|
@@ -478,7 +490,7 @@ class FileAccessControl {
|
|
|
478
490
|
if (FileAccessControl.ACL_IDENTITY) {
|
|
479
491
|
resolve(FileAccessControl.ACL_IDENTITY);
|
|
480
492
|
}
|
|
481
|
-
|
|
493
|
+
const psProc = child_process__namespace.spawn(FileAccessControl.POWERSHELL_PATH, ["-Command", "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name"], {
|
|
482
494
|
windowsHide: true,
|
|
483
495
|
stdio: ["ignore", "pipe", "pipe"], // Needed to prevent hanging on Win 7
|
|
484
496
|
});
|
|
@@ -502,7 +514,7 @@ class FileAccessControl {
|
|
|
502
514
|
}
|
|
503
515
|
// Some very old versions of Node (< 0.11) don't have this
|
|
504
516
|
if (child_process__namespace.spawnSync) {
|
|
505
|
-
|
|
517
|
+
const psProc = child_process__namespace.spawnSync(FileAccessControl.POWERSHELL_PATH, ["-Command", "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name"], {
|
|
506
518
|
windowsHide: true,
|
|
507
519
|
stdio: ["ignore", "pipe", "pipe"], // Needed to prevent hanging on Win 7
|
|
508
520
|
});
|
|
@@ -539,6 +551,7 @@ FileAccessControl.OS_PROVIDES_FILE_PROTECTION = false;
|
|
|
539
551
|
FileAccessControl.USE_ICACLS = os__namespace.type() === "Windows_NT";
|
|
540
552
|
|
|
541
553
|
// Copyright (c) Microsoft Corporation.
|
|
554
|
+
// Licensed under the MIT license.
|
|
542
555
|
const readdirAsync$1 = util.promisify(fs__namespace.readdir);
|
|
543
556
|
const statAsync$1 = util.promisify(fs__namespace.stat);
|
|
544
557
|
const lstatAsync = util.promisify(fs__namespace.lstat);
|
|
@@ -588,6 +601,7 @@ const confirmDirExists = async (directory) => {
|
|
|
588
601
|
};
|
|
589
602
|
|
|
590
603
|
// Copyright (c) Microsoft Corporation.
|
|
604
|
+
// Licensed under the MIT license.
|
|
591
605
|
const statAsync = util.promisify(fs__namespace.stat);
|
|
592
606
|
const readdirAsync = util.promisify(fs__namespace.readdir);
|
|
593
607
|
const readFileAsync = util.promisify(fs__namespace.readFile);
|
|
@@ -1752,23 +1766,23 @@ const RequestData = {
|
|
|
1752
1766
|
|
|
1753
1767
|
var Mappers = /*#__PURE__*/Object.freeze({
|
|
1754
1768
|
__proto__: null,
|
|
1755
|
-
TelemetryItem: TelemetryItem,
|
|
1756
|
-
MonitorBase: MonitorBase,
|
|
1757
|
-
MonitorDomain: MonitorDomain,
|
|
1758
|
-
TrackResponse: TrackResponse,
|
|
1759
|
-
TelemetryErrorDetails: TelemetryErrorDetails,
|
|
1760
|
-
MetricDataPoint: MetricDataPoint,
|
|
1761
|
-
TelemetryExceptionDetails: TelemetryExceptionDetails,
|
|
1762
|
-
StackFrame: StackFrame,
|
|
1763
1769
|
AvailabilityData: AvailabilityData,
|
|
1764
|
-
TelemetryEventData: TelemetryEventData,
|
|
1765
|
-
TelemetryExceptionData: TelemetryExceptionData,
|
|
1766
1770
|
MessageData: MessageData,
|
|
1771
|
+
MetricDataPoint: MetricDataPoint,
|
|
1767
1772
|
MetricsData: MetricsData,
|
|
1773
|
+
MonitorBase: MonitorBase,
|
|
1774
|
+
MonitorDomain: MonitorDomain,
|
|
1768
1775
|
PageViewData: PageViewData,
|
|
1769
1776
|
PageViewPerfData: PageViewPerfData,
|
|
1770
1777
|
RemoteDependencyData: RemoteDependencyData,
|
|
1771
|
-
RequestData: RequestData
|
|
1778
|
+
RequestData: RequestData,
|
|
1779
|
+
StackFrame: StackFrame,
|
|
1780
|
+
TelemetryErrorDetails: TelemetryErrorDetails,
|
|
1781
|
+
TelemetryEventData: TelemetryEventData,
|
|
1782
|
+
TelemetryExceptionData: TelemetryExceptionData,
|
|
1783
|
+
TelemetryExceptionDetails: TelemetryExceptionDetails,
|
|
1784
|
+
TelemetryItem: TelemetryItem,
|
|
1785
|
+
TrackResponse: TrackResponse
|
|
1772
1786
|
});
|
|
1773
1787
|
|
|
1774
1788
|
/*
|
|
@@ -1792,7 +1806,7 @@ class ApplicationInsightsClient extends coreClient__namespace.ServiceClient {
|
|
|
1792
1806
|
const defaults = {
|
|
1793
1807
|
requestContentType: "application/json; charset=utf-8"
|
|
1794
1808
|
};
|
|
1795
|
-
const packageDetails = `azsdk-js-monitor-opentelemetry-exporter/1.0.0-beta.
|
|
1809
|
+
const packageDetails = `azsdk-js-monitor-opentelemetry-exporter/1.0.0-beta.17`;
|
|
1796
1810
|
const userAgentPrefix = options.userAgentOptions && options.userAgentOptions.userAgentPrefix
|
|
1797
1811
|
? `${options.userAgentOptions.userAgentPrefix} ${packageDetails}`
|
|
1798
1812
|
: `${packageDetails}`;
|
|
@@ -1868,6 +1882,8 @@ const trackOperationSpec = {
|
|
|
1868
1882
|
serializer
|
|
1869
1883
|
};
|
|
1870
1884
|
|
|
1885
|
+
// Copyright (c) Microsoft Corporation.
|
|
1886
|
+
// Licensed under the MIT license.
|
|
1871
1887
|
class NetworkStatsbeat {
|
|
1872
1888
|
constructor(endpoint, host) {
|
|
1873
1889
|
this.endpoint = endpoint;
|
|
@@ -1895,12 +1911,12 @@ const StatsbeatResourceProvider = {
|
|
|
1895
1911
|
};
|
|
1896
1912
|
var StatsbeatCounter;
|
|
1897
1913
|
(function (StatsbeatCounter) {
|
|
1898
|
-
StatsbeatCounter["SUCCESS_COUNT"] = "
|
|
1899
|
-
StatsbeatCounter["FAILURE_COUNT"] = "
|
|
1900
|
-
StatsbeatCounter["RETRY_COUNT"] = "
|
|
1901
|
-
StatsbeatCounter["THROTTLE_COUNT"] = "
|
|
1902
|
-
StatsbeatCounter["EXCEPTION_COUNT"] = "
|
|
1903
|
-
StatsbeatCounter["AVERAGE_DURATION"] = "
|
|
1914
|
+
StatsbeatCounter["SUCCESS_COUNT"] = "Request_Success_Count";
|
|
1915
|
+
StatsbeatCounter["FAILURE_COUNT"] = "Request_Failure_Count";
|
|
1916
|
+
StatsbeatCounter["RETRY_COUNT"] = "Retry_Count";
|
|
1917
|
+
StatsbeatCounter["THROTTLE_COUNT"] = "Throttle_Count";
|
|
1918
|
+
StatsbeatCounter["EXCEPTION_COUNT"] = "Exception_Count";
|
|
1919
|
+
StatsbeatCounter["AVERAGE_DURATION"] = "Request_Duration";
|
|
1904
1920
|
StatsbeatCounter["ATTACH"] = "Attach";
|
|
1905
1921
|
StatsbeatCounter["FEATURE"] = "Feature";
|
|
1906
1922
|
})(StatsbeatCounter || (StatsbeatCounter = {}));
|
|
@@ -1930,35 +1946,36 @@ var StatsbeatFeatureType;
|
|
|
1930
1946
|
})(StatsbeatFeatureType || (StatsbeatFeatureType = {}));
|
|
1931
1947
|
|
|
1932
1948
|
// Copyright (c) Microsoft Corporation.
|
|
1949
|
+
// Licensed under the MIT license.
|
|
1933
1950
|
const os = require("os");
|
|
1934
1951
|
class StatsbeatMetrics {
|
|
1935
1952
|
constructor() {
|
|
1936
|
-
this.
|
|
1937
|
-
this.
|
|
1938
|
-
this.
|
|
1939
|
-
this.
|
|
1953
|
+
this.resourceProvider = StatsbeatResourceProvider.unknown;
|
|
1954
|
+
this.vmInfo = {};
|
|
1955
|
+
this.os = os.type();
|
|
1956
|
+
this.resourceIdentifier = "";
|
|
1940
1957
|
}
|
|
1941
|
-
async
|
|
1958
|
+
async getResourceProvider() {
|
|
1942
1959
|
// Check resource provider
|
|
1943
|
-
this.
|
|
1960
|
+
this.resourceProvider = StatsbeatResourceProvider.unknown;
|
|
1944
1961
|
if (process.env.WEBSITE_SITE_NAME) {
|
|
1945
1962
|
// Web apps
|
|
1946
|
-
this.
|
|
1963
|
+
this.resourceProvider = StatsbeatResourceProvider.appsvc;
|
|
1947
1964
|
}
|
|
1948
1965
|
else if (process.env.FUNCTIONS_WORKER_RUNTIME) {
|
|
1949
1966
|
// Function apps
|
|
1950
|
-
this.
|
|
1967
|
+
this.resourceProvider = StatsbeatResourceProvider.functions;
|
|
1951
1968
|
}
|
|
1952
1969
|
else if (await this.getAzureComputeMetadata()) {
|
|
1953
|
-
this.
|
|
1954
|
-
this.
|
|
1970
|
+
this.resourceProvider = StatsbeatResourceProvider.vm;
|
|
1971
|
+
this.resourceIdentifier = this.vmInfo.id + "/" + this.vmInfo.subscriptionId;
|
|
1955
1972
|
// Overrride OS as VM info have higher precedence
|
|
1956
|
-
if (this.
|
|
1957
|
-
this.
|
|
1973
|
+
if (this.vmInfo.osType) {
|
|
1974
|
+
this.os = this.vmInfo.osType;
|
|
1958
1975
|
}
|
|
1959
1976
|
}
|
|
1960
1977
|
else {
|
|
1961
|
-
this.
|
|
1978
|
+
this.resourceProvider = StatsbeatResourceProvider.unknown;
|
|
1962
1979
|
}
|
|
1963
1980
|
}
|
|
1964
1981
|
async getAzureComputeMetadata() {
|
|
@@ -1976,17 +1993,17 @@ class StatsbeatMetrics {
|
|
|
1976
1993
|
.then((res) => {
|
|
1977
1994
|
if (res.status === 200) {
|
|
1978
1995
|
// Success; VM
|
|
1979
|
-
this.
|
|
1996
|
+
this.vmInfo.isVM = true;
|
|
1980
1997
|
let virtualMachineData = "";
|
|
1981
1998
|
res.on("data", (data) => {
|
|
1982
1999
|
virtualMachineData += data;
|
|
1983
2000
|
});
|
|
1984
2001
|
res.on("end", () => {
|
|
1985
2002
|
try {
|
|
1986
|
-
|
|
1987
|
-
this.
|
|
1988
|
-
this.
|
|
1989
|
-
this.
|
|
2003
|
+
const data = JSON.parse(virtualMachineData);
|
|
2004
|
+
this.vmInfo.id = data["vmId"] || "";
|
|
2005
|
+
this.vmInfo.subscriptionId = data["subscriptionId"] || "";
|
|
2006
|
+
this.vmInfo.osType = data["osType"] || "";
|
|
1990
2007
|
}
|
|
1991
2008
|
catch (error) {
|
|
1992
2009
|
api.diag.debug("Failed to parse JSON: ", error);
|
|
@@ -2003,8 +2020,8 @@ class StatsbeatMetrics {
|
|
|
2003
2020
|
});
|
|
2004
2021
|
return false;
|
|
2005
2022
|
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2023
|
+
getConnectionString(endpointUrl) {
|
|
2024
|
+
const currentEndpoint = endpointUrl;
|
|
2008
2025
|
for (let i = 0; i < EU_ENDPOINTS.length; i++) {
|
|
2009
2026
|
if (currentEndpoint.includes(EU_ENDPOINTS[i])) {
|
|
2010
2027
|
return EU_CONNECTION_STRING;
|
|
@@ -2015,6 +2032,7 @@ class StatsbeatMetrics {
|
|
|
2015
2032
|
}
|
|
2016
2033
|
|
|
2017
2034
|
// Copyright (c) Microsoft Corporation.
|
|
2035
|
+
// Licensed under the MIT license.
|
|
2018
2036
|
function createPropertiesFromMetricAttributes(attributes) {
|
|
2019
2037
|
const properties = {};
|
|
2020
2038
|
if (attributes) {
|
|
@@ -2029,7 +2047,7 @@ function createPropertiesFromMetricAttributes(attributes) {
|
|
|
2029
2047
|
* @internal
|
|
2030
2048
|
*/
|
|
2031
2049
|
function resourceMetricsToEnvelope(metrics, ikey, isStatsbeat) {
|
|
2032
|
-
|
|
2050
|
+
const envelopes = [];
|
|
2033
2051
|
const time = new Date();
|
|
2034
2052
|
const instrumentationKey = ikey;
|
|
2035
2053
|
const tags = createTagsFromResource(metrics.resource);
|
|
@@ -2043,19 +2061,19 @@ function resourceMetricsToEnvelope(metrics, ikey, isStatsbeat) {
|
|
|
2043
2061
|
metrics.scopeMetrics.forEach((scopeMetric) => {
|
|
2044
2062
|
scopeMetric.metrics.forEach((metric) => {
|
|
2045
2063
|
metric.dataPoints.forEach((dataPoint) => {
|
|
2046
|
-
|
|
2064
|
+
const baseData = {
|
|
2047
2065
|
metrics: [],
|
|
2048
2066
|
version: 2,
|
|
2049
2067
|
properties: {},
|
|
2050
2068
|
};
|
|
2051
2069
|
baseData.properties = createPropertiesFromMetricAttributes(dataPoint.attributes);
|
|
2052
|
-
|
|
2070
|
+
const metricDataPoint = {
|
|
2053
2071
|
name: metric.descriptor.name,
|
|
2054
2072
|
value: 0,
|
|
2055
2073
|
dataPointType: "Aggregation",
|
|
2056
2074
|
};
|
|
2057
|
-
if (metric.dataPointType
|
|
2058
|
-
metric.dataPointType
|
|
2075
|
+
if (metric.dataPointType === sdkMetrics.DataPointType.SUM ||
|
|
2076
|
+
metric.dataPointType === sdkMetrics.DataPointType.GAUGE) {
|
|
2059
2077
|
metricDataPoint.value = dataPoint.value;
|
|
2060
2078
|
metricDataPoint.count = 1;
|
|
2061
2079
|
}
|
|
@@ -2066,7 +2084,7 @@ function resourceMetricsToEnvelope(metrics, ikey, isStatsbeat) {
|
|
|
2066
2084
|
metricDataPoint.min = dataPoint.value.min;
|
|
2067
2085
|
}
|
|
2068
2086
|
baseData.metrics.push(metricDataPoint);
|
|
2069
|
-
|
|
2087
|
+
const envelope = {
|
|
2070
2088
|
name: envelopeName,
|
|
2071
2089
|
time: time,
|
|
2072
2090
|
sampleRate: 100,
|
|
@@ -2086,6 +2104,7 @@ function resourceMetricsToEnvelope(metrics, ikey, isStatsbeat) {
|
|
|
2086
2104
|
}
|
|
2087
2105
|
|
|
2088
2106
|
// Copyright (c) Microsoft Corporation.
|
|
2107
|
+
// Licensed under the MIT license.
|
|
2089
2108
|
/**
|
|
2090
2109
|
* Azure Monitor Statsbeat Exporter
|
|
2091
2110
|
*/
|
|
@@ -2100,7 +2119,12 @@ class AzureMonitorStatsbeatExporter extends AzureMonitorBaseExporter {
|
|
|
2100
2119
|
* Flag to determine if the Exporter is shutdown.
|
|
2101
2120
|
*/
|
|
2102
2121
|
this._isShutdown = false;
|
|
2103
|
-
this._sender = new HttpSender(
|
|
2122
|
+
this._sender = new HttpSender({
|
|
2123
|
+
endpointUrl: this.endpointUrl,
|
|
2124
|
+
instrumentationKey: this.instrumentationKey,
|
|
2125
|
+
trackStatsbeat: this.trackStatsbeat,
|
|
2126
|
+
exporterOptions: options,
|
|
2127
|
+
});
|
|
2104
2128
|
}
|
|
2105
2129
|
/**
|
|
2106
2130
|
* Export Statsbeat metrics.
|
|
@@ -2110,7 +2134,7 @@ class AzureMonitorStatsbeatExporter extends AzureMonitorBaseExporter {
|
|
|
2110
2134
|
setTimeout(() => resultCallback({ code: core.ExportResultCode.FAILED }), 0);
|
|
2111
2135
|
return;
|
|
2112
2136
|
}
|
|
2113
|
-
|
|
2137
|
+
const envelopes = resourceMetricsToEnvelope(metrics, this.instrumentationKey, true // isStatsbeat flag passed to create a Statsbeat envelope.
|
|
2114
2138
|
);
|
|
2115
2139
|
// Supress tracing until OpenTelemetry Metrics SDK support it
|
|
2116
2140
|
api.context.with(core.suppressTracing(api.context.active()), async () => {
|
|
@@ -2133,140 +2157,138 @@ class AzureMonitorStatsbeatExporter extends AzureMonitorBaseExporter {
|
|
|
2133
2157
|
}
|
|
2134
2158
|
|
|
2135
2159
|
// Copyright (c) Microsoft Corporation.
|
|
2160
|
+
// Licensed under the MIT license.
|
|
2136
2161
|
class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
2137
2162
|
constructor(options) {
|
|
2138
2163
|
super();
|
|
2139
|
-
this.
|
|
2140
|
-
this.
|
|
2141
|
-
this.
|
|
2142
|
-
this.
|
|
2143
|
-
this.
|
|
2144
|
-
this.
|
|
2164
|
+
this.isInitialized = false;
|
|
2165
|
+
this.statsCollectionShortInterval = 900000; // 15 minutes
|
|
2166
|
+
this.networkStatsbeatCollection = [];
|
|
2167
|
+
this.attach = "sdk";
|
|
2168
|
+
this.connectionString = super.getConnectionString(options.endpointUrl);
|
|
2169
|
+
this.networkStatsbeatMeterProvider = new sdkMetrics.MeterProvider();
|
|
2145
2170
|
const exporterConfig = {
|
|
2146
|
-
connectionString: this.
|
|
2171
|
+
connectionString: this.connectionString,
|
|
2147
2172
|
};
|
|
2148
|
-
this.
|
|
2173
|
+
this.networkAzureExporter = new AzureMonitorStatsbeatExporter(exporterConfig);
|
|
2149
2174
|
// Exports Network Statsbeat every 15 minutes
|
|
2150
2175
|
const networkMetricReaderOptions = {
|
|
2151
|
-
exporter: this.
|
|
2152
|
-
exportIntervalMillis: options.networkCollectionInterval || this.
|
|
2176
|
+
exporter: this.networkAzureExporter,
|
|
2177
|
+
exportIntervalMillis: options.networkCollectionInterval || this.statsCollectionShortInterval, // 15 minutes
|
|
2153
2178
|
};
|
|
2154
|
-
this.
|
|
2155
|
-
this.
|
|
2156
|
-
this.
|
|
2157
|
-
this.
|
|
2158
|
-
this.
|
|
2159
|
-
this.
|
|
2160
|
-
this.
|
|
2161
|
-
this.
|
|
2162
|
-
this.
|
|
2163
|
-
this.
|
|
2164
|
-
this.
|
|
2165
|
-
this.
|
|
2166
|
-
this.
|
|
2167
|
-
this.
|
|
2168
|
-
this.
|
|
2169
|
-
this.
|
|
2170
|
-
os: super.
|
|
2171
|
-
rp: super.
|
|
2172
|
-
cikey: this.
|
|
2173
|
-
runtimeVersion: this.
|
|
2174
|
-
language: this.
|
|
2175
|
-
version: this.
|
|
2176
|
-
attach: this.
|
|
2179
|
+
this.networkMetricReader = new sdkMetrics.PeriodicExportingMetricReader(networkMetricReaderOptions);
|
|
2180
|
+
this.networkStatsbeatMeterProvider.addMetricReader(this.networkMetricReader);
|
|
2181
|
+
this.networkStatsbeatMeter = this.networkStatsbeatMeterProvider.getMeter("Azure Monitor Network Statsbeat");
|
|
2182
|
+
this.endpointUrl = options.endpointUrl;
|
|
2183
|
+
this.runtimeVersion = process.version;
|
|
2184
|
+
this.language = STATSBEAT_LANGUAGE;
|
|
2185
|
+
this.version = packageVersion;
|
|
2186
|
+
this.host = this.getShortHost(options.endpointUrl);
|
|
2187
|
+
this.cikey = options.instrumentationKey;
|
|
2188
|
+
this.successCountGauge = this.networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.SUCCESS_COUNT);
|
|
2189
|
+
this.failureCountGauge = this.networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.FAILURE_COUNT);
|
|
2190
|
+
this.retryCountGauge = this.networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.RETRY_COUNT);
|
|
2191
|
+
this.throttleCountGauge = this.networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.THROTTLE_COUNT);
|
|
2192
|
+
this.exceptionCountGauge = this.networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.EXCEPTION_COUNT);
|
|
2193
|
+
this.averageDurationGauge = this.networkStatsbeatMeter.createObservableGauge(StatsbeatCounter.AVERAGE_DURATION);
|
|
2194
|
+
this.commonProperties = {
|
|
2195
|
+
os: super.os,
|
|
2196
|
+
rp: super.resourceProvider,
|
|
2197
|
+
cikey: this.cikey,
|
|
2198
|
+
runtimeVersion: this.runtimeVersion,
|
|
2199
|
+
language: this.language,
|
|
2200
|
+
version: this.version,
|
|
2201
|
+
attach: this.attach,
|
|
2177
2202
|
};
|
|
2178
|
-
this.
|
|
2179
|
-
endpoint: this.
|
|
2180
|
-
host: this.
|
|
2203
|
+
this.networkProperties = {
|
|
2204
|
+
endpoint: this.endpointUrl,
|
|
2205
|
+
host: this.host,
|
|
2181
2206
|
};
|
|
2182
|
-
this.
|
|
2183
|
-
this.
|
|
2184
|
-
}
|
|
2185
|
-
isInitialized() {
|
|
2186
|
-
return this._isInitialized;
|
|
2207
|
+
this.isInitialized = true;
|
|
2208
|
+
this.initialize();
|
|
2187
2209
|
}
|
|
2188
2210
|
shutdown() {
|
|
2189
|
-
this.
|
|
2211
|
+
return this.networkStatsbeatMeterProvider.shutdown();
|
|
2190
2212
|
}
|
|
2191
|
-
async
|
|
2213
|
+
async initialize() {
|
|
2192
2214
|
try {
|
|
2193
|
-
await super.
|
|
2215
|
+
await super.getResourceProvider();
|
|
2194
2216
|
// Add network observable callbacks
|
|
2195
|
-
this.
|
|
2196
|
-
this.
|
|
2197
|
-
this.
|
|
2217
|
+
this.successCountGauge.addCallback(this.successCallback.bind(this));
|
|
2218
|
+
this.networkStatsbeatMeter.addBatchObservableCallback(this.failureCallback.bind(this), [
|
|
2219
|
+
this.failureCountGauge,
|
|
2198
2220
|
]);
|
|
2199
|
-
this.
|
|
2200
|
-
this.
|
|
2221
|
+
this.networkStatsbeatMeter.addBatchObservableCallback(this.retryCallback.bind(this), [
|
|
2222
|
+
this.retryCountGauge,
|
|
2201
2223
|
]);
|
|
2202
|
-
this.
|
|
2203
|
-
this.
|
|
2224
|
+
this.networkStatsbeatMeter.addBatchObservableCallback(this.throttleCallback.bind(this), [
|
|
2225
|
+
this.throttleCountGauge,
|
|
2204
2226
|
]);
|
|
2205
|
-
this.
|
|
2206
|
-
this.
|
|
2227
|
+
this.networkStatsbeatMeter.addBatchObservableCallback(this.exceptionCallback.bind(this), [
|
|
2228
|
+
this.exceptionCountGauge,
|
|
2207
2229
|
]);
|
|
2208
|
-
this.
|
|
2230
|
+
this.averageDurationGauge.addCallback(this.durationCallback.bind(this));
|
|
2209
2231
|
}
|
|
2210
2232
|
catch (error) {
|
|
2211
2233
|
api.diag.debug("Call to get the resource provider failed.");
|
|
2212
2234
|
}
|
|
2213
2235
|
}
|
|
2214
2236
|
// Observable gauge callbacks
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2237
|
+
successCallback(observableResult) {
|
|
2238
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2239
|
+
const attributes = Object.assign(Object.assign({}, this.commonProperties), this.networkProperties);
|
|
2218
2240
|
observableResult.observe(counter.totalSuccesfulRequestCount, attributes);
|
|
2219
2241
|
counter.totalSuccesfulRequestCount = 0;
|
|
2220
2242
|
}
|
|
2221
|
-
|
|
2222
|
-
|
|
2243
|
+
failureCallback(observableResult) {
|
|
2244
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2223
2245
|
/*
|
|
2224
2246
|
Takes the failureCountGauge, value (of the counter), and attributes
|
|
2225
2247
|
create a unqiue counter based on statusCode as well
|
|
2226
2248
|
append statusCode to attributes so the newly created attributes are unique.
|
|
2227
2249
|
*/
|
|
2228
|
-
|
|
2250
|
+
const attributes = Object.assign(Object.assign(Object.assign({}, this.networkProperties), this.commonProperties), { statusCode: 0 });
|
|
2229
2251
|
// For each { statusCode -> count } mapping, call observe, passing the count and attributes that include the statusCode
|
|
2230
2252
|
for (let i = 0; i < counter.totalFailedRequestCount.length; i++) {
|
|
2231
2253
|
attributes.statusCode = counter.totalFailedRequestCount[i].statusCode;
|
|
2232
|
-
observableResult.observe(this.
|
|
2254
|
+
observableResult.observe(this.failureCountGauge, counter.totalFailedRequestCount[i].count, Object.assign({}, attributes));
|
|
2233
2255
|
counter.totalFailedRequestCount[i].count = 0;
|
|
2234
2256
|
}
|
|
2235
2257
|
}
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2258
|
+
retryCallback(observableResult) {
|
|
2259
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2260
|
+
const attributes = Object.assign(Object.assign(Object.assign({}, this.networkProperties), this.commonProperties), { statusCode: 0 });
|
|
2239
2261
|
for (let i = 0; i < counter.retryCount.length; i++) {
|
|
2240
2262
|
attributes.statusCode = counter.retryCount[i].statusCode;
|
|
2241
|
-
observableResult.observe(this.
|
|
2263
|
+
observableResult.observe(this.retryCountGauge, counter.retryCount[i].count, Object.assign({}, attributes));
|
|
2242
2264
|
counter.retryCount[i].count = 0;
|
|
2243
2265
|
}
|
|
2244
2266
|
}
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2267
|
+
throttleCallback(observableResult) {
|
|
2268
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2269
|
+
const attributes = Object.assign(Object.assign(Object.assign({}, this.networkProperties), this.commonProperties), { statusCode: 0 });
|
|
2248
2270
|
for (let i = 0; i < counter.throttleCount.length; i++) {
|
|
2249
2271
|
attributes.statusCode = counter.throttleCount[i].statusCode;
|
|
2250
|
-
observableResult.observe(this.
|
|
2272
|
+
observableResult.observe(this.throttleCountGauge, counter.throttleCount[i].count, Object.assign({}, attributes));
|
|
2251
2273
|
counter.throttleCount[i].count = 0;
|
|
2252
2274
|
}
|
|
2253
2275
|
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2276
|
+
exceptionCallback(observableResult) {
|
|
2277
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2278
|
+
const attributes = Object.assign(Object.assign(Object.assign({}, this.networkProperties), this.commonProperties), { exceptionType: "" });
|
|
2257
2279
|
for (let i = 0; i < counter.exceptionCount.length; i++) {
|
|
2258
2280
|
attributes.exceptionType = counter.exceptionCount[i].exceptionType;
|
|
2259
|
-
observableResult.observe(this.
|
|
2281
|
+
observableResult.observe(this.exceptionCountGauge, counter.exceptionCount[i].count, Object.assign({}, attributes));
|
|
2260
2282
|
counter.exceptionCount[i].count = 0;
|
|
2261
2283
|
}
|
|
2262
2284
|
}
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
for (let i = 0; i < this.
|
|
2267
|
-
|
|
2285
|
+
durationCallback(observableResult) {
|
|
2286
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2287
|
+
const attributes = Object.assign(Object.assign({}, this.networkProperties), this.commonProperties);
|
|
2288
|
+
for (let i = 0; i < this.networkStatsbeatCollection.length; i++) {
|
|
2289
|
+
const currentCounter = this.networkStatsbeatCollection[i];
|
|
2268
2290
|
currentCounter.time = Number(new Date());
|
|
2269
|
-
|
|
2291
|
+
const intervalRequests = currentCounter.totalRequestCount - currentCounter.lastRequestCount || 0;
|
|
2270
2292
|
currentCounter.averageRequestExecutionTime =
|
|
2271
2293
|
(currentCounter.intervalRequestExecutionTime -
|
|
2272
2294
|
currentCounter.lastIntervalRequestExecutionTime) /
|
|
@@ -2280,20 +2302,20 @@ class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2280
2302
|
}
|
|
2281
2303
|
// Public methods to increase counters
|
|
2282
2304
|
countSuccess(duration) {
|
|
2283
|
-
if (!this.
|
|
2305
|
+
if (!this.isInitialized) {
|
|
2284
2306
|
return;
|
|
2285
2307
|
}
|
|
2286
|
-
|
|
2308
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2287
2309
|
counter.totalRequestCount++;
|
|
2288
2310
|
counter.totalSuccesfulRequestCount++;
|
|
2289
2311
|
counter.intervalRequestExecutionTime += duration;
|
|
2290
2312
|
}
|
|
2291
2313
|
countFailure(duration, statusCode) {
|
|
2292
|
-
if (!this.
|
|
2314
|
+
if (!this.isInitialized) {
|
|
2293
2315
|
return;
|
|
2294
2316
|
}
|
|
2295
|
-
|
|
2296
|
-
|
|
2317
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2318
|
+
const currentStatusCounter = counter.totalFailedRequestCount.find((statusCounter) => statusCode === statusCounter.statusCode);
|
|
2297
2319
|
if (currentStatusCounter) {
|
|
2298
2320
|
currentStatusCounter.count++;
|
|
2299
2321
|
}
|
|
@@ -2304,11 +2326,11 @@ class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2304
2326
|
counter.intervalRequestExecutionTime += duration;
|
|
2305
2327
|
}
|
|
2306
2328
|
countRetry(statusCode) {
|
|
2307
|
-
if (!this.
|
|
2329
|
+
if (!this.isInitialized) {
|
|
2308
2330
|
return;
|
|
2309
2331
|
}
|
|
2310
|
-
|
|
2311
|
-
|
|
2332
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2333
|
+
const currentStatusCounter = counter.retryCount.find((statusCounter) => statusCode === statusCounter.statusCode);
|
|
2312
2334
|
if (currentStatusCounter) {
|
|
2313
2335
|
currentStatusCounter.count++;
|
|
2314
2336
|
}
|
|
@@ -2317,11 +2339,11 @@ class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2317
2339
|
}
|
|
2318
2340
|
}
|
|
2319
2341
|
countThrottle(statusCode) {
|
|
2320
|
-
if (!this.
|
|
2342
|
+
if (!this.isInitialized) {
|
|
2321
2343
|
return;
|
|
2322
2344
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2345
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2346
|
+
const currentStatusCounter = counter.throttleCount.find((statusCounter) => statusCode === statusCounter.statusCode);
|
|
2325
2347
|
if (currentStatusCounter) {
|
|
2326
2348
|
currentStatusCounter.count++;
|
|
2327
2349
|
}
|
|
@@ -2330,11 +2352,11 @@ class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2330
2352
|
}
|
|
2331
2353
|
}
|
|
2332
2354
|
countException(exceptionType) {
|
|
2333
|
-
if (!this.
|
|
2355
|
+
if (!this.isInitialized) {
|
|
2334
2356
|
return;
|
|
2335
2357
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2358
|
+
const counter = this.getNetworkStatsbeatCounter(this.endpointUrl, this.host);
|
|
2359
|
+
const currentErrorCounter = counter.exceptionCount.find((exceptionCounter) => exceptionType.name === exceptionCounter.exceptionType);
|
|
2338
2360
|
if (currentErrorCounter) {
|
|
2339
2361
|
currentErrorCounter.count++;
|
|
2340
2362
|
}
|
|
@@ -2343,26 +2365,26 @@ class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2343
2365
|
}
|
|
2344
2366
|
}
|
|
2345
2367
|
// Gets a networkStatsbeat counter if one exists for the given endpoint
|
|
2346
|
-
|
|
2368
|
+
getNetworkStatsbeatCounter(endpoint, host) {
|
|
2347
2369
|
// Check if the counter is available
|
|
2348
|
-
for (let i = 0; i < this.
|
|
2370
|
+
for (let i = 0; i < this.networkStatsbeatCollection.length; i++) {
|
|
2349
2371
|
// Same object
|
|
2350
|
-
if (endpoint === this.
|
|
2351
|
-
host === this.
|
|
2352
|
-
return this.
|
|
2372
|
+
if (endpoint === this.networkStatsbeatCollection[i].endpoint &&
|
|
2373
|
+
host === this.networkStatsbeatCollection[i].host) {
|
|
2374
|
+
return this.networkStatsbeatCollection[i];
|
|
2353
2375
|
}
|
|
2354
2376
|
}
|
|
2355
2377
|
// Create a new counter if not found
|
|
2356
|
-
|
|
2357
|
-
this.
|
|
2378
|
+
const newCounter = new NetworkStatsbeat(endpoint, host);
|
|
2379
|
+
this.networkStatsbeatCollection.push(newCounter);
|
|
2358
2380
|
return newCounter;
|
|
2359
2381
|
}
|
|
2360
|
-
|
|
2382
|
+
getShortHost(originalHost) {
|
|
2361
2383
|
let shortHost = originalHost;
|
|
2362
2384
|
try {
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
if (res
|
|
2385
|
+
const hostRegex = new RegExp(/^https?:\/\/(?:www\.)?([^\/.-]+)/);
|
|
2386
|
+
const res = hostRegex.exec(originalHost);
|
|
2387
|
+
if (res !== null && res.length > 1) {
|
|
2366
2388
|
shortHost = res[1];
|
|
2367
2389
|
}
|
|
2368
2390
|
shortHost = shortHost.replace(".in.applicationinsights.azure.com", "");
|
|
@@ -2375,6 +2397,7 @@ class NetworkStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2375
2397
|
}
|
|
2376
2398
|
|
|
2377
2399
|
// Copyright (c) Microsoft Corporation.
|
|
2400
|
+
// Licensed under the MIT license.
|
|
2378
2401
|
let instance$1 = null;
|
|
2379
2402
|
/**
|
|
2380
2403
|
* Long Interval Statsbeat Metrics
|
|
@@ -2383,65 +2406,67 @@ let instance$1 = null;
|
|
|
2383
2406
|
class LongIntervalStatsbeatMetrics extends StatsbeatMetrics {
|
|
2384
2407
|
constructor(options) {
|
|
2385
2408
|
super();
|
|
2386
|
-
this.
|
|
2387
|
-
this.
|
|
2388
|
-
this.
|
|
2389
|
-
this.
|
|
2390
|
-
this.
|
|
2391
|
-
this.
|
|
2392
|
-
this.
|
|
2409
|
+
this.AZURE_MONITOR_STATSBEAT_FEATURES = process.env.AZURE_MONITOR_STATSBEAT_FEATURES;
|
|
2410
|
+
this.statsCollectionLongInterval = 86400000; // 1 day
|
|
2411
|
+
this.attach = "sdk";
|
|
2412
|
+
this.feature = 0;
|
|
2413
|
+
this.instrumentation = 0;
|
|
2414
|
+
this.isInitialized = false;
|
|
2415
|
+
this.connectionString = super.getConnectionString(options.endpointUrl);
|
|
2393
2416
|
const exporterConfig = {
|
|
2394
|
-
connectionString: this.
|
|
2417
|
+
connectionString: this.connectionString,
|
|
2395
2418
|
};
|
|
2396
|
-
if (this.
|
|
2419
|
+
if (this.AZURE_MONITOR_STATSBEAT_FEATURES) {
|
|
2397
2420
|
try {
|
|
2398
|
-
this.
|
|
2399
|
-
this.
|
|
2421
|
+
this.feature = JSON.parse(this.AZURE_MONITOR_STATSBEAT_FEATURES).feature;
|
|
2422
|
+
this.instrumentation = JSON.parse(this.AZURE_MONITOR_STATSBEAT_FEATURES).instrumentation;
|
|
2400
2423
|
}
|
|
2401
2424
|
catch (error) {
|
|
2402
2425
|
api.diag.error(`LongIntervalStatsbeat: Failed to parse features/instrumentations (error ${error})`);
|
|
2403
2426
|
}
|
|
2404
2427
|
}
|
|
2405
|
-
this.
|
|
2406
|
-
this.
|
|
2428
|
+
this.longIntervalStatsbeatMeterProvider = new sdkMetrics.MeterProvider();
|
|
2429
|
+
this.longIntervalAzureExporter = new AzureMonitorStatsbeatExporter(exporterConfig);
|
|
2407
2430
|
// Export Long Interval Statsbeats every day
|
|
2408
2431
|
const longIntervalMetricReaderOptions = {
|
|
2409
|
-
exporter: this.
|
|
2410
|
-
exportIntervalMillis: Number(process.env.LONG_INTERVAL_EXPORT_MILLIS) || this.
|
|
2432
|
+
exporter: this.longIntervalAzureExporter,
|
|
2433
|
+
exportIntervalMillis: Number(process.env.LONG_INTERVAL_EXPORT_MILLIS) || this.statsCollectionLongInterval, // 1 day
|
|
2411
2434
|
};
|
|
2412
|
-
this.
|
|
2413
|
-
this.
|
|
2414
|
-
this.
|
|
2435
|
+
this.longIntervalMetricReader = new sdkMetrics.PeriodicExportingMetricReader(longIntervalMetricReaderOptions);
|
|
2436
|
+
this.longIntervalStatsbeatMeterProvider.addMetricReader(this.longIntervalMetricReader);
|
|
2437
|
+
this.longIntervalStatsbeatMeter = this.longIntervalStatsbeatMeterProvider.getMeter("Azure Monitor Long Interval Statsbeat");
|
|
2415
2438
|
// Assign Common Properties
|
|
2416
|
-
this.
|
|
2417
|
-
this.
|
|
2418
|
-
this.
|
|
2419
|
-
this.
|
|
2420
|
-
this.
|
|
2421
|
-
this.
|
|
2422
|
-
this.
|
|
2423
|
-
os: super.
|
|
2424
|
-
rp: super.
|
|
2425
|
-
cikey: this.
|
|
2426
|
-
runtimeVersion: this.
|
|
2427
|
-
language: this.
|
|
2428
|
-
version: this.
|
|
2429
|
-
attach: this.
|
|
2439
|
+
this.runtimeVersion = process.version;
|
|
2440
|
+
this.language = STATSBEAT_LANGUAGE;
|
|
2441
|
+
this.version = packageVersion;
|
|
2442
|
+
this.cikey = options.instrumentationKey;
|
|
2443
|
+
this.featureStatsbeatGauge = this.longIntervalStatsbeatMeter.createObservableGauge(StatsbeatCounter.FEATURE);
|
|
2444
|
+
this.attachStatsbeatGauge = this.longIntervalStatsbeatMeter.createObservableGauge(StatsbeatCounter.ATTACH);
|
|
2445
|
+
this.commonProperties = {
|
|
2446
|
+
os: super.os,
|
|
2447
|
+
rp: super.resourceProvider,
|
|
2448
|
+
cikey: this.cikey,
|
|
2449
|
+
runtimeVersion: this.runtimeVersion,
|
|
2450
|
+
language: this.language,
|
|
2451
|
+
version: this.version,
|
|
2452
|
+
attach: this.attach,
|
|
2430
2453
|
};
|
|
2431
|
-
this.
|
|
2432
|
-
rpId: super.
|
|
2454
|
+
this.attachProperties = {
|
|
2455
|
+
rpId: super.resourceIdentifier,
|
|
2433
2456
|
};
|
|
2434
|
-
this.
|
|
2435
|
-
this.
|
|
2457
|
+
this.isInitialized = true;
|
|
2458
|
+
this.initialize();
|
|
2436
2459
|
}
|
|
2437
|
-
async
|
|
2460
|
+
async initialize() {
|
|
2438
2461
|
try {
|
|
2439
|
-
await this.
|
|
2462
|
+
await this.getResourceProvider();
|
|
2440
2463
|
// Add long interval observable callbacks
|
|
2441
|
-
this.
|
|
2442
|
-
this.
|
|
2464
|
+
this.attachStatsbeatGauge.addCallback(this.attachCallback.bind(this));
|
|
2465
|
+
this.longIntervalStatsbeatMeter.addBatchObservableCallback(this.featureCallback.bind(this), [
|
|
2466
|
+
this.featureStatsbeatGauge,
|
|
2467
|
+
]);
|
|
2443
2468
|
// Export Feature/Attach Statsbeat once upon app initialization
|
|
2444
|
-
this.
|
|
2469
|
+
this.longIntervalAzureExporter.export((await this.longIntervalMetricReader.collect()).resourceMetrics, (result) => {
|
|
2445
2470
|
if (result.code !== core.ExportResultCode.SUCCESS) {
|
|
2446
2471
|
api.diag.error(`LongIntervalStatsbeat: metrics export failed (error ${result.error})`);
|
|
2447
2472
|
}
|
|
@@ -2451,26 +2476,23 @@ class LongIntervalStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
2451
2476
|
api.diag.debug("Call to get the resource provider failed.");
|
|
2452
2477
|
}
|
|
2453
2478
|
}
|
|
2454
|
-
|
|
2479
|
+
featureCallback(observableResult) {
|
|
2455
2480
|
let attributes;
|
|
2456
|
-
if (this.
|
|
2457
|
-
attributes = Object.assign(Object.assign({}, this.
|
|
2458
|
-
observableResult.observe(this.
|
|
2481
|
+
if (this.instrumentation) {
|
|
2482
|
+
attributes = Object.assign(Object.assign({}, this.commonProperties), { feature: this.instrumentation, type: StatsbeatFeatureType.INSTRUMENTATION });
|
|
2483
|
+
observableResult.observe(this.featureStatsbeatGauge, 1, Object.assign({}, attributes));
|
|
2459
2484
|
}
|
|
2460
|
-
if (this.
|
|
2461
|
-
attributes = Object.assign(Object.assign({}, this.
|
|
2462
|
-
observableResult.observe(this.
|
|
2485
|
+
if (this.feature) {
|
|
2486
|
+
attributes = Object.assign(Object.assign({}, this.commonProperties), { feature: this.feature, type: StatsbeatFeatureType.FEATURE });
|
|
2487
|
+
observableResult.observe(this.featureStatsbeatGauge, 1, Object.assign({}, attributes));
|
|
2463
2488
|
}
|
|
2464
2489
|
}
|
|
2465
|
-
|
|
2466
|
-
|
|
2490
|
+
attachCallback(observableResult) {
|
|
2491
|
+
const attributes = Object.assign(Object.assign({}, this.commonProperties), this.attachProperties);
|
|
2467
2492
|
observableResult.observe(1, attributes);
|
|
2468
2493
|
}
|
|
2469
|
-
isInitialized() {
|
|
2470
|
-
return this._isInitialized;
|
|
2471
|
-
}
|
|
2472
2494
|
shutdown() {
|
|
2473
|
-
this.
|
|
2495
|
+
return this.longIntervalStatsbeatMeterProvider.shutdown();
|
|
2474
2496
|
}
|
|
2475
2497
|
}
|
|
2476
2498
|
/**
|
|
@@ -2524,29 +2546,30 @@ function msToTimeSpan(ms) {
|
|
|
2524
2546
|
}
|
|
2525
2547
|
|
|
2526
2548
|
// Copyright (c) Microsoft Corporation.
|
|
2549
|
+
// Licensed under the MIT license.
|
|
2527
2550
|
const DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS = 60000;
|
|
2528
2551
|
/**
|
|
2529
2552
|
* Base sender class
|
|
2530
2553
|
* @internal
|
|
2531
2554
|
*/
|
|
2532
2555
|
class BaseSender {
|
|
2533
|
-
constructor(
|
|
2534
|
-
this.
|
|
2535
|
-
this.
|
|
2536
|
-
this.
|
|
2537
|
-
this.
|
|
2538
|
-
if (trackStatsbeat) {
|
|
2556
|
+
constructor(options) {
|
|
2557
|
+
this.statsbeatFailureCount = 0;
|
|
2558
|
+
this.batchSendRetryIntervalMs = DEFAULT_BATCH_SEND_RETRY_INTERVAL_MS;
|
|
2559
|
+
this.numConsecutiveRedirects = 0;
|
|
2560
|
+
this.persister = new FileSystemPersist(options.instrumentationKey, options.exporterOptions);
|
|
2561
|
+
if (options.trackStatsbeat) {
|
|
2539
2562
|
// Initialize statsbeatMetrics
|
|
2540
|
-
this.
|
|
2541
|
-
instrumentationKey: instrumentationKey,
|
|
2542
|
-
endpointUrl: endpointUrl,
|
|
2563
|
+
this.networkStatsbeatMetrics = new NetworkStatsbeatMetrics({
|
|
2564
|
+
instrumentationKey: options.instrumentationKey,
|
|
2565
|
+
endpointUrl: options.endpointUrl,
|
|
2543
2566
|
});
|
|
2544
|
-
this.
|
|
2545
|
-
instrumentationKey: instrumentationKey,
|
|
2546
|
-
endpointUrl: endpointUrl,
|
|
2567
|
+
this.longIntervalStatsbeatMetrics = getInstance$1({
|
|
2568
|
+
instrumentationKey: options.instrumentationKey,
|
|
2569
|
+
endpointUrl: options.endpointUrl,
|
|
2547
2570
|
});
|
|
2548
2571
|
}
|
|
2549
|
-
this.
|
|
2572
|
+
this.retryTimer = null;
|
|
2550
2573
|
}
|
|
2551
2574
|
/**
|
|
2552
2575
|
* Export envelopes
|
|
@@ -2562,24 +2585,24 @@ class BaseSender {
|
|
|
2562
2585
|
const { result, statusCode } = await this.send(envelopes);
|
|
2563
2586
|
const endTime = new Date().getTime();
|
|
2564
2587
|
const duration = endTime - startTime;
|
|
2565
|
-
this.
|
|
2588
|
+
this.numConsecutiveRedirects = 0;
|
|
2566
2589
|
if (statusCode === 200) {
|
|
2567
2590
|
// Success -- @todo: start retry timer
|
|
2568
|
-
if (!this.
|
|
2569
|
-
this.
|
|
2570
|
-
this.
|
|
2571
|
-
this.
|
|
2572
|
-
}, this.
|
|
2573
|
-
this.
|
|
2591
|
+
if (!this.retryTimer) {
|
|
2592
|
+
this.retryTimer = setTimeout(() => {
|
|
2593
|
+
this.retryTimer = null;
|
|
2594
|
+
this.sendFirstPersistedFile();
|
|
2595
|
+
}, this.batchSendRetryIntervalMs);
|
|
2596
|
+
this.retryTimer.unref();
|
|
2574
2597
|
}
|
|
2575
2598
|
// If we are not exportings statsbeat and statsbeat is not disabled -- count success
|
|
2576
|
-
(_a = this.
|
|
2599
|
+
(_a = this.networkStatsbeatMetrics) === null || _a === void 0 ? void 0 : _a.countSuccess(duration);
|
|
2577
2600
|
return { code: core.ExportResultCode.SUCCESS };
|
|
2578
2601
|
}
|
|
2579
2602
|
else if (statusCode && isRetriable(statusCode)) {
|
|
2580
2603
|
// Failed -- persist failed data
|
|
2581
2604
|
if (statusCode === 429 || statusCode === 439) {
|
|
2582
|
-
(_b = this.
|
|
2605
|
+
(_b = this.networkStatsbeatMetrics) === null || _b === void 0 ? void 0 : _b.countThrottle(statusCode);
|
|
2583
2606
|
}
|
|
2584
2607
|
if (result) {
|
|
2585
2608
|
api.diag.info(result);
|
|
@@ -2593,31 +2616,31 @@ class BaseSender {
|
|
|
2593
2616
|
});
|
|
2594
2617
|
}
|
|
2595
2618
|
if (filteredEnvelopes.length > 0) {
|
|
2596
|
-
(_c = this.
|
|
2619
|
+
(_c = this.networkStatsbeatMetrics) === null || _c === void 0 ? void 0 : _c.countRetry(statusCode);
|
|
2597
2620
|
// calls resultCallback(ExportResult) based on result of persister.push
|
|
2598
|
-
return await this.
|
|
2621
|
+
return await this.persist(filteredEnvelopes);
|
|
2599
2622
|
}
|
|
2600
2623
|
// Failed -- not retriable
|
|
2601
|
-
(_d = this.
|
|
2624
|
+
(_d = this.networkStatsbeatMetrics) === null || _d === void 0 ? void 0 : _d.countFailure(duration, statusCode);
|
|
2602
2625
|
return {
|
|
2603
2626
|
code: core.ExportResultCode.FAILED,
|
|
2604
2627
|
};
|
|
2605
2628
|
}
|
|
2606
2629
|
else {
|
|
2607
2630
|
// calls resultCallback(ExportResult) based on result of persister.push
|
|
2608
|
-
(_e = this.
|
|
2609
|
-
return await this.
|
|
2631
|
+
(_e = this.networkStatsbeatMetrics) === null || _e === void 0 ? void 0 : _e.countRetry(statusCode);
|
|
2632
|
+
return await this.persist(envelopes);
|
|
2610
2633
|
}
|
|
2611
2634
|
}
|
|
2612
2635
|
else {
|
|
2613
2636
|
// Failed -- not retriable
|
|
2614
|
-
if (this.
|
|
2637
|
+
if (this.networkStatsbeatMetrics) {
|
|
2615
2638
|
if (statusCode) {
|
|
2616
|
-
this.
|
|
2639
|
+
this.networkStatsbeatMetrics.countFailure(duration, statusCode);
|
|
2617
2640
|
}
|
|
2618
2641
|
}
|
|
2619
2642
|
else {
|
|
2620
|
-
this.
|
|
2643
|
+
this.incrementStatsbeatFailure();
|
|
2621
2644
|
}
|
|
2622
2645
|
return {
|
|
2623
2646
|
code: core.ExportResultCode.FAILED,
|
|
@@ -2630,9 +2653,9 @@ class BaseSender {
|
|
|
2630
2653
|
(restError.statusCode === 307 || // Temporary redirect
|
|
2631
2654
|
restError.statusCode === 308)) {
|
|
2632
2655
|
// Permanent redirect
|
|
2633
|
-
this.
|
|
2656
|
+
this.numConsecutiveRedirects++;
|
|
2634
2657
|
// To prevent circular redirects
|
|
2635
|
-
if (this.
|
|
2658
|
+
if (this.numConsecutiveRedirects < 10) {
|
|
2636
2659
|
if (restError.response && restError.response.headers) {
|
|
2637
2660
|
const location = restError.response.headers.get("location");
|
|
2638
2661
|
if (location) {
|
|
@@ -2644,23 +2667,23 @@ class BaseSender {
|
|
|
2644
2667
|
}
|
|
2645
2668
|
}
|
|
2646
2669
|
else {
|
|
2647
|
-
|
|
2648
|
-
(_f = this.
|
|
2670
|
+
const redirectError = new Error("Circular redirect");
|
|
2671
|
+
(_f = this.networkStatsbeatMetrics) === null || _f === void 0 ? void 0 : _f.countException(redirectError);
|
|
2649
2672
|
return { code: core.ExportResultCode.FAILED, error: redirectError };
|
|
2650
2673
|
}
|
|
2651
2674
|
}
|
|
2652
2675
|
else if (restError.statusCode && isRetriable(restError.statusCode)) {
|
|
2653
|
-
(_g = this.
|
|
2654
|
-
return
|
|
2676
|
+
(_g = this.networkStatsbeatMetrics) === null || _g === void 0 ? void 0 : _g.countRetry(restError.statusCode);
|
|
2677
|
+
return this.persist(envelopes);
|
|
2655
2678
|
}
|
|
2656
|
-
if (this.
|
|
2679
|
+
if (this.isNetworkError(restError)) {
|
|
2657
2680
|
if (restError.statusCode) {
|
|
2658
|
-
(_h = this.
|
|
2681
|
+
(_h = this.networkStatsbeatMetrics) === null || _h === void 0 ? void 0 : _h.countRetry(restError.statusCode);
|
|
2659
2682
|
}
|
|
2660
2683
|
api.diag.error("Retrying due to transient client side error. Error message:", restError.message);
|
|
2661
|
-
return
|
|
2684
|
+
return this.persist(envelopes);
|
|
2662
2685
|
}
|
|
2663
|
-
(_j = this.
|
|
2686
|
+
(_j = this.networkStatsbeatMetrics) === null || _j === void 0 ? void 0 : _j.countException(restError);
|
|
2664
2687
|
api.diag.error("Envelopes could not be exported and are not retriable. Error message:", restError.message);
|
|
2665
2688
|
return { code: core.ExportResultCode.FAILED, error: restError };
|
|
2666
2689
|
}
|
|
@@ -2668,9 +2691,9 @@ class BaseSender {
|
|
|
2668
2691
|
/**
|
|
2669
2692
|
* Persist envelopes to disk
|
|
2670
2693
|
*/
|
|
2671
|
-
async
|
|
2694
|
+
async persist(envelopes) {
|
|
2672
2695
|
try {
|
|
2673
|
-
const success = await this.
|
|
2696
|
+
const success = await this.persister.push(envelopes);
|
|
2674
2697
|
return success
|
|
2675
2698
|
? { code: core.ExportResultCode.SUCCESS }
|
|
2676
2699
|
: {
|
|
@@ -2683,19 +2706,19 @@ class BaseSender {
|
|
|
2683
2706
|
}
|
|
2684
2707
|
}
|
|
2685
2708
|
// Disable collection of statsbeat metrics after max failures
|
|
2686
|
-
|
|
2709
|
+
incrementStatsbeatFailure() {
|
|
2687
2710
|
var _a, _b;
|
|
2688
|
-
this.
|
|
2689
|
-
if (this.
|
|
2690
|
-
(_a = this.
|
|
2691
|
-
(_b = this.
|
|
2692
|
-
this.
|
|
2693
|
-
this.
|
|
2711
|
+
this.statsbeatFailureCount++;
|
|
2712
|
+
if (this.statsbeatFailureCount > MAX_STATSBEAT_FAILURES) {
|
|
2713
|
+
(_a = this.networkStatsbeatMetrics) === null || _a === void 0 ? void 0 : _a.shutdown();
|
|
2714
|
+
(_b = this.longIntervalStatsbeatMetrics) === null || _b === void 0 ? void 0 : _b.shutdown();
|
|
2715
|
+
this.networkStatsbeatMetrics = undefined;
|
|
2716
|
+
this.statsbeatFailureCount = 0;
|
|
2694
2717
|
}
|
|
2695
2718
|
}
|
|
2696
|
-
async
|
|
2719
|
+
async sendFirstPersistedFile() {
|
|
2697
2720
|
try {
|
|
2698
|
-
const envelopes = (await this.
|
|
2721
|
+
const envelopes = (await this.persister.shift());
|
|
2699
2722
|
if (envelopes) {
|
|
2700
2723
|
await this.send(envelopes);
|
|
2701
2724
|
}
|
|
@@ -2704,7 +2727,7 @@ class BaseSender {
|
|
|
2704
2727
|
api.diag.warn(`Failed to fetch persisted file`, err);
|
|
2705
2728
|
}
|
|
2706
2729
|
}
|
|
2707
|
-
|
|
2730
|
+
isNetworkError(error) {
|
|
2708
2731
|
if (error && error.code && error.code === "REQUEST_SEND_ERROR") {
|
|
2709
2732
|
return true;
|
|
2710
2733
|
}
|
|
@@ -2713,23 +2736,30 @@ class BaseSender {
|
|
|
2713
2736
|
}
|
|
2714
2737
|
|
|
2715
2738
|
// Copyright (c) Microsoft Corporation.
|
|
2739
|
+
// Licensed under the MIT license.
|
|
2716
2740
|
const applicationInsightsResource = "https://monitor.azure.com//.default";
|
|
2717
2741
|
/**
|
|
2718
2742
|
* Exporter HTTP sender class
|
|
2719
2743
|
* @internal
|
|
2720
2744
|
*/
|
|
2721
2745
|
class HttpSender extends BaseSender {
|
|
2722
|
-
constructor(
|
|
2723
|
-
super(
|
|
2746
|
+
constructor(options) {
|
|
2747
|
+
super(options);
|
|
2724
2748
|
// Build endpoint using provided configuration or default values
|
|
2725
|
-
this.
|
|
2726
|
-
if (
|
|
2749
|
+
this.appInsightsClientOptions = Object.assign({ host: options.endpointUrl }, options.exporterOptions);
|
|
2750
|
+
if (this.appInsightsClientOptions.credential) {
|
|
2727
2751
|
// Add credentialScopes
|
|
2728
|
-
options.
|
|
2752
|
+
if (options.aadAudience) {
|
|
2753
|
+
this.appInsightsClientOptions.credentialScopes = [options.aadAudience];
|
|
2754
|
+
}
|
|
2755
|
+
else {
|
|
2756
|
+
// Default
|
|
2757
|
+
this.appInsightsClientOptions.credentialScopes = [applicationInsightsResource];
|
|
2758
|
+
}
|
|
2729
2759
|
}
|
|
2730
|
-
this.
|
|
2760
|
+
this.appInsightsClient = new ApplicationInsightsClient(this.appInsightsClientOptions);
|
|
2731
2761
|
// Handle redirects in HTTP Sender
|
|
2732
|
-
this.
|
|
2762
|
+
this.appInsightsClient.pipeline.removePolicy({ name: coreRestPipeline.redirectPolicyName });
|
|
2733
2763
|
}
|
|
2734
2764
|
/**
|
|
2735
2765
|
* Send Azure envelopes
|
|
@@ -2737,21 +2767,16 @@ class HttpSender extends BaseSender {
|
|
|
2737
2767
|
*/
|
|
2738
2768
|
async send(envelopes) {
|
|
2739
2769
|
var _a;
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
options.onResponse(rawResponse, flatResponse);
|
|
2747
|
-
}
|
|
2770
|
+
const options = {};
|
|
2771
|
+
let response;
|
|
2772
|
+
function onResponse(rawResponse, flatResponse) {
|
|
2773
|
+
response = rawResponse;
|
|
2774
|
+
if (options.onResponse) {
|
|
2775
|
+
options.onResponse(rawResponse, flatResponse);
|
|
2748
2776
|
}
|
|
2749
|
-
await this._appInsightsClient.track(envelopes, Object.assign(Object.assign({}, options), { onResponse }));
|
|
2750
|
-
return { statusCode: response === null || response === void 0 ? void 0 : response.status, result: (_a = response === null || response === void 0 ? void 0 : response.bodyAsText) !== null && _a !== void 0 ? _a : "" };
|
|
2751
|
-
}
|
|
2752
|
-
catch (e) {
|
|
2753
|
-
throw e;
|
|
2754
2777
|
}
|
|
2778
|
+
await this.appInsightsClient.track(envelopes, Object.assign(Object.assign({}, options), { onResponse }));
|
|
2779
|
+
return { statusCode: response === null || response === void 0 ? void 0 : response.status, result: (_a = response === null || response === void 0 ? void 0 : response.bodyAsText) !== null && _a !== void 0 ? _a : "" };
|
|
2755
2780
|
}
|
|
2756
2781
|
/**
|
|
2757
2782
|
* Shutdown sender
|
|
@@ -2762,15 +2787,16 @@ class HttpSender extends BaseSender {
|
|
|
2762
2787
|
}
|
|
2763
2788
|
handlePermanentRedirect(location) {
|
|
2764
2789
|
if (location) {
|
|
2765
|
-
const locUrl = new
|
|
2790
|
+
const locUrl = new url.URL(location);
|
|
2766
2791
|
if (locUrl && locUrl.host) {
|
|
2767
|
-
this.
|
|
2792
|
+
this.appInsightsClient.host = "https://" + locUrl.host;
|
|
2768
2793
|
}
|
|
2769
2794
|
}
|
|
2770
2795
|
}
|
|
2771
2796
|
}
|
|
2772
2797
|
|
|
2773
2798
|
// Copyright (c) Microsoft Corporation.
|
|
2799
|
+
// Licensed under the MIT license.
|
|
2774
2800
|
let instance = null;
|
|
2775
2801
|
/**
|
|
2776
2802
|
* Azure Telemetry context.
|
|
@@ -2790,13 +2816,13 @@ class Context {
|
|
|
2790
2816
|
[Context.nodeVersion] = node.split(".");
|
|
2791
2817
|
Context.opentelemetryVersion = core.SDK_INFO[semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_VERSION];
|
|
2792
2818
|
Context.sdkVersion = packageVersion;
|
|
2793
|
-
|
|
2819
|
+
const prefix = process.env["AZURE_MONITOR_AGENT_PREFIX"]
|
|
2794
2820
|
? process.env["AZURE_MONITOR_AGENT_PREFIX"]
|
|
2795
2821
|
: "";
|
|
2796
|
-
|
|
2822
|
+
const version = process.env["AZURE_MONITOR_DISTRO_VERSION"]
|
|
2797
2823
|
? `dst${process.env["AZURE_MONITOR_DISTRO_VERSION"]}`
|
|
2798
2824
|
: `ext${Context.sdkVersion}`;
|
|
2799
|
-
|
|
2825
|
+
const internalSdkVersion = `${prefix}node${Context.nodeVersion}:otel${Context.opentelemetryVersion}:${version}`;
|
|
2800
2826
|
this.tags[KnownContextTagKeys.AiInternalSdkVersion] = internalSdkVersion;
|
|
2801
2827
|
}
|
|
2802
2828
|
}
|
|
@@ -2815,6 +2841,7 @@ function getInstance() {
|
|
|
2815
2841
|
}
|
|
2816
2842
|
|
|
2817
2843
|
// Copyright (c) Microsoft Corporation.
|
|
2844
|
+
// Licensed under the MIT license.
|
|
2818
2845
|
function createTagsFromResource(resource) {
|
|
2819
2846
|
const context = getInstance();
|
|
2820
2847
|
const tags = Object.assign({}, context.tags);
|
|
@@ -2892,7 +2919,7 @@ function getCloudRoleInstance(resource) {
|
|
|
2892
2919
|
return String(serviceInstanceId);
|
|
2893
2920
|
}
|
|
2894
2921
|
// Default
|
|
2895
|
-
return
|
|
2922
|
+
return os$1 && os$1.hostname();
|
|
2896
2923
|
}
|
|
2897
2924
|
function isSqlDB(dbSystem) {
|
|
2898
2925
|
return (dbSystem === semanticConventions.DbSystemValues.DB2 ||
|
|
@@ -2976,20 +3003,20 @@ function createResourceMetricEnvelope(resource, instrumentationKey) {
|
|
|
2976
3003
|
for (const key of Object.keys(resource.attributes)) {
|
|
2977
3004
|
// Avoid duplication ignoring fields already mapped.
|
|
2978
3005
|
if (!(key.startsWith("_MS.") ||
|
|
2979
|
-
key
|
|
2980
|
-
key
|
|
2981
|
-
key
|
|
3006
|
+
key === semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_VERSION ||
|
|
3007
|
+
key === semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE ||
|
|
3008
|
+
key === semanticConventions.SemanticResourceAttributes.TELEMETRY_SDK_NAME)) {
|
|
2982
3009
|
resourceAttributes[key] = resource.attributes[key];
|
|
2983
3010
|
}
|
|
2984
3011
|
}
|
|
2985
3012
|
// Only send event when resource attributes are available
|
|
2986
3013
|
if (Object.keys(resourceAttributes).length > 0) {
|
|
2987
|
-
|
|
3014
|
+
const baseData = {
|
|
2988
3015
|
version: 2,
|
|
2989
3016
|
metrics: [{ name: "_OTELRESOURCE_", value: 1 }],
|
|
2990
3017
|
properties: resourceAttributes,
|
|
2991
3018
|
};
|
|
2992
|
-
|
|
3019
|
+
const envelope = {
|
|
2993
3020
|
name: "Microsoft.ApplicationInsights.Metric",
|
|
2994
3021
|
time: new Date(),
|
|
2995
3022
|
sampleRate: 100,
|
|
@@ -3026,6 +3053,7 @@ const MicrosoftEventHub = "Microsoft.EventHub";
|
|
|
3026
3053
|
const MessageBusDestination = "message_bus.destination";
|
|
3027
3054
|
|
|
3028
3055
|
// Copyright (c) Microsoft Corporation.
|
|
3056
|
+
// Licensed under the MIT license.
|
|
3029
3057
|
/**
|
|
3030
3058
|
* Average span.links[].attributes.enqueuedTime
|
|
3031
3059
|
*/
|
|
@@ -3072,6 +3100,7 @@ const parseEventHubSpan = (span, baseData) => {
|
|
|
3072
3100
|
};
|
|
3073
3101
|
|
|
3074
3102
|
// Copyright (c) Microsoft Corporation.
|
|
3103
|
+
// Licensed under the MIT license.
|
|
3075
3104
|
function createTagsFromSpan(span) {
|
|
3076
3105
|
const tags = createTagsFromResource(span.resource);
|
|
3077
3106
|
tags[KnownContextTagKeys.AiOperationId] = span.spanContext().traceId;
|
|
@@ -3124,21 +3153,21 @@ function createPropertiesFromSpanAttributes(attributes) {
|
|
|
3124
3153
|
for (const key of Object.keys(attributes)) {
|
|
3125
3154
|
// Avoid duplication ignoring fields already mapped.
|
|
3126
3155
|
if (!(key.startsWith("_MS.") ||
|
|
3127
|
-
key
|
|
3128
|
-
key
|
|
3129
|
-
key
|
|
3130
|
-
key
|
|
3131
|
-
key
|
|
3132
|
-
key
|
|
3133
|
-
key
|
|
3134
|
-
key
|
|
3135
|
-
key
|
|
3136
|
-
key
|
|
3137
|
-
key
|
|
3138
|
-
key
|
|
3139
|
-
key
|
|
3140
|
-
key
|
|
3141
|
-
key
|
|
3156
|
+
key === semanticConventions.SemanticAttributes.NET_PEER_IP ||
|
|
3157
|
+
key === semanticConventions.SemanticAttributes.NET_PEER_NAME ||
|
|
3158
|
+
key === semanticConventions.SemanticAttributes.PEER_SERVICE ||
|
|
3159
|
+
key === semanticConventions.SemanticAttributes.HTTP_METHOD ||
|
|
3160
|
+
key === semanticConventions.SemanticAttributes.HTTP_URL ||
|
|
3161
|
+
key === semanticConventions.SemanticAttributes.HTTP_STATUS_CODE ||
|
|
3162
|
+
key === semanticConventions.SemanticAttributes.HTTP_ROUTE ||
|
|
3163
|
+
key === semanticConventions.SemanticAttributes.HTTP_HOST ||
|
|
3164
|
+
key === semanticConventions.SemanticAttributes.HTTP_URL ||
|
|
3165
|
+
key === semanticConventions.SemanticAttributes.DB_SYSTEM ||
|
|
3166
|
+
key === semanticConventions.SemanticAttributes.DB_STATEMENT ||
|
|
3167
|
+
key === semanticConventions.SemanticAttributes.DB_OPERATION ||
|
|
3168
|
+
key === semanticConventions.SemanticAttributes.DB_NAME ||
|
|
3169
|
+
key === semanticConventions.SemanticAttributes.RPC_SYSTEM ||
|
|
3170
|
+
key === semanticConventions.SemanticAttributes.RPC_GRPC_STATUS_CODE)) {
|
|
3142
3171
|
properties[key] = attributes[key];
|
|
3143
3172
|
}
|
|
3144
3173
|
}
|
|
@@ -3161,7 +3190,7 @@ function createDependencyData(span) {
|
|
|
3161
3190
|
const remoteDependencyData = {
|
|
3162
3191
|
name: span.name,
|
|
3163
3192
|
id: `${span.spanContext().spanId}`,
|
|
3164
|
-
success: span.status.code
|
|
3193
|
+
success: span.status.code !== api.SpanStatusCode.ERROR,
|
|
3165
3194
|
resultCode: "0",
|
|
3166
3195
|
type: "Dependency",
|
|
3167
3196
|
duration: msToTimeSpan(core.hrTimeToMilliseconds(span.duration)),
|
|
@@ -3198,10 +3227,11 @@ function createDependencyData(span) {
|
|
|
3198
3227
|
// Remove default port
|
|
3199
3228
|
const portRegex = new RegExp(/(https?)(:\/\/.*)(:\d+)(\S*)/);
|
|
3200
3229
|
const res = portRegex.exec(target);
|
|
3201
|
-
if (res
|
|
3230
|
+
if (res !== null) {
|
|
3202
3231
|
const protocol = res[1];
|
|
3203
3232
|
const port = res[3];
|
|
3204
|
-
if ((protocol
|
|
3233
|
+
if ((protocol === "https" && port === ":443") ||
|
|
3234
|
+
(protocol === "http" && port === ":80")) {
|
|
3205
3235
|
// Drop port
|
|
3206
3236
|
target = res[1] + res[2] + res[4];
|
|
3207
3237
|
}
|
|
@@ -3269,7 +3299,7 @@ function createDependencyData(span) {
|
|
|
3269
3299
|
function createRequestData(span) {
|
|
3270
3300
|
const requestData = {
|
|
3271
3301
|
id: `${span.spanContext().spanId}`,
|
|
3272
|
-
success: span.status.code
|
|
3302
|
+
success: span.status.code !== api.SpanStatusCode.ERROR,
|
|
3273
3303
|
responseCode: "0",
|
|
3274
3304
|
duration: msToTimeSpan(core.hrTimeToMilliseconds(span.duration)),
|
|
3275
3305
|
version: 2,
|
|
@@ -3369,7 +3399,7 @@ function spanEventsToEnvelopes(span, ikey) {
|
|
|
3369
3399
|
tags[KnownContextTagKeys.AiOperationParentId] = spanId;
|
|
3370
3400
|
}
|
|
3371
3401
|
// Only generate exception telemetry for incoming requests
|
|
3372
|
-
if (event.name
|
|
3402
|
+
if (event.name === "exception" && span.kind === api.SpanKind.SERVER) {
|
|
3373
3403
|
name = "Microsoft.ApplicationInsights.Exception";
|
|
3374
3404
|
baseType = "ExceptionData";
|
|
3375
3405
|
let typeName = "";
|
|
@@ -3387,7 +3417,7 @@ function spanEventsToEnvelopes(span, ikey) {
|
|
|
3387
3417
|
message = String(exceptionMsg);
|
|
3388
3418
|
}
|
|
3389
3419
|
const escaped = event.attributes[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED];
|
|
3390
|
-
if (escaped
|
|
3420
|
+
if (escaped !== undefined) {
|
|
3391
3421
|
properties[semanticConventions.SemanticAttributes.EXCEPTION_ESCAPED] = String(escaped);
|
|
3392
3422
|
}
|
|
3393
3423
|
}
|
|
@@ -3437,6 +3467,7 @@ function spanEventsToEnvelopes(span, ikey) {
|
|
|
3437
3467
|
}
|
|
3438
3468
|
|
|
3439
3469
|
// Copyright (c) Microsoft Corporation.
|
|
3470
|
+
// Licensed under the MIT license.
|
|
3440
3471
|
/**
|
|
3441
3472
|
* Azure Monitor OpenTelemetry Trace Exporter.
|
|
3442
3473
|
*/
|
|
@@ -3450,8 +3481,14 @@ class AzureMonitorTraceExporter extends AzureMonitorBaseExporter {
|
|
|
3450
3481
|
/**
|
|
3451
3482
|
* Flag to determine if Exporter is shutdown.
|
|
3452
3483
|
*/
|
|
3453
|
-
this.
|
|
3454
|
-
this.
|
|
3484
|
+
this.isShutdown = false;
|
|
3485
|
+
this.sender = new HttpSender({
|
|
3486
|
+
endpointUrl: this.endpointUrl,
|
|
3487
|
+
instrumentationKey: this.instrumentationKey,
|
|
3488
|
+
trackStatsbeat: this.trackStatsbeat,
|
|
3489
|
+
exporterOptions: options,
|
|
3490
|
+
aadAudience: this.aadAudience,
|
|
3491
|
+
});
|
|
3455
3492
|
api.diag.debug("AzureMonitorTraceExporter was successfully setup");
|
|
3456
3493
|
}
|
|
3457
3494
|
/**
|
|
@@ -3460,26 +3497,26 @@ class AzureMonitorTraceExporter extends AzureMonitorBaseExporter {
|
|
|
3460
3497
|
* @param resultCallback - Result callback.
|
|
3461
3498
|
*/
|
|
3462
3499
|
async export(spans, resultCallback) {
|
|
3463
|
-
if (this.
|
|
3500
|
+
if (this.isShutdown) {
|
|
3464
3501
|
api.diag.info("Exporter shut down. Failed to export spans.");
|
|
3465
3502
|
setTimeout(() => resultCallback({ code: core.ExportResultCode.FAILED }), 0);
|
|
3466
3503
|
return;
|
|
3467
3504
|
}
|
|
3468
3505
|
api.diag.info(`Exporting ${spans.length} span(s). Converting to envelopes...`);
|
|
3469
3506
|
if (spans.length > 0) {
|
|
3470
|
-
|
|
3507
|
+
const envelopes = [];
|
|
3471
3508
|
const resourceMetricEnvelope = createResourceMetricEnvelope(spans[0].resource, this.instrumentationKey);
|
|
3472
3509
|
if (resourceMetricEnvelope) {
|
|
3473
3510
|
envelopes.push(resourceMetricEnvelope);
|
|
3474
3511
|
}
|
|
3475
3512
|
spans.forEach((span) => {
|
|
3476
3513
|
envelopes.push(readableSpanToEnvelope(span, this.instrumentationKey));
|
|
3477
|
-
|
|
3514
|
+
const spanEventEnvelopes = spanEventsToEnvelopes(span, this.instrumentationKey);
|
|
3478
3515
|
if (spanEventEnvelopes.length > 0) {
|
|
3479
3516
|
envelopes.push(...spanEventEnvelopes);
|
|
3480
3517
|
}
|
|
3481
3518
|
});
|
|
3482
|
-
resultCallback(await this.
|
|
3519
|
+
resultCallback(await this.sender.exportEnvelopes(envelopes));
|
|
3483
3520
|
}
|
|
3484
3521
|
// No data to export
|
|
3485
3522
|
resultCallback({ code: core.ExportResultCode.SUCCESS });
|
|
@@ -3488,13 +3525,14 @@ class AzureMonitorTraceExporter extends AzureMonitorBaseExporter {
|
|
|
3488
3525
|
* Shutdown AzureMonitorTraceExporter.
|
|
3489
3526
|
*/
|
|
3490
3527
|
async shutdown() {
|
|
3491
|
-
this.
|
|
3528
|
+
this.isShutdown = true;
|
|
3492
3529
|
api.diag.info("AzureMonitorTraceExporter shutting down");
|
|
3493
|
-
return this.
|
|
3530
|
+
return this.sender.shutdown();
|
|
3494
3531
|
}
|
|
3495
3532
|
}
|
|
3496
3533
|
|
|
3497
3534
|
// Copyright (c) Microsoft Corporation.
|
|
3535
|
+
// Licensed under the MIT license.
|
|
3498
3536
|
/**
|
|
3499
3537
|
* Azure Monitor OpenTelemetry Metric Exporter.
|
|
3500
3538
|
*/
|
|
@@ -3509,7 +3547,13 @@ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
|
|
|
3509
3547
|
* Flag to determine if Exporter is shutdown.
|
|
3510
3548
|
*/
|
|
3511
3549
|
this._isShutdown = false;
|
|
3512
|
-
this._sender = new HttpSender(
|
|
3550
|
+
this._sender = new HttpSender({
|
|
3551
|
+
endpointUrl: this.endpointUrl,
|
|
3552
|
+
instrumentationKey: this.instrumentationKey,
|
|
3553
|
+
trackStatsbeat: this.trackStatsbeat,
|
|
3554
|
+
exporterOptions: options,
|
|
3555
|
+
aadAudience: this.aadAudience,
|
|
3556
|
+
});
|
|
3513
3557
|
api.diag.debug("AzureMonitorMetricExporter was successfully setup");
|
|
3514
3558
|
}
|
|
3515
3559
|
/**
|
|
@@ -3524,9 +3568,9 @@ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
|
|
|
3524
3568
|
return;
|
|
3525
3569
|
}
|
|
3526
3570
|
api.diag.info(`Exporting ${metrics.scopeMetrics.length} metrics(s). Converting to envelopes...`);
|
|
3527
|
-
|
|
3571
|
+
const envelopes = resourceMetricsToEnvelope(metrics, this.instrumentationKey);
|
|
3528
3572
|
// Supress tracing until OpenTelemetry Metrics SDK support it
|
|
3529
|
-
api.context.with(core.suppressTracing(api.context.active()), async () => {
|
|
3573
|
+
await api.context.with(core.suppressTracing(api.context.active()), async () => {
|
|
3530
3574
|
resultCallback(await this._sender.exportEnvelopes(envelopes));
|
|
3531
3575
|
});
|
|
3532
3576
|
}
|
|
@@ -3542,8 +3586,8 @@ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
|
|
|
3542
3586
|
* Select aggregation temporality
|
|
3543
3587
|
*/
|
|
3544
3588
|
selectAggregationTemporality(instrumentType) {
|
|
3545
|
-
if (instrumentType
|
|
3546
|
-
instrumentType
|
|
3589
|
+
if (instrumentType === sdkMetrics.InstrumentType.UP_DOWN_COUNTER ||
|
|
3590
|
+
instrumentType === sdkMetrics.InstrumentType.OBSERVABLE_UP_DOWN_COUNTER) {
|
|
3547
3591
|
return sdkMetrics.AggregationTemporality.CUMULATIVE;
|
|
3548
3592
|
}
|
|
3549
3593
|
return sdkMetrics.AggregationTemporality.DELTA;
|
|
@@ -3557,13 +3601,14 @@ class AzureMonitorMetricExporter extends AzureMonitorBaseExporter {
|
|
|
3557
3601
|
}
|
|
3558
3602
|
|
|
3559
3603
|
// Copyright (c) Microsoft Corporation.
|
|
3604
|
+
// Licensed under the MIT license.
|
|
3560
3605
|
/**
|
|
3561
3606
|
* Log to Azure envelope parsing.
|
|
3562
3607
|
* @internal
|
|
3563
3608
|
*/
|
|
3564
3609
|
function logToEnvelope(log, ikey) {
|
|
3565
3610
|
const time = log.hrTime ? new Date(core.hrTimeToMilliseconds(log.hrTime)) : new Date();
|
|
3566
|
-
|
|
3611
|
+
const sampleRate = 100;
|
|
3567
3612
|
const instrumentationKey = ikey;
|
|
3568
3613
|
const tags = createTagsFromLog(log);
|
|
3569
3614
|
const [properties, measurements] = createPropertiesFromLog(log);
|
|
@@ -3572,13 +3617,13 @@ function logToEnvelope(log, ikey) {
|
|
|
3572
3617
|
let baseData;
|
|
3573
3618
|
if (!log.attributes[ApplicationInsightsBaseType]) {
|
|
3574
3619
|
// Get Exception attributes if available
|
|
3575
|
-
|
|
3620
|
+
const exceptionType = log.attributes[semanticConventions.SemanticAttributes.EXCEPTION_TYPE];
|
|
3576
3621
|
if (exceptionType) {
|
|
3577
|
-
|
|
3578
|
-
|
|
3622
|
+
const exceptionMessage = log.attributes[semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE];
|
|
3623
|
+
const exceptionStacktrace = log.attributes[semanticConventions.SemanticAttributes.EXCEPTION_STACKTRACE];
|
|
3579
3624
|
name = ApplicationInsightsExceptionName;
|
|
3580
3625
|
baseType = ApplicationInsightsExceptionBaseType;
|
|
3581
|
-
|
|
3626
|
+
const exceptionDetails = {
|
|
3582
3627
|
typeName: String(exceptionType),
|
|
3583
3628
|
message: String(exceptionMessage),
|
|
3584
3629
|
hasFullStack: exceptionStacktrace ? true : false,
|
|
@@ -3644,9 +3689,9 @@ function createPropertiesFromLog(log) {
|
|
|
3644
3689
|
for (const key of Object.keys(log.attributes)) {
|
|
3645
3690
|
// Avoid duplication ignoring fields already mapped.
|
|
3646
3691
|
if (!(key.startsWith("_MS.") ||
|
|
3647
|
-
key
|
|
3648
|
-
key
|
|
3649
|
-
key
|
|
3692
|
+
key === semanticConventions.SemanticAttributes.EXCEPTION_TYPE ||
|
|
3693
|
+
key === semanticConventions.SemanticAttributes.EXCEPTION_MESSAGE ||
|
|
3694
|
+
key === semanticConventions.SemanticAttributes.EXCEPTION_STACKTRACE)) {
|
|
3650
3695
|
properties[key] = log.attributes[key];
|
|
3651
3696
|
}
|
|
3652
3697
|
}
|
|
@@ -3730,6 +3775,7 @@ function getLegacyApplicationInsightsBaseData(log) {
|
|
|
3730
3775
|
}
|
|
3731
3776
|
|
|
3732
3777
|
// Copyright (c) Microsoft Corporation.
|
|
3778
|
+
// Licensed under the MIT license.
|
|
3733
3779
|
/**
|
|
3734
3780
|
* Azure Monitor OpenTelemetry Log Exporter.
|
|
3735
3781
|
*/
|
|
@@ -3744,7 +3790,13 @@ class AzureMonitorLogExporter extends AzureMonitorBaseExporter {
|
|
|
3744
3790
|
* Flag to determine if Exporter is shutdown.
|
|
3745
3791
|
*/
|
|
3746
3792
|
this._isShutdown = false;
|
|
3747
|
-
this._sender = new HttpSender(
|
|
3793
|
+
this._sender = new HttpSender({
|
|
3794
|
+
endpointUrl: this.endpointUrl,
|
|
3795
|
+
instrumentationKey: this.instrumentationKey,
|
|
3796
|
+
trackStatsbeat: this.trackStatsbeat,
|
|
3797
|
+
exporterOptions: options,
|
|
3798
|
+
aadAudience: this.aadAudience,
|
|
3799
|
+
});
|
|
3748
3800
|
api.diag.debug("AzureMonitorLogExporter was successfully setup");
|
|
3749
3801
|
}
|
|
3750
3802
|
/**
|
|
@@ -3759,15 +3811,15 @@ class AzureMonitorLogExporter extends AzureMonitorBaseExporter {
|
|
|
3759
3811
|
return;
|
|
3760
3812
|
}
|
|
3761
3813
|
api.diag.info(`Exporting ${logs.length} logs(s). Converting to envelopes...`);
|
|
3762
|
-
|
|
3814
|
+
const envelopes = [];
|
|
3763
3815
|
logs.forEach((log) => {
|
|
3764
|
-
|
|
3816
|
+
const envelope = logToEnvelope(log, this.instrumentationKey);
|
|
3765
3817
|
if (envelope) {
|
|
3766
3818
|
envelopes.push(envelope);
|
|
3767
3819
|
}
|
|
3768
3820
|
});
|
|
3769
3821
|
// Supress tracing until OpenTelemetry Logs SDK support it
|
|
3770
|
-
api.context.with(core.suppressTracing(api.context.active()), async () => {
|
|
3822
|
+
await api.context.with(core.suppressTracing(api.context.active()), async () => {
|
|
3771
3823
|
resultCallback(await this._sender.exportEnvelopes(envelopes));
|
|
3772
3824
|
});
|
|
3773
3825
|
}
|