Skip to content

Commit 6274032

Browse files
committed
Update flush of sdk stats.
1 parent 377013a commit 6274032

3 files changed

Lines changed: 43 additions & 26 deletions

File tree

AISKU/src/AISku.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import {
1111
IAutoExceptionTelemetry, IChannelControls, IConfig, IConfigDefaults, IConfiguration, ICookieMgr, ICustomProperties, IDependencyTelemetry,
1212
IDiagnosticLogger, IDistributedTraceContext, IDynamicConfigHandler, IEventTelemetry, IExceptionTelemetry, ILoadedPlugin,
1313
IMetricTelemetry, INotificationManager, IOTelApi, IOTelSpanOptions, IPageViewPerformanceTelemetry, IPageViewTelemetry, IPlugin,
14-
IReadableSpan, IRequestHeaders, ISdkStatsNotifCbk, ISpanScope, ITelemetryContext as Common_ITelemetryContext, ITelemetryInitializerHandler, ITelemetryItem,
15-
ITelemetryPlugin, ITelemetryUnloadState, IThrottleInterval, IThrottleLimit, IThrottleMgrConfig, ITraceApi, ITraceProvider,
16-
ITraceTelemetry, IUnloadHook, OTelTimeInput, PropertiesPluginIdentifier, ThrottleMgr, UnloadHandler, WatcherFunction,
17-
_eInternalMessageId, _throwInternal, addPageHideEventListener, addPageUnloadEventListener, cfgDfMerge, cfgDfValidate,
18-
createDynamicConfig, createOTelApi, createProcessTelemetryContext, createSdkStatsNotifCbk, createTraceProvider, createUniqueNamespace, doPerf, eLoggingSeverity,
19-
hasDocument, hasWindow, isArray, isFeatureEnabled, isFunction, isNullOrUndefined, isReactNative, isString, mergeEvtNamespace,
20-
onConfigChange, parseConnectionString, proxyAssign, proxyFunctions, removePageHideEventListener, removePageUnloadEventListener, useSpan
14+
IReadableSpan, IRequestHeaders, ISdkStatsNotifCbk, ISpanScope, ITelemetryContext as Common_ITelemetryContext,
15+
ITelemetryInitializerHandler, ITelemetryItem, ITelemetryPlugin, ITelemetryUnloadState, IThrottleInterval, IThrottleLimit,
16+
IThrottleMgrConfig, ITraceApi, ITraceProvider, ITraceTelemetry, IUnloadHook, OTelTimeInput, PropertiesPluginIdentifier, ThrottleMgr,
17+
UnloadHandler, WatcherFunction, _eInternalMessageId, _throwInternal, addPageHideEventListener, addPageUnloadEventListener, cfgDfMerge,
18+
cfgDfValidate, createDynamicConfig, createOTelApi, createProcessTelemetryContext, createSdkStatsNotifCbk, createTraceProvider,
19+
createUniqueNamespace, doPerf, eLoggingSeverity, hasDocument, hasWindow, isArray, isFeatureEnabled, isFunction, isNullOrUndefined,
20+
isReactNative, isString, mergeEvtNamespace, onConfigChange, parseConnectionString, proxyAssign, proxyFunctions,
21+
removePageHideEventListener, removePageUnloadEventListener, useSpan
2122
} from "@microsoft/applicationinsights-core-js";
2223
import {
2324
AjaxPlugin as DependenciesPlugin, DependencyInitializerFunction, DependencyListenerFunction, IDependencyInitializerHandler,
@@ -398,10 +399,15 @@ export class AppInsightsSku implements IApplicationInsights<IConfiguration & ICo
398399
// Register SDK Stats notification listener (on by default)
399400
if (isFeatureEnabled(SDK_STATS, _config, true)) {
400401
_sdkStatsListener = createSdkStatsNotifCbk({
401-
trk: function (item: ITelemetryItem) { _core.track(item); },
402+
trk: function (item: ITelemetryItem) {
403+
_core.track(item);
404+
},
402405
lang: "JavaScript",
403406
ver: SDK_STATS_VERSION,
404-
int: SDK_STATS_FLUSH_INTERVAL
407+
int: SDK_STATS_FLUSH_INTERVAL,
408+
fnFlush: function () {
409+
_self.onunloadFlush(false);
410+
}
405411
});
406412
_core.addNotificationListener(_sdkStatsListener);
407413
}
@@ -589,13 +595,6 @@ export class AppInsightsSku implements IApplicationInsights<IConfiguration & ICo
589595
if (!unloadDone) {
590596
unloadDone = true;
591597

592-
// Flush and remove SDK Stats listener before unload
593-
if (_sdkStatsListener && _core) {
594-
_sdkStatsListener.flush();
595-
_core.removeNotificationListener(_sdkStatsListener);
596-
_sdkStatsListener = null;
597-
}
598-
599598
// Reset OTel API to clean up all trace state before unloading core
600599
if (_core) {
601600
// Clear the trace provider to stop any active spans
@@ -619,6 +618,15 @@ export class AppInsightsSku implements IApplicationInsights<IConfiguration & ICo
619618

620619
_removePageEventHandlers();
621620

621+
// Unload SDK Stats listener BEFORE core.unload() tears down the pipeline.
622+
// unload() calls core.track() to enqueue the accumulated metrics,
623+
// then calls fnFlush to flush the channel so they actually get sent.
624+
if (_sdkStatsListener && _core) {
625+
_sdkStatsListener.unload();
626+
_core.removeNotificationListener(_sdkStatsListener);
627+
_sdkStatsListener = null;
628+
}
629+
622630
_core.unload && _core.unload(isAsync, _unloadCallback, cbTimeout);
623631

624632
return result;

shared/AppInsightsCore/src/core/NotificationManager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import { IPromise, createAllPromise, createPromise, doAwaitResponse } from "@nev
55
import { ITimerHandler, arrForEach, arrIndexOf, objDefine, safe, scheduleTimeout } from "@nevware21/ts-utils";
66
import { createDynamicConfig } from "../config/DynamicConfig";
77
import {
8-
STR_EVENTS_DISCARDED, STR_EVENTS_RETRY, STR_EVENTS_SEND_REQUEST, STR_EVENTS_SENT, STR_OFFLINE_DROP, STR_OFFLINE_SENT, STR_OFFLINE_STORE, STR_PERF_EVENT
8+
STR_EVENTS_DISCARDED, STR_EVENTS_RETRY, STR_EVENTS_SEND_REQUEST, STR_EVENTS_SENT, STR_OFFLINE_DROP, STR_OFFLINE_SENT, STR_OFFLINE_STORE,
9+
STR_PERF_EVENT
910
} from "../constants/InternalConstants";
1011
import { IConfiguration } from "../interfaces/ai/IConfiguration";
1112
import { INotificationListener } from "../interfaces/ai/INotificationListener";

shared/AppInsightsCore/src/core/SdkStatsNotificationCbk.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33
"use strict";
44

5-
import { ITimerHandler, scheduleTimeout } from "@nevware21/ts-utils";
5+
import { ITimerHandler, objHasOwn, scheduleTimeout } from "@nevware21/ts-utils";
66
import { INotificationListener } from "../interfaces/ai/INotificationListener";
77
import { ITelemetryItem } from "../interfaces/ai/ITelemetryItem";
88

@@ -51,6 +51,11 @@ export interface ISdkStatsConfig {
5151
* Flush interval override in ms (default 900000 = 15 min).
5252
*/
5353
int?: number;
54+
/**
55+
* Optional callback to flush the channel after enqueuing SDK stats metrics.
56+
* Called by unload() after core.track() so the metrics get transmitted before teardown.
57+
*/
58+
fnFlush?: () => void;
5459
}
5560

5661
/**
@@ -94,7 +99,7 @@ export function createSdkStatsNotifCbk(cfg: ISdkStatsConfig): ISdkStatsNotifCbk
9499

95100
function _isSdkStatsMetric(item: ITelemetryItem): boolean {
96101
var n = item.name;
97-
return n === "Item Success Count" || n === "Item Dropped Count" || n === "Item Retry Count";
102+
return n === MET_SUCCESS || n === MET_DROPPED || n === MET_RETRY;
98103
}
99104

100105
function _incSuccess(items: ITelemetryItem[]) {
@@ -145,8 +150,9 @@ export function createSdkStatsNotifCbk(cfg: ISdkStatsConfig): ISdkStatsNotifCbk
145150
name: name,
146151
baseType: "MetricData",
147152
baseData: {
148-
ver: 2,
149-
metrics: [{ name: name, value: value }],
153+
name: name,
154+
average: value,
155+
sampleCount: 1,
150156
properties: props
151157
}
152158
} as ITelemetryItem;
@@ -174,7 +180,7 @@ export function createSdkStatsNotifCbk(cfg: ISdkStatsConfig): ISdkStatsNotifCbk
174180

175181
// Flush success counts
176182
for (telType in _successCounts) {
177-
if (_successCounts.hasOwnProperty(telType)) {
183+
if (objHasOwn(_successCounts, telType)) {
178184
cnt = _successCounts[telType];
179185
if (cnt > 0) {
180186
var successProps: { [key: string]: any } = {};
@@ -186,10 +192,10 @@ export function createSdkStatsNotifCbk(cfg: ISdkStatsConfig): ISdkStatsNotifCbk
186192

187193
// Flush dropped counts
188194
for (code in _droppedCounts) {
189-
if (_droppedCounts.hasOwnProperty(code)) {
195+
if (objHasOwn(_droppedCounts, code)) {
190196
bucket = _droppedCounts[code];
191197
for (telType in bucket) {
192-
if (bucket.hasOwnProperty(telType)) {
198+
if (objHasOwn(bucket, telType)) {
193199
cnt = bucket[telType];
194200
if (cnt > 0) {
195201
var dropProps: { [key: string]: any } = {};
@@ -204,10 +210,10 @@ export function createSdkStatsNotifCbk(cfg: ISdkStatsConfig): ISdkStatsNotifCbk
204210

205211
// Flush retry counts
206212
for (code in _retryCounts) {
207-
if (_retryCounts.hasOwnProperty(code)) {
213+
if (objHasOwn(_retryCounts, code)) {
208214
bucket = _retryCounts[code];
209215
for (telType in bucket) {
210-
if (bucket.hasOwnProperty(telType)) {
216+
if (objHasOwn(bucket, telType)) {
211217
cnt = bucket[telType];
212218
if (cnt > 0) {
213219
var retryProps: { [key: string]: any } = {};
@@ -240,6 +246,8 @@ export function createSdkStatsNotifCbk(cfg: ISdkStatsConfig): ISdkStatsNotifCbk
240246
unload: function () {
241247
// Flush remaining counts before unload
242248
_flush();
249+
// Flush the channel so the metrics just enqueued actually get sent
250+
cfg.fnFlush && cfg.fnFlush();
243251
if (_timer) {
244252
_timer.cancel();
245253
_timer = null;

0 commit comments

Comments
 (0)