@azure/monitor-opentelemetry-exporter 1.0.0-beta.31 → 1.0.0-beta.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/commonjs/Declarations/Constants.d.ts +5 -0
- package/dist/commonjs/Declarations/Constants.d.ts.map +1 -1
- package/dist/commonjs/Declarations/Constants.js +6 -1
- package/dist/commonjs/Declarations/Constants.js.map +1 -1
- package/dist/commonjs/export/base.js +25 -14
- package/dist/commonjs/export/base.js.map +1 -1
- package/dist/commonjs/export/log.js +5 -4
- package/dist/commonjs/export/log.js.map +1 -1
- package/dist/commonjs/export/metric.js +5 -4
- package/dist/commonjs/export/metric.js.map +1 -1
- package/dist/commonjs/export/statsbeat/customerStatsbeat.d.ts +125 -0
- package/dist/commonjs/export/statsbeat/customerStatsbeat.d.ts.map +1 -0
- package/dist/commonjs/export/statsbeat/customerStatsbeat.js +480 -0
- package/dist/commonjs/export/statsbeat/customerStatsbeat.js.map +1 -0
- package/dist/commonjs/export/statsbeat/longIntervalStatsbeatMetrics.d.ts +7 -7
- package/dist/commonjs/export/statsbeat/longIntervalStatsbeatMetrics.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/longIntervalStatsbeatMetrics.js +69 -30
- package/dist/commonjs/export/statsbeat/longIntervalStatsbeatMetrics.js.map +1 -1
- package/dist/commonjs/export/statsbeat/networkStatsbeatMetrics.d.ts +6 -1
- package/dist/commonjs/export/statsbeat/networkStatsbeatMetrics.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/networkStatsbeatMetrics.js +115 -43
- package/dist/commonjs/export/statsbeat/networkStatsbeatMetrics.js.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatExporter.d.ts +7 -0
- package/dist/commonjs/export/statsbeat/statsbeatExporter.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatExporter.js +25 -5
- package/dist/commonjs/export/statsbeat/statsbeatExporter.js.map +1 -1
- package/dist/commonjs/export/statsbeat/statsbeatMetrics.js +6 -8
- package/dist/commonjs/export/statsbeat/statsbeatMetrics.js.map +1 -1
- package/dist/commonjs/export/statsbeat/types.d.ts +52 -0
- package/dist/commonjs/export/statsbeat/types.d.ts.map +1 -1
- package/dist/commonjs/export/statsbeat/types.js +75 -1
- package/dist/commonjs/export/statsbeat/types.js.map +1 -1
- package/dist/commonjs/export/trace.js +6 -5
- package/dist/commonjs/export/trace.js.map +1 -1
- package/dist/commonjs/generated/applicationInsightsClient.js +9 -4
- package/dist/commonjs/generated/applicationInsightsClient.js.map +1 -1
- package/dist/commonjs/generated/models/mappers.js +145 -68
- package/dist/commonjs/generated/models/mappers.js.map +1 -1
- package/dist/commonjs/index.d.ts +2 -1
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +5 -3
- package/dist/commonjs/index.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 +101 -34
- package/dist/commonjs/platform/nodejs/baseSender.js.map +1 -1
- package/dist/commonjs/platform/nodejs/context/context.d.ts +0 -1
- package/dist/commonjs/platform/nodejs/context/context.d.ts.map +1 -1
- package/dist/commonjs/platform/nodejs/context/context.js +4 -8
- package/dist/commonjs/platform/nodejs/context/context.js.map +1 -1
- package/dist/commonjs/platform/nodejs/httpSender.js +11 -4
- package/dist/commonjs/platform/nodejs/httpSender.js.map +1 -1
- package/dist/commonjs/platform/nodejs/index.d.ts +1 -0
- package/dist/commonjs/platform/nodejs/index.d.ts.map +1 -1
- package/dist/commonjs/platform/nodejs/index.js +1 -0
- package/dist/commonjs/platform/nodejs/index.js.map +1 -1
- package/dist/commonjs/platform/nodejs/persist/fileAccessControl.js +7 -7
- package/dist/commonjs/platform/nodejs/persist/fileAccessControl.js.map +1 -1
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.d.ts +9 -1
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.d.ts.map +1 -1
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.js +37 -16
- package/dist/commonjs/platform/nodejs/persist/fileSystemPersist.js.map +1 -1
- package/dist/commonjs/{sampling.d.ts → sampling/percentageSampler.d.ts} +2 -3
- package/dist/commonjs/sampling/percentageSampler.d.ts.map +1 -0
- package/dist/commonjs/{sampling.js → sampling/percentageSampler.js} +6 -39
- package/dist/commonjs/sampling/percentageSampler.js.map +1 -0
- package/dist/commonjs/sampling/rateLimitedSampler.d.ts +58 -0
- package/dist/commonjs/sampling/rateLimitedSampler.d.ts.map +1 -0
- package/dist/commonjs/sampling/rateLimitedSampler.js +118 -0
- package/dist/commonjs/sampling/rateLimitedSampler.js.map +1 -0
- package/dist/commonjs/sampling/samplingUtils.d.ts +17 -0
- package/dist/commonjs/sampling/samplingUtils.d.ts.map +1 -0
- package/dist/commonjs/sampling/samplingUtils.js +94 -0
- package/dist/commonjs/sampling/samplingUtils.js.map +1 -0
- package/dist/commonjs/tsdoc-metadata.json +11 -11
- package/dist/commonjs/types.d.ts.map +1 -1
- package/dist/commonjs/types.js +1 -0
- package/dist/commonjs/types.js.map +1 -1
- package/dist/commonjs/utils/common.js +2 -3
- package/dist/commonjs/utils/common.js.map +1 -1
- package/dist/commonjs/utils/connectionStringParser.js +3 -3
- package/dist/commonjs/utils/connectionStringParser.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/eventhub.js +5 -2
- package/dist/commonjs/utils/eventhub.js.map +1 -1
- package/dist/commonjs/utils/logUtils.js +10 -9
- package/dist/commonjs/utils/logUtils.js.map +1 -1
- package/dist/commonjs/utils/metricUtils.d.ts.map +1 -1
- package/dist/commonjs/utils/metricUtils.js +6 -6
- package/dist/commonjs/utils/metricUtils.js.map +1 -1
- package/dist/commonjs/utils/spanUtils.d.ts.map +1 -1
- package/dist/commonjs/utils/spanUtils.js +16 -14
- package/dist/commonjs/utils/spanUtils.js.map +1 -1
- package/dist/esm/Declarations/Constants.d.ts +5 -0
- package/dist/esm/Declarations/Constants.d.ts.map +1 -1
- package/dist/esm/Declarations/Constants.js +5 -0
- package/dist/esm/Declarations/Constants.js.map +1 -1
- package/dist/esm/export/base.js +25 -14
- package/dist/esm/export/base.js.map +1 -1
- package/dist/esm/export/log.js +5 -4
- package/dist/esm/export/log.js.map +1 -1
- package/dist/esm/export/metric.js +5 -4
- package/dist/esm/export/metric.js.map +1 -1
- package/dist/esm/export/statsbeat/customerStatsbeat.d.ts +125 -0
- package/dist/esm/export/statsbeat/customerStatsbeat.d.ts.map +1 -0
- package/dist/esm/export/statsbeat/customerStatsbeat.js +475 -0
- package/dist/esm/export/statsbeat/customerStatsbeat.js.map +1 -0
- package/dist/esm/export/statsbeat/longIntervalStatsbeatMetrics.d.ts +7 -7
- package/dist/esm/export/statsbeat/longIntervalStatsbeatMetrics.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/longIntervalStatsbeatMetrics.js +68 -30
- package/dist/esm/export/statsbeat/longIntervalStatsbeatMetrics.js.map +1 -1
- package/dist/esm/export/statsbeat/networkStatsbeatMetrics.d.ts +6 -1
- package/dist/esm/export/statsbeat/networkStatsbeatMetrics.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/networkStatsbeatMetrics.js +115 -43
- package/dist/esm/export/statsbeat/networkStatsbeatMetrics.js.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatExporter.d.ts +7 -0
- package/dist/esm/export/statsbeat/statsbeatExporter.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatExporter.js +25 -5
- package/dist/esm/export/statsbeat/statsbeatExporter.js.map +1 -1
- package/dist/esm/export/statsbeat/statsbeatMetrics.js +6 -8
- package/dist/esm/export/statsbeat/statsbeatMetrics.js.map +1 -1
- package/dist/esm/export/statsbeat/types.d.ts +52 -0
- package/dist/esm/export/statsbeat/types.d.ts.map +1 -1
- package/dist/esm/export/statsbeat/types.js +73 -0
- package/dist/esm/export/statsbeat/types.js.map +1 -1
- package/dist/esm/export/trace.js +6 -5
- package/dist/esm/export/trace.js.map +1 -1
- package/dist/esm/generated/applicationInsightsClient.js +9 -4
- package/dist/esm/generated/applicationInsightsClient.js.map +1 -1
- package/dist/esm/generated/models/mappers.js +145 -68
- package/dist/esm/generated/models/mappers.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.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 +104 -37
- package/dist/esm/platform/nodejs/baseSender.js.map +1 -1
- package/dist/esm/platform/nodejs/context/context.d.ts +0 -1
- package/dist/esm/platform/nodejs/context/context.d.ts.map +1 -1
- package/dist/esm/platform/nodejs/context/context.js +4 -8
- package/dist/esm/platform/nodejs/context/context.js.map +1 -1
- package/dist/esm/platform/nodejs/httpSender.js +11 -4
- package/dist/esm/platform/nodejs/httpSender.js.map +1 -1
- package/dist/esm/platform/nodejs/index.d.ts +1 -0
- package/dist/esm/platform/nodejs/index.d.ts.map +1 -1
- package/dist/esm/platform/nodejs/index.js +1 -0
- package/dist/esm/platform/nodejs/index.js.map +1 -1
- package/dist/esm/platform/nodejs/persist/fileAccessControl.js +7 -7
- package/dist/esm/platform/nodejs/persist/fileAccessControl.js.map +1 -1
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.d.ts +9 -1
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.d.ts.map +1 -1
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.js +37 -16
- package/dist/esm/platform/nodejs/persist/fileSystemPersist.js.map +1 -1
- package/dist/esm/{sampling.d.ts → sampling/percentageSampler.d.ts} +2 -3
- package/dist/esm/sampling/percentageSampler.d.ts.map +1 -0
- package/dist/esm/{sampling.js → sampling/percentageSampler.js} +6 -39
- package/dist/esm/sampling/percentageSampler.js.map +1 -0
- package/dist/esm/sampling/rateLimitedSampler.d.ts +58 -0
- package/dist/esm/sampling/rateLimitedSampler.d.ts.map +1 -0
- package/dist/esm/sampling/rateLimitedSampler.js +114 -0
- package/dist/esm/sampling/rateLimitedSampler.js.map +1 -0
- package/dist/esm/sampling/samplingUtils.d.ts +17 -0
- package/dist/esm/sampling/samplingUtils.d.ts.map +1 -0
- package/dist/esm/sampling/samplingUtils.js +89 -0
- package/dist/esm/sampling/samplingUtils.js.map +1 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/types.js +2 -1
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/common.js +2 -3
- package/dist/esm/utils/common.js.map +1 -1
- package/dist/esm/utils/connectionStringParser.js +3 -3
- package/dist/esm/utils/connectionStringParser.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/eventhub.js +5 -2
- package/dist/esm/utils/eventhub.js.map +1 -1
- package/dist/esm/utils/logUtils.js +10 -9
- package/dist/esm/utils/logUtils.js.map +1 -1
- package/dist/esm/utils/metricUtils.d.ts.map +1 -1
- package/dist/esm/utils/metricUtils.js +6 -6
- package/dist/esm/utils/metricUtils.js.map +1 -1
- package/dist/esm/utils/spanUtils.d.ts.map +1 -1
- package/dist/esm/utils/spanUtils.js +16 -14
- package/dist/esm/utils/spanUtils.js.map +1 -1
- package/package.json +21 -26
- package/dist/commonjs/sampling.d.ts.map +0 -1
- package/dist/commonjs/sampling.js.map +0 -1
- package/dist/esm/sampling.d.ts.map +0 -1
- package/dist/esm/sampling.js.map +0 -1
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
import { diag } from "@opentelemetry/api";
|
|
4
|
+
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
5
|
+
import * as ai from "../../utils/constants/applicationinsights.js";
|
|
6
|
+
import { StatsbeatMetrics } from "./statsbeatMetrics.js";
|
|
7
|
+
import { CustomerStatsbeat, DropCode, RetryCode } from "./types.js";
|
|
8
|
+
import { CustomStatsbeatCounter, STATSBEAT_LANGUAGE, TelemetryType } from "./types.js";
|
|
9
|
+
import { getAttachType } from "../../utils/metricUtils.js";
|
|
10
|
+
import { AzureMonitorStatsbeatExporter } from "./statsbeatExporter.js";
|
|
11
|
+
import { BreezePerformanceCounterNames } from "../../types.js";
|
|
12
|
+
/**
|
|
13
|
+
* Class that handles customer-facing statsbeat metrics
|
|
14
|
+
* These metrics are sent to the customer's breeze endpoint
|
|
15
|
+
*
|
|
16
|
+
* Implements a singleton pattern to ensure only one set of customer statsbeat metrics
|
|
17
|
+
* is exported every 15 minutes, regardless of the number of exporters or senders.
|
|
18
|
+
*/
|
|
19
|
+
export class CustomerStatsbeatMetrics extends StatsbeatMetrics {
|
|
20
|
+
static _instance;
|
|
21
|
+
statsCollectionInterval = 900000; // 15 minutes
|
|
22
|
+
customerStatsbeatMeter;
|
|
23
|
+
customerStatsbeatMeterProvider;
|
|
24
|
+
customerStatsbeatExporter;
|
|
25
|
+
customerStatsbeatCounter;
|
|
26
|
+
customerStatsbeatMetricReader;
|
|
27
|
+
isInitialized = false;
|
|
28
|
+
// Custom dimensions
|
|
29
|
+
language;
|
|
30
|
+
version;
|
|
31
|
+
attach = getAttachType();
|
|
32
|
+
// Observable Gauges
|
|
33
|
+
itemSuccessCountGauge;
|
|
34
|
+
itemDropCountGauge;
|
|
35
|
+
itemRetryCountGauge;
|
|
36
|
+
// Customer statsbeat properties
|
|
37
|
+
customerProperties;
|
|
38
|
+
constructor(options) {
|
|
39
|
+
super();
|
|
40
|
+
const exporterConfig = {
|
|
41
|
+
connectionString: `InstrumentationKey=${options.instrumentationKey};IngestionEndpoint=${options.endpointUrl}`,
|
|
42
|
+
};
|
|
43
|
+
this.customerStatsbeatExporter = new AzureMonitorStatsbeatExporter(exporterConfig);
|
|
44
|
+
// Exports Customer Statsbeat every 15 minutes
|
|
45
|
+
const customerMetricReaderOptions = {
|
|
46
|
+
exporter: this.customerStatsbeatExporter,
|
|
47
|
+
exportIntervalMillis: options.networkCollectionInterval || this.statsCollectionInterval,
|
|
48
|
+
};
|
|
49
|
+
this.customerStatsbeatMetricReader = new PeriodicExportingMetricReader(customerMetricReaderOptions);
|
|
50
|
+
this.customerStatsbeatMeterProvider = new MeterProvider({
|
|
51
|
+
readers: [this.customerStatsbeatMetricReader],
|
|
52
|
+
});
|
|
53
|
+
this.customerStatsbeatMeter = this.customerStatsbeatMeterProvider.getMeter("Azure Monitor Customer Statsbeat");
|
|
54
|
+
this.language = STATSBEAT_LANGUAGE;
|
|
55
|
+
this.version = ai.packageVersion;
|
|
56
|
+
this.itemSuccessCountGauge = this.customerStatsbeatMeter.createObservableGauge(CustomStatsbeatCounter.ITEM_SUCCESS_COUNT);
|
|
57
|
+
this.itemDropCountGauge = this.customerStatsbeatMeter.createObservableGauge(CustomStatsbeatCounter.ITEM_DROP_COUNT);
|
|
58
|
+
this.itemRetryCountGauge = this.customerStatsbeatMeter.createObservableGauge(CustomStatsbeatCounter.ITEM_RETRY_COUNT);
|
|
59
|
+
if (!this.isInitialized) {
|
|
60
|
+
this.initialize();
|
|
61
|
+
}
|
|
62
|
+
this.isInitialized = true;
|
|
63
|
+
// Initialize the single customer statsbeat counter
|
|
64
|
+
this.customerStatsbeatCounter = new CustomerStatsbeat();
|
|
65
|
+
this.customerProperties = {
|
|
66
|
+
language: this.language,
|
|
67
|
+
version: this.version,
|
|
68
|
+
computeType: this.attach,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get singleton instance of CustomerStatsbeatMetrics
|
|
73
|
+
* @param options - Configuration options for customer statsbeat metrics
|
|
74
|
+
* @returns The singleton instance
|
|
75
|
+
*/
|
|
76
|
+
static getInstance(options) {
|
|
77
|
+
if (!CustomerStatsbeatMetrics._instance) {
|
|
78
|
+
CustomerStatsbeatMetrics._instance = new CustomerStatsbeatMetrics(options);
|
|
79
|
+
}
|
|
80
|
+
return CustomerStatsbeatMetrics._instance;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Shutdown the singleton instance
|
|
84
|
+
* Used for cleanup and complete shutdown
|
|
85
|
+
*/
|
|
86
|
+
static shutdown() {
|
|
87
|
+
if (CustomerStatsbeatMetrics._instance) {
|
|
88
|
+
const shutdownPromise = CustomerStatsbeatMetrics._instance.shutdown();
|
|
89
|
+
CustomerStatsbeatMetrics._instance = undefined;
|
|
90
|
+
return shutdownPromise;
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Shuts down the customer statsbeat metrics provider
|
|
96
|
+
* @returns Promise<void>
|
|
97
|
+
*/
|
|
98
|
+
shutdown() {
|
|
99
|
+
return this.customerStatsbeatMeterProvider.shutdown();
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Initializes the customer statsbeat metrics
|
|
103
|
+
* Sets up the resource provider and adds observable callbacks for each metric
|
|
104
|
+
* @returns Promise<void>
|
|
105
|
+
*/
|
|
106
|
+
async initialize() {
|
|
107
|
+
try {
|
|
108
|
+
await super.getResourceProvider();
|
|
109
|
+
this.customerStatsbeatMeter.addBatchObservableCallback(this.itemSuccessCallback.bind(this), [
|
|
110
|
+
this.itemSuccessCountGauge,
|
|
111
|
+
]);
|
|
112
|
+
this.customerStatsbeatMeter.addBatchObservableCallback(this.itemDropCallback.bind(this), [
|
|
113
|
+
this.itemDropCountGauge,
|
|
114
|
+
]);
|
|
115
|
+
this.customerStatsbeatMeter.addBatchObservableCallback(this.itemRetryCallback.bind(this), [
|
|
116
|
+
this.itemRetryCountGauge,
|
|
117
|
+
]);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
diag.debug("Call to get the resource provider failed for customer statsbeat metrics.");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Observable gauge callbacks
|
|
124
|
+
itemSuccessCallback(observableResult) {
|
|
125
|
+
const counter = this.customerStatsbeatCounter;
|
|
126
|
+
const attributes = { ...this.customerProperties, telemetry_type: TelemetryType.UNKNOWN };
|
|
127
|
+
// For each { telemetry_type -> count } mapping, call observe, passing the count and attributes that include the telemetry_type
|
|
128
|
+
for (const [telemetry_type, count] of counter.totalItemSuccessCount.entries()) {
|
|
129
|
+
attributes.telemetry_type = telemetry_type;
|
|
130
|
+
observableResult.observe(this.itemSuccessCountGauge, count, {
|
|
131
|
+
...attributes,
|
|
132
|
+
});
|
|
133
|
+
counter.totalItemSuccessCount.set(telemetry_type, 0);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
itemDropCallback(observableResult) {
|
|
137
|
+
const counter = this.customerStatsbeatCounter;
|
|
138
|
+
const baseAttributes = {
|
|
139
|
+
...this.customerProperties,
|
|
140
|
+
"drop.code": DropCode.UNKNOWN,
|
|
141
|
+
telemetry_type: TelemetryType.UNKNOWN,
|
|
142
|
+
};
|
|
143
|
+
// Iterate through the nested Map structure: telemetry_type -> drop.code -> reason -> count
|
|
144
|
+
for (const [telemetryType, dropCodeMap] of counter.totalItemDropCount.entries()) {
|
|
145
|
+
for (const [dropCode, reasonMap] of dropCodeMap.entries()) {
|
|
146
|
+
for (const [reason, count] of reasonMap.entries()) {
|
|
147
|
+
const attributes = { ...baseAttributes };
|
|
148
|
+
attributes.telemetry_type = telemetryType;
|
|
149
|
+
attributes["drop.code"] = dropCode;
|
|
150
|
+
// Include drop.reason for all case
|
|
151
|
+
if (reason) {
|
|
152
|
+
attributes["drop.reason"] = reason;
|
|
153
|
+
}
|
|
154
|
+
observableResult.observe(this.itemDropCountGauge, count, {
|
|
155
|
+
...attributes,
|
|
156
|
+
});
|
|
157
|
+
// Reset the count to 0
|
|
158
|
+
reasonMap.set(reason, 0);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
itemRetryCallback(observableResult) {
|
|
164
|
+
const counter = this.customerStatsbeatCounter;
|
|
165
|
+
const baseAttributes = {
|
|
166
|
+
...this.customerProperties,
|
|
167
|
+
"retry.code": RetryCode.UNKNOWN,
|
|
168
|
+
telemetry_type: TelemetryType.UNKNOWN,
|
|
169
|
+
};
|
|
170
|
+
// Iterate through the nested Map structure: telemetry_type -> retry.code -> reason -> count
|
|
171
|
+
for (const [telemetryType, retryCodeMap] of counter.totalItemRetryCount.entries()) {
|
|
172
|
+
for (const [retryCode, reasonMap] of retryCodeMap.entries()) {
|
|
173
|
+
for (const [reason, count] of reasonMap.entries()) {
|
|
174
|
+
const attributes = { ...baseAttributes };
|
|
175
|
+
attributes.telemetry_type = telemetryType;
|
|
176
|
+
attributes["retry.code"] = retryCode;
|
|
177
|
+
// Include retry.reason for all cases
|
|
178
|
+
if (reason) {
|
|
179
|
+
attributes["retry.reason"] = reason;
|
|
180
|
+
}
|
|
181
|
+
observableResult.observe(this.itemRetryCountGauge, count, {
|
|
182
|
+
...attributes,
|
|
183
|
+
});
|
|
184
|
+
// Reset the count to 0
|
|
185
|
+
reasonMap.set(reason, 0);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// Public methods to track metrics
|
|
191
|
+
/**
|
|
192
|
+
* Tracks succcessful items
|
|
193
|
+
* @param envelopes - Number of successful envelopes
|
|
194
|
+
* @param telemetry_type - The type of telemetry being tracked
|
|
195
|
+
*/
|
|
196
|
+
countSuccessfulItems(envelopes) {
|
|
197
|
+
const counter = this.customerStatsbeatCounter;
|
|
198
|
+
let telemetry_type;
|
|
199
|
+
// Get the current count for this telemetry type, or 0 if it doesn't exist
|
|
200
|
+
for (const envelope of envelopes) {
|
|
201
|
+
telemetry_type = this.getTelemetryTypeFromEnvelope(envelope);
|
|
202
|
+
const currentCount = counter.totalItemSuccessCount.get(telemetry_type) || 0;
|
|
203
|
+
counter.totalItemSuccessCount.set(telemetry_type, currentCount + 1);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Tracks dropped items
|
|
208
|
+
* @param envelopes - Number of envelopes dropped
|
|
209
|
+
* @param dropCode - The drop code indicating the reason for drop
|
|
210
|
+
* @param telemetry_type - The type of telemetry being tracked
|
|
211
|
+
* @param exceptionMessage - Optional exception message when dropCode is CLIENT_EXCEPTION
|
|
212
|
+
*/
|
|
213
|
+
countDroppedItems(envelopes, dropCode, exceptionMessage) {
|
|
214
|
+
const counter = this.customerStatsbeatCounter;
|
|
215
|
+
let telemetry_type;
|
|
216
|
+
for (const envelope of envelopes) {
|
|
217
|
+
telemetry_type = this.getTelemetryTypeFromEnvelope(envelope);
|
|
218
|
+
// Get or create the dropCode map for this telemetry_type
|
|
219
|
+
let dropCodeMap = counter.totalItemDropCount.get(telemetry_type);
|
|
220
|
+
if (!dropCodeMap) {
|
|
221
|
+
dropCodeMap = new Map();
|
|
222
|
+
counter.totalItemDropCount.set(telemetry_type, dropCodeMap);
|
|
223
|
+
}
|
|
224
|
+
// Get or create the reason map for this dropCode
|
|
225
|
+
let reasonMap = dropCodeMap.get(dropCode);
|
|
226
|
+
if (!reasonMap) {
|
|
227
|
+
reasonMap = new Map();
|
|
228
|
+
dropCodeMap.set(dropCode, reasonMap);
|
|
229
|
+
}
|
|
230
|
+
// Generate a low-cardinality, informative reason description
|
|
231
|
+
const reason = this.getDropReason(dropCode, exceptionMessage);
|
|
232
|
+
// Update the count for this reason
|
|
233
|
+
const currentCount = reasonMap.get(reason) || 0;
|
|
234
|
+
reasonMap.set(reason, currentCount + 1);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Generates a low-cardinality, informative description for drop reasons
|
|
239
|
+
* @param dropCode - The drop code (enum value or status code number)
|
|
240
|
+
* @param exceptionMessage - Optional exception message for CLIENT_EXCEPTION
|
|
241
|
+
* @returns A descriptive reason string with low cardinality
|
|
242
|
+
*/
|
|
243
|
+
getDropReason(dropCode, exceptionMessage) {
|
|
244
|
+
if (dropCode === DropCode.CLIENT_EXCEPTION) {
|
|
245
|
+
// For client exceptions, derive a low-cardinality reason from the exception message
|
|
246
|
+
if (exceptionMessage) {
|
|
247
|
+
return this.categorizeExceptionMessage(exceptionMessage);
|
|
248
|
+
}
|
|
249
|
+
return "unknown_exception";
|
|
250
|
+
}
|
|
251
|
+
// Handle status code drop codes (numeric values)
|
|
252
|
+
if (typeof dropCode === "number") {
|
|
253
|
+
return this.categorizeStatusCode(dropCode);
|
|
254
|
+
}
|
|
255
|
+
// Handle other enum drop codes
|
|
256
|
+
switch (dropCode) {
|
|
257
|
+
case DropCode.CLIENT_EXPIRED_DATA:
|
|
258
|
+
return "expired_data";
|
|
259
|
+
case DropCode.CLIENT_READONLY:
|
|
260
|
+
return "readonly_mode";
|
|
261
|
+
case DropCode.CLIENT_STALE_DATA:
|
|
262
|
+
return "stale_data";
|
|
263
|
+
case DropCode.CLIENT_PERSISTENCE_CAPACITY:
|
|
264
|
+
return "persistence_full";
|
|
265
|
+
case DropCode.NON_RETRYABLE_STATUS_CODE:
|
|
266
|
+
return "non_retryable_status";
|
|
267
|
+
case DropCode.UNKNOWN:
|
|
268
|
+
default:
|
|
269
|
+
return "unknown_reason";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Categorizes exception messages into low-cardinality groups
|
|
274
|
+
* @param exceptionMessage - The exception message to categorize
|
|
275
|
+
* @returns A low-cardinality category string
|
|
276
|
+
*/
|
|
277
|
+
categorizeExceptionMessage(exceptionMessage) {
|
|
278
|
+
const message = exceptionMessage.toLowerCase();
|
|
279
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
280
|
+
return "timeout_exception";
|
|
281
|
+
}
|
|
282
|
+
if (message.includes("network") || message.includes("connection")) {
|
|
283
|
+
return "network_exception";
|
|
284
|
+
}
|
|
285
|
+
if (message.includes("auth") ||
|
|
286
|
+
message.includes("unauthorized") ||
|
|
287
|
+
message.includes("forbidden")) {
|
|
288
|
+
return "auth_exception";
|
|
289
|
+
}
|
|
290
|
+
if (message.includes("parsing") || message.includes("parse") || message.includes("invalid")) {
|
|
291
|
+
return "parsing_exception";
|
|
292
|
+
}
|
|
293
|
+
if (message.includes("disk") || message.includes("storage") || message.includes("file")) {
|
|
294
|
+
return "storage_exception";
|
|
295
|
+
}
|
|
296
|
+
if (message.includes("memory") || message.includes("out of memory")) {
|
|
297
|
+
return "memory_exception";
|
|
298
|
+
}
|
|
299
|
+
return "other_exception";
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Categorizes HTTP status codes into informative descriptions
|
|
303
|
+
* @param statusCode - The HTTP status code
|
|
304
|
+
* @returns A descriptive category string
|
|
305
|
+
*/
|
|
306
|
+
categorizeStatusCode(statusCode) {
|
|
307
|
+
if (statusCode >= 400 && statusCode < 500) {
|
|
308
|
+
switch (statusCode) {
|
|
309
|
+
case 400:
|
|
310
|
+
return "bad_request";
|
|
311
|
+
case 401:
|
|
312
|
+
return "unauthorized";
|
|
313
|
+
case 403:
|
|
314
|
+
return "forbidden";
|
|
315
|
+
case 404:
|
|
316
|
+
return "not_found";
|
|
317
|
+
case 408:
|
|
318
|
+
return "request_timeout";
|
|
319
|
+
case 413:
|
|
320
|
+
return "payload_too_large";
|
|
321
|
+
case 429:
|
|
322
|
+
return "too_many_requests";
|
|
323
|
+
default:
|
|
324
|
+
return "client_error_4xx";
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (statusCode >= 500 && statusCode < 600) {
|
|
328
|
+
switch (statusCode) {
|
|
329
|
+
case 500:
|
|
330
|
+
return "internal_server_error";
|
|
331
|
+
case 502:
|
|
332
|
+
return "bad_gateway";
|
|
333
|
+
case 503:
|
|
334
|
+
return "service_unavailable";
|
|
335
|
+
case 504:
|
|
336
|
+
return "gateway_timeout";
|
|
337
|
+
default:
|
|
338
|
+
return "server_error_5xx";
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
return `status_${statusCode}`;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Tracks retried envelopes
|
|
345
|
+
* @param envelopes - Number of envelopes retried
|
|
346
|
+
* @param retryCode - The retry code indicating the reason for retry
|
|
347
|
+
* @param telemetry_type - The type of telemetry being tracked
|
|
348
|
+
* @param exceptionMessage - Optional exception message when retryCode is CLIENT_EXCEPTION
|
|
349
|
+
*/
|
|
350
|
+
countRetryItems(envelopes, retryCode, exceptionMessage) {
|
|
351
|
+
const counter = this.customerStatsbeatCounter;
|
|
352
|
+
let telemetry_type;
|
|
353
|
+
for (const envelope of envelopes) {
|
|
354
|
+
telemetry_type = this.getTelemetryTypeFromEnvelope(envelope);
|
|
355
|
+
// Get or create the retryCode map for this telemetry_type
|
|
356
|
+
let retryCodeMap = counter.totalItemRetryCount.get(telemetry_type);
|
|
357
|
+
if (!retryCodeMap) {
|
|
358
|
+
retryCodeMap = new Map();
|
|
359
|
+
counter.totalItemRetryCount.set(telemetry_type, retryCodeMap);
|
|
360
|
+
}
|
|
361
|
+
// Get or create the reason map for this retryCode
|
|
362
|
+
let reasonMap = retryCodeMap.get(retryCode);
|
|
363
|
+
if (!reasonMap) {
|
|
364
|
+
reasonMap = new Map();
|
|
365
|
+
retryCodeMap.set(retryCode, reasonMap);
|
|
366
|
+
}
|
|
367
|
+
// Generate a low-cardinality, informative reason description
|
|
368
|
+
const reason = this.getRetryReason(retryCode, exceptionMessage);
|
|
369
|
+
// Update the count for this reason
|
|
370
|
+
const currentCount = reasonMap.get(reason) || 0;
|
|
371
|
+
reasonMap.set(reason, currentCount + 1);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Generates a low-cardinality, informative description for retry reasons
|
|
376
|
+
* @param retryCode - The retry code (enum value or status code number)
|
|
377
|
+
* @param exceptionMessage - Optional exception message for CLIENT_EXCEPTION
|
|
378
|
+
* @returns A descriptive reason string with low cardinality
|
|
379
|
+
*/
|
|
380
|
+
getRetryReason(retryCode, exceptionMessage) {
|
|
381
|
+
if (retryCode === RetryCode.CLIENT_EXCEPTION) {
|
|
382
|
+
// For client exceptions, derive a low-cardinality reason from the exception message
|
|
383
|
+
if (exceptionMessage) {
|
|
384
|
+
return this.categorizeExceptionMessage(exceptionMessage);
|
|
385
|
+
}
|
|
386
|
+
return "unknown_exception";
|
|
387
|
+
}
|
|
388
|
+
// Handle status code retry codes (numeric values)
|
|
389
|
+
if (typeof retryCode === "number") {
|
|
390
|
+
return this.categorizeStatusCode(retryCode);
|
|
391
|
+
}
|
|
392
|
+
// Handle other enum retry codes
|
|
393
|
+
switch (retryCode) {
|
|
394
|
+
case RetryCode.CLIENT_TIMEOUT:
|
|
395
|
+
return "client_timeout";
|
|
396
|
+
case RetryCode.RETRYABLE_STATUS_CODE:
|
|
397
|
+
return "retryable_status";
|
|
398
|
+
case RetryCode.UNKNOWN:
|
|
399
|
+
default:
|
|
400
|
+
return "unknown_reason";
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Check if a metric name corresponds to a performance counter
|
|
405
|
+
* @param metricName - The name of the metric to check
|
|
406
|
+
* @returns true if the metric name is a performance counter, false otherwise
|
|
407
|
+
*/
|
|
408
|
+
isPerformanceCounterMetric(metricName) {
|
|
409
|
+
return Object.values(BreezePerformanceCounterNames).includes(metricName);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Extract telemetry type from an envelope based on its baseType
|
|
413
|
+
* @param envelope - The envelope to extract telemetry type from
|
|
414
|
+
* @returns The corresponding telemetry type
|
|
415
|
+
*/
|
|
416
|
+
getTelemetryTypeFromEnvelope(envelope) {
|
|
417
|
+
if (envelope.data && envelope.data.baseType) {
|
|
418
|
+
switch (envelope.data.baseType) {
|
|
419
|
+
case "MessageData":
|
|
420
|
+
return TelemetryType.TRACE;
|
|
421
|
+
case "AvailabilityData":
|
|
422
|
+
return TelemetryType.AVAILABILITY;
|
|
423
|
+
case "TelemetryEventData":
|
|
424
|
+
return TelemetryType.CUSTOM_EVENT;
|
|
425
|
+
case "TelemetryExceptionData":
|
|
426
|
+
return TelemetryType.EXCEPTION;
|
|
427
|
+
case "PageViewData":
|
|
428
|
+
return TelemetryType.PAGE_VIEW;
|
|
429
|
+
case "RemoteDependencyData":
|
|
430
|
+
return TelemetryType.DEPENDENCY;
|
|
431
|
+
case "RequestData":
|
|
432
|
+
return TelemetryType.REQUEST;
|
|
433
|
+
case "MetricData": {
|
|
434
|
+
const metricsData = envelope.data.baseData;
|
|
435
|
+
if (metricsData && metricsData.metrics && metricsData.metrics.length > 0) {
|
|
436
|
+
// Check if any of the metrics are performance counters
|
|
437
|
+
const hasPerformanceCounter = metricsData.metrics.some((metric) => this.isPerformanceCounterMetric(metric.name));
|
|
438
|
+
return hasPerformanceCounter
|
|
439
|
+
? TelemetryType.PERFORMANCE_COUNTER
|
|
440
|
+
: TelemetryType.CUSTOM_METRIC;
|
|
441
|
+
}
|
|
442
|
+
return TelemetryType.CUSTOM_METRIC;
|
|
443
|
+
}
|
|
444
|
+
default:
|
|
445
|
+
return TelemetryType.UNKNOWN;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return TelemetryType.UNKNOWN;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Checks if the given error is a timeout-related error
|
|
452
|
+
* @param error - The error to check
|
|
453
|
+
* @returns true if the error is timeout-related, false otherwise
|
|
454
|
+
*/
|
|
455
|
+
isTimeoutError(error) {
|
|
456
|
+
// Check for various timeout error codes that indicate client timeouts
|
|
457
|
+
const timeoutErrorCodes = [
|
|
458
|
+
"ETIMEDOUT", // Connection timed out
|
|
459
|
+
"ESOCKETTIMEDOUT", // Socket timeout
|
|
460
|
+
"ECONNRESET", // Connection reset (often due to timeout)
|
|
461
|
+
"ENOTFOUND", // DNS lookup failed/timeout
|
|
462
|
+
];
|
|
463
|
+
if (error && error.code && timeoutErrorCodes.includes(error.code)) {
|
|
464
|
+
return true;
|
|
465
|
+
}
|
|
466
|
+
// Also check if the error message contains timeout-related keywords
|
|
467
|
+
if (error && error.message) {
|
|
468
|
+
const timeoutKeywords = ["timeout", "timed out", "connection reset"];
|
|
469
|
+
const errorMessage = error.message.toLowerCase();
|
|
470
|
+
return timeoutKeywords.some((keyword) => errorMessage.includes(keyword));
|
|
471
|
+
}
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=customerStatsbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"customerStatsbeat.js","sourceRoot":"","sources":["../../../../src/export/statsbeat/customerStatsbeat.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { BatchObservableResult, Meter, ObservableGauge } from \"@opentelemetry/api\";\nimport { diag } from \"@opentelemetry/api\";\nimport type { PeriodicExportingMetricReaderOptions } from \"@opentelemetry/sdk-metrics\";\nimport { MeterProvider, PeriodicExportingMetricReader } from \"@opentelemetry/sdk-metrics\";\nimport type { AzureMonitorExporterOptions } from \"../../index.js\";\nimport * as ai from \"../../utils/constants/applicationinsights.js\";\nimport { StatsbeatMetrics } from \"./statsbeatMetrics.js\";\nimport type { CustomerStatsbeatProperties, StatsbeatOptions } from \"./types.js\";\nimport { CustomerStatsbeat, DropCode, RetryCode } from \"./types.js\";\nimport { CustomStatsbeatCounter, STATSBEAT_LANGUAGE, TelemetryType } from \"./types.js\";\nimport { getAttachType } from \"../../utils/metricUtils.js\";\nimport { AzureMonitorStatsbeatExporter } from \"./statsbeatExporter.js\";\nimport { BreezePerformanceCounterNames } from \"../../types.js\";\nimport type { MetricsData } from \"../../generated/index.js\";\nimport type { TelemetryItem as Envelope } from \"../../generated/index.js\";\n\n/**\n * Class that handles customer-facing statsbeat metrics\n * These metrics are sent to the customer's breeze endpoint\n *\n * Implements a singleton pattern to ensure only one set of customer statsbeat metrics\n * is exported every 15 minutes, regardless of the number of exporters or senders.\n */\nexport class CustomerStatsbeatMetrics extends StatsbeatMetrics {\n private static _instance: CustomerStatsbeatMetrics | undefined;\n\n private statsCollectionInterval: number = 900000; // 15 minutes\n private customerStatsbeatMeter: Meter;\n private customerStatsbeatMeterProvider: MeterProvider;\n private customerStatsbeatExporter: AzureMonitorStatsbeatExporter;\n private customerStatsbeatCounter: CustomerStatsbeat;\n private customerStatsbeatMetricReader: PeriodicExportingMetricReader;\n private isInitialized: boolean = false;\n\n // Custom dimensions\n private language: string;\n private version: string;\n private attach: string = getAttachType();\n\n // Observable Gauges\n private itemSuccessCountGauge: ObservableGauge;\n private itemDropCountGauge: ObservableGauge;\n private itemRetryCountGauge: ObservableGauge;\n\n // Customer statsbeat properties\n private customerProperties: CustomerStatsbeatProperties;\n\n private constructor(options: StatsbeatOptions) {\n super();\n const exporterConfig: AzureMonitorExporterOptions = {\n connectionString: `InstrumentationKey=${options.instrumentationKey};IngestionEndpoint=${options.endpointUrl}`,\n };\n\n this.customerStatsbeatExporter = new AzureMonitorStatsbeatExporter(exporterConfig);\n // Exports Customer Statsbeat every 15 minutes\n const customerMetricReaderOptions: PeriodicExportingMetricReaderOptions = {\n exporter: this.customerStatsbeatExporter,\n exportIntervalMillis: options.networkCollectionInterval || this.statsCollectionInterval,\n };\n this.customerStatsbeatMetricReader = new PeriodicExportingMetricReader(\n customerMetricReaderOptions,\n );\n this.customerStatsbeatMeterProvider = new MeterProvider({\n readers: [this.customerStatsbeatMetricReader],\n });\n\n this.customerStatsbeatMeter = this.customerStatsbeatMeterProvider.getMeter(\n \"Azure Monitor Customer Statsbeat\",\n );\n\n this.language = STATSBEAT_LANGUAGE;\n this.version = ai.packageVersion;\n\n this.itemSuccessCountGauge = this.customerStatsbeatMeter.createObservableGauge(\n CustomStatsbeatCounter.ITEM_SUCCESS_COUNT,\n );\n this.itemDropCountGauge = this.customerStatsbeatMeter.createObservableGauge(\n CustomStatsbeatCounter.ITEM_DROP_COUNT,\n );\n this.itemRetryCountGauge = this.customerStatsbeatMeter.createObservableGauge(\n CustomStatsbeatCounter.ITEM_RETRY_COUNT,\n );\n\n if (!this.isInitialized) {\n this.initialize();\n }\n this.isInitialized = true;\n\n // Initialize the single customer statsbeat counter\n this.customerStatsbeatCounter = new CustomerStatsbeat();\n\n this.customerProperties = {\n language: this.language,\n version: this.version,\n computeType: this.attach,\n };\n }\n\n /**\n * Get singleton instance of CustomerStatsbeatMetrics\n * @param options - Configuration options for customer statsbeat metrics\n * @returns The singleton instance\n */\n public static getInstance(options: StatsbeatOptions): CustomerStatsbeatMetrics {\n if (!CustomerStatsbeatMetrics._instance) {\n CustomerStatsbeatMetrics._instance = new CustomerStatsbeatMetrics(options);\n }\n return CustomerStatsbeatMetrics._instance;\n }\n\n /**\n * Shutdown the singleton instance\n * Used for cleanup and complete shutdown\n */\n public static shutdown(): Promise<void> | undefined {\n if (CustomerStatsbeatMetrics._instance) {\n const shutdownPromise = CustomerStatsbeatMetrics._instance.shutdown();\n CustomerStatsbeatMetrics._instance = undefined;\n return shutdownPromise;\n }\n return undefined;\n }\n\n /**\n * Shuts down the customer statsbeat metrics provider\n * @returns Promise<void>\n */\n public shutdown(): Promise<void> {\n return this.customerStatsbeatMeterProvider.shutdown();\n }\n\n /**\n * Initializes the customer statsbeat metrics\n * Sets up the resource provider and adds observable callbacks for each metric\n * @returns Promise<void>\n */\n private async initialize(): Promise<void> {\n try {\n await super.getResourceProvider();\n this.customerStatsbeatMeter.addBatchObservableCallback(this.itemSuccessCallback.bind(this), [\n this.itemSuccessCountGauge,\n ]);\n this.customerStatsbeatMeter.addBatchObservableCallback(this.itemDropCallback.bind(this), [\n this.itemDropCountGauge,\n ]);\n this.customerStatsbeatMeter.addBatchObservableCallback(this.itemRetryCallback.bind(this), [\n this.itemRetryCountGauge,\n ]);\n } catch (error) {\n diag.debug(\"Call to get the resource provider failed for customer statsbeat metrics.\");\n }\n }\n\n // Observable gauge callbacks\n private itemSuccessCallback(observableResult: BatchObservableResult): void {\n const counter: CustomerStatsbeat = this.customerStatsbeatCounter;\n const attributes = { ...this.customerProperties, telemetry_type: TelemetryType.UNKNOWN };\n\n // For each { telemetry_type -> count } mapping, call observe, passing the count and attributes that include the telemetry_type\n for (const [telemetry_type, count] of counter.totalItemSuccessCount.entries()) {\n attributes.telemetry_type = telemetry_type;\n observableResult.observe(this.itemSuccessCountGauge, count, {\n ...attributes,\n });\n counter.totalItemSuccessCount.set(telemetry_type, 0);\n }\n }\n\n private itemDropCallback(observableResult: BatchObservableResult): void {\n const counter: CustomerStatsbeat = this.customerStatsbeatCounter;\n const baseAttributes: CustomerStatsbeatProperties & {\n \"drop.code\": DropCode | number;\n telemetry_type: TelemetryType;\n } = {\n ...this.customerProperties,\n \"drop.code\": DropCode.UNKNOWN,\n telemetry_type: TelemetryType.UNKNOWN,\n };\n\n // Iterate through the nested Map structure: telemetry_type -> drop.code -> reason -> count\n for (const [telemetryType, dropCodeMap] of counter.totalItemDropCount.entries()) {\n for (const [dropCode, reasonMap] of dropCodeMap.entries()) {\n for (const [reason, count] of reasonMap.entries()) {\n const attributes = { ...baseAttributes };\n attributes.telemetry_type = telemetryType;\n attributes[\"drop.code\"] = dropCode;\n\n // Include drop.reason for all case\n if (reason) {\n (attributes as any)[\"drop.reason\"] = reason;\n }\n\n observableResult.observe(this.itemDropCountGauge, count, {\n ...attributes,\n });\n\n // Reset the count to 0\n reasonMap.set(reason, 0);\n }\n }\n }\n }\n\n private itemRetryCallback(observableResult: BatchObservableResult): void {\n const counter: CustomerStatsbeat = this.customerStatsbeatCounter;\n const baseAttributes: CustomerStatsbeatProperties & {\n \"retry.code\": RetryCode | number;\n telemetry_type: TelemetryType;\n } = {\n ...this.customerProperties,\n \"retry.code\": RetryCode.UNKNOWN,\n telemetry_type: TelemetryType.UNKNOWN,\n };\n\n // Iterate through the nested Map structure: telemetry_type -> retry.code -> reason -> count\n for (const [telemetryType, retryCodeMap] of counter.totalItemRetryCount.entries()) {\n for (const [retryCode, reasonMap] of retryCodeMap.entries()) {\n for (const [reason, count] of reasonMap.entries()) {\n const attributes = { ...baseAttributes };\n attributes.telemetry_type = telemetryType;\n attributes[\"retry.code\"] = retryCode;\n\n // Include retry.reason for all cases\n if (reason) {\n (attributes as any)[\"retry.reason\"] = reason;\n }\n\n observableResult.observe(this.itemRetryCountGauge, count, {\n ...attributes,\n });\n\n // Reset the count to 0\n reasonMap.set(reason, 0);\n }\n }\n }\n }\n\n // Public methods to track metrics\n /**\n * Tracks succcessful items\n * @param envelopes - Number of successful envelopes\n * @param telemetry_type - The type of telemetry being tracked\n */\n public countSuccessfulItems(envelopes: Envelope[]): void {\n const counter: CustomerStatsbeat = this.customerStatsbeatCounter;\n let telemetry_type: TelemetryType;\n\n // Get the current count for this telemetry type, or 0 if it doesn't exist\n for (const envelope of envelopes) {\n telemetry_type = this.getTelemetryTypeFromEnvelope(envelope);\n const currentCount = counter.totalItemSuccessCount.get(telemetry_type) || 0;\n counter.totalItemSuccessCount.set(telemetry_type, currentCount + 1);\n }\n }\n\n /**\n * Tracks dropped items\n * @param envelopes - Number of envelopes dropped\n * @param dropCode - The drop code indicating the reason for drop\n * @param telemetry_type - The type of telemetry being tracked\n * @param exceptionMessage - Optional exception message when dropCode is CLIENT_EXCEPTION\n */\n public countDroppedItems(\n envelopes: Envelope[],\n dropCode: DropCode | number,\n exceptionMessage?: string,\n ): void {\n const counter: CustomerStatsbeat = this.customerStatsbeatCounter;\n let telemetry_type: TelemetryType;\n\n for (const envelope of envelopes) {\n telemetry_type = this.getTelemetryTypeFromEnvelope(envelope);\n // Get or create the dropCode map for this telemetry_type\n let dropCodeMap = counter.totalItemDropCount.get(telemetry_type);\n if (!dropCodeMap) {\n dropCodeMap = new Map<DropCode | number, Map<string, number>>();\n counter.totalItemDropCount.set(telemetry_type, dropCodeMap);\n }\n\n // Get or create the reason map for this dropCode\n let reasonMap = dropCodeMap.get(dropCode);\n if (!reasonMap) {\n reasonMap = new Map<string, number>();\n dropCodeMap.set(dropCode, reasonMap);\n }\n\n // Generate a low-cardinality, informative reason description\n const reason = this.getDropReason(dropCode, exceptionMessage);\n\n // Update the count for this reason\n const currentCount = reasonMap.get(reason) || 0;\n reasonMap.set(reason, currentCount + 1);\n }\n }\n\n /**\n * Generates a low-cardinality, informative description for drop reasons\n * @param dropCode - The drop code (enum value or status code number)\n * @param exceptionMessage - Optional exception message for CLIENT_EXCEPTION\n * @returns A descriptive reason string with low cardinality\n */\n private getDropReason(dropCode: DropCode | number, exceptionMessage?: string): string {\n if (dropCode === DropCode.CLIENT_EXCEPTION) {\n // For client exceptions, derive a low-cardinality reason from the exception message\n if (exceptionMessage) {\n return this.categorizeExceptionMessage(exceptionMessage);\n }\n return \"unknown_exception\";\n }\n\n // Handle status code drop codes (numeric values)\n if (typeof dropCode === \"number\") {\n return this.categorizeStatusCode(dropCode);\n }\n\n // Handle other enum drop codes\n switch (dropCode) {\n case DropCode.CLIENT_EXPIRED_DATA:\n return \"expired_data\";\n case DropCode.CLIENT_READONLY:\n return \"readonly_mode\";\n case DropCode.CLIENT_STALE_DATA:\n return \"stale_data\";\n case DropCode.CLIENT_PERSISTENCE_CAPACITY:\n return \"persistence_full\";\n case DropCode.NON_RETRYABLE_STATUS_CODE:\n return \"non_retryable_status\";\n case DropCode.UNKNOWN:\n default:\n return \"unknown_reason\";\n }\n }\n\n /**\n * Categorizes exception messages into low-cardinality groups\n * @param exceptionMessage - The exception message to categorize\n * @returns A low-cardinality category string\n */\n private categorizeExceptionMessage(exceptionMessage: string): string {\n const message = exceptionMessage.toLowerCase();\n\n if (message.includes(\"timeout\") || message.includes(\"timed out\")) {\n return \"timeout_exception\";\n }\n if (message.includes(\"network\") || message.includes(\"connection\")) {\n return \"network_exception\";\n }\n if (\n message.includes(\"auth\") ||\n message.includes(\"unauthorized\") ||\n message.includes(\"forbidden\")\n ) {\n return \"auth_exception\";\n }\n if (message.includes(\"parsing\") || message.includes(\"parse\") || message.includes(\"invalid\")) {\n return \"parsing_exception\";\n }\n if (message.includes(\"disk\") || message.includes(\"storage\") || message.includes(\"file\")) {\n return \"storage_exception\";\n }\n if (message.includes(\"memory\") || message.includes(\"out of memory\")) {\n return \"memory_exception\";\n }\n\n return \"other_exception\";\n }\n\n /**\n * Categorizes HTTP status codes into informative descriptions\n * @param statusCode - The HTTP status code\n * @returns A descriptive category string\n */\n private categorizeStatusCode(statusCode: number): string {\n if (statusCode >= 400 && statusCode < 500) {\n switch (statusCode) {\n case 400:\n return \"bad_request\";\n case 401:\n return \"unauthorized\";\n case 403:\n return \"forbidden\";\n case 404:\n return \"not_found\";\n case 408:\n return \"request_timeout\";\n case 413:\n return \"payload_too_large\";\n case 429:\n return \"too_many_requests\";\n default:\n return \"client_error_4xx\";\n }\n }\n\n if (statusCode >= 500 && statusCode < 600) {\n switch (statusCode) {\n case 500:\n return \"internal_server_error\";\n case 502:\n return \"bad_gateway\";\n case 503:\n return \"service_unavailable\";\n case 504:\n return \"gateway_timeout\";\n default:\n return \"server_error_5xx\";\n }\n }\n\n return `status_${statusCode}`;\n }\n /**\n * Tracks retried envelopes\n * @param envelopes - Number of envelopes retried\n * @param retryCode - The retry code indicating the reason for retry\n * @param telemetry_type - The type of telemetry being tracked\n * @param exceptionMessage - Optional exception message when retryCode is CLIENT_EXCEPTION\n */\n public countRetryItems(\n envelopes: Envelope[],\n retryCode: RetryCode | number,\n exceptionMessage?: string,\n ): void {\n const counter: CustomerStatsbeat = this.customerStatsbeatCounter;\n let telemetry_type: TelemetryType;\n\n for (const envelope of envelopes) {\n telemetry_type = this.getTelemetryTypeFromEnvelope(envelope);\n // Get or create the retryCode map for this telemetry_type\n let retryCodeMap = counter.totalItemRetryCount.get(telemetry_type);\n if (!retryCodeMap) {\n retryCodeMap = new Map<RetryCode | number, Map<string, number>>();\n counter.totalItemRetryCount.set(telemetry_type, retryCodeMap);\n }\n\n // Get or create the reason map for this retryCode\n let reasonMap = retryCodeMap.get(retryCode);\n if (!reasonMap) {\n reasonMap = new Map<string, number>();\n retryCodeMap.set(retryCode, reasonMap);\n }\n\n // Generate a low-cardinality, informative reason description\n const reason = this.getRetryReason(retryCode, exceptionMessage);\n\n // Update the count for this reason\n const currentCount = reasonMap.get(reason) || 0;\n reasonMap.set(reason, currentCount + 1);\n }\n }\n\n /**\n * Generates a low-cardinality, informative description for retry reasons\n * @param retryCode - The retry code (enum value or status code number)\n * @param exceptionMessage - Optional exception message for CLIENT_EXCEPTION\n * @returns A descriptive reason string with low cardinality\n */\n private getRetryReason(retryCode: RetryCode | number, exceptionMessage?: string): string {\n if (retryCode === RetryCode.CLIENT_EXCEPTION) {\n // For client exceptions, derive a low-cardinality reason from the exception message\n if (exceptionMessage) {\n return this.categorizeExceptionMessage(exceptionMessage);\n }\n return \"unknown_exception\";\n }\n\n // Handle status code retry codes (numeric values)\n if (typeof retryCode === \"number\") {\n return this.categorizeStatusCode(retryCode);\n }\n\n // Handle other enum retry codes\n switch (retryCode) {\n case RetryCode.CLIENT_TIMEOUT:\n return \"client_timeout\";\n case RetryCode.RETRYABLE_STATUS_CODE:\n return \"retryable_status\";\n case RetryCode.UNKNOWN:\n default:\n return \"unknown_reason\";\n }\n }\n\n /**\n * Check if a metric name corresponds to a performance counter\n * @param metricName - The name of the metric to check\n * @returns true if the metric name is a performance counter, false otherwise\n */\n private isPerformanceCounterMetric(metricName: string): boolean {\n return Object.values(BreezePerformanceCounterNames).includes(\n metricName as BreezePerformanceCounterNames,\n );\n }\n\n /**\n * Extract telemetry type from an envelope based on its baseType\n * @param envelope - The envelope to extract telemetry type from\n * @returns The corresponding telemetry type\n */\n public getTelemetryTypeFromEnvelope(envelope: Envelope): TelemetryType {\n if (envelope.data && envelope.data.baseType) {\n switch (envelope.data.baseType) {\n case \"MessageData\":\n return TelemetryType.TRACE;\n case \"AvailabilityData\":\n return TelemetryType.AVAILABILITY;\n case \"TelemetryEventData\":\n return TelemetryType.CUSTOM_EVENT;\n case \"TelemetryExceptionData\":\n return TelemetryType.EXCEPTION;\n case \"PageViewData\":\n return TelemetryType.PAGE_VIEW;\n case \"RemoteDependencyData\":\n return TelemetryType.DEPENDENCY;\n case \"RequestData\":\n return TelemetryType.REQUEST;\n case \"MetricData\": {\n const metricsData = envelope.data.baseData as MetricsData;\n if (metricsData && metricsData.metrics && metricsData.metrics.length > 0) {\n // Check if any of the metrics are performance counters\n const hasPerformanceCounter = metricsData.metrics.some((metric) =>\n this.isPerformanceCounterMetric(metric.name),\n );\n return hasPerformanceCounter\n ? TelemetryType.PERFORMANCE_COUNTER\n : TelemetryType.CUSTOM_METRIC;\n }\n return TelemetryType.CUSTOM_METRIC;\n }\n default:\n return TelemetryType.UNKNOWN;\n }\n }\n return TelemetryType.UNKNOWN;\n }\n\n /**\n * Checks if the given error is a timeout-related error\n * @param error - The error to check\n * @returns true if the error is timeout-related, false otherwise\n */\n public isTimeoutError(error: { code?: string; message?: string }): boolean {\n // Check for various timeout error codes that indicate client timeouts\n const timeoutErrorCodes = [\n \"ETIMEDOUT\", // Connection timed out\n \"ESOCKETTIMEDOUT\", // Socket timeout\n \"ECONNRESET\", // Connection reset (often due to timeout)\n \"ENOTFOUND\", // DNS lookup failed/timeout\n ];\n\n if (error && error.code && timeoutErrorCodes.includes(error.code)) {\n return true;\n }\n\n // Also check if the error message contains timeout-related keywords\n if (error && error.message) {\n const timeoutKeywords = [\"timeout\", \"timed out\", \"connection reset\"];\n const errorMessage = error.message.toLowerCase();\n return timeoutKeywords.some((keyword) => errorMessage.includes(keyword));\n }\n\n return false;\n }\n}\n"]}
|
|
@@ -4,7 +4,8 @@ import type { StatsbeatOptions } from "./types.js";
|
|
|
4
4
|
* Long Interval Statsbeat Metrics
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
declare class LongIntervalStatsbeatMetrics extends StatsbeatMetrics {
|
|
7
|
+
export declare class LongIntervalStatsbeatMetrics extends StatsbeatMetrics {
|
|
8
|
+
private static instance;
|
|
8
9
|
private statsCollectionLongInterval;
|
|
9
10
|
private cikey;
|
|
10
11
|
private runtimeVersion;
|
|
@@ -29,11 +30,10 @@ declare class LongIntervalStatsbeatMetrics extends StatsbeatMetrics {
|
|
|
29
30
|
private setFeatures;
|
|
30
31
|
private attachCallback;
|
|
31
32
|
shutdown(): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Singleton LongIntervalStatsbeatMetrics instance.
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
static getInstance(options: StatsbeatOptions): LongIntervalStatsbeatMetrics;
|
|
32
38
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Singleton LongIntervalStatsbeatMetrics instance.
|
|
35
|
-
* @internal
|
|
36
|
-
*/
|
|
37
|
-
export declare function getInstance(options: StatsbeatOptions): LongIntervalStatsbeatMetrics;
|
|
38
|
-
export {};
|
|
39
39
|
//# sourceMappingURL=longIntervalStatsbeatMetrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"longIntervalStatsbeatMetrics.d.ts","sourceRoot":"","sources":["../../../../src/export/statsbeat/longIntervalStatsbeatMetrics.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"longIntervalStatsbeatMetrics.d.ts","sourceRoot":"","sources":["../../../../src/export/statsbeat/longIntervalStatsbeatMetrics.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAGV,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,gBAAgB;IAChE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA6C;IACpE,OAAO,CAAC,2BAA2B,CAAoB;IAEvD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAA2B;IAEzC,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,gBAAgB,CAA4B;IAEpD,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,eAAe,CAAa;IAEpC,OAAO,CAAC,kCAAkC,CAAgB;IAC1D,OAAO,CAAC,yBAAyB,CAAgC;IACjE,OAAO,CAAC,wBAAwB,CAAgC;IAChE,OAAO,CAAC,0BAA0B,CAAQ;IAG1C,OAAO,CAAC,gBAAgB,CAAS;IAGjC,OAAO,CAAC,qBAAqB,CAAkB;IAC/C,OAAO,CAAC,oBAAoB,CAAkB;IAEvC,aAAa,EAAE,OAAO,CAAS;gBAE1B,OAAO,EAAE,gBAAgB;YA0DvB,UAAU;IAsCxB,OAAO,CAAC,oBAAoB;IAwB5B,OAAO,CAAC,WAAW;IAcnB,OAAO,CAAC,cAAc;IAKf,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAGhC;;;OAGG;WACW,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,4BAA4B;CAMnF"}
|