UNPKG

@microsoft/applicationinsights-core-js

Version:

Microsoft Application Insights Core Javascript SDK

931 lines (929 loc) • 66.7 kB
/* * Application Insights JavaScript SDK - Core, 3.3.9 * Copyright (c) Microsoft and contributors. All rights reserved. */ var _a; import { __spreadArrayFn as __spreadArray } from "@microsoft/applicationinsights-shims"; import dynamicProto from "@microsoft/dynamicproto-js"; import { createPromise, createSyncAllSettledPromise, doAwaitResponse } from "@nevware21/ts-async"; import { arrAppend, arrForEach, arrIndexOf, createTimeout, deepExtend, hasDocument, isFunction, isNullOrUndefined, isPlainObject, isPromiseLike, objDeepFreeze, objDefine, objForEachKey, objFreeze, objHasOwn, scheduleTimeout, throwError } from "@nevware21/ts-utils"; import { createDynamicConfig, onConfigChange } from "../Config/DynamicConfig"; import { ActiveStatus } from "../JavaScriptSDK.Enums/InitActiveStatusEnum"; import { _DYN_ADD_NOTIFICATION_LIS1, _DYN_CANCEL, _DYN_CREATE_NEW, _DYN_ENABLED, _DYN_GET_NOTIFY_MGR, _DYN_GET_PLUGIN, _DYN_GET_PROCESS_TEL_CONT2, _DYN_IDENTIFIER, _DYN_INITIALIZE, _DYN_IS_INITIALIZED, _DYN_LENGTH, _DYN_LOGGER, _DYN_LOGGING_LEVEL_CONSOL4, _DYN_MESSAGE, _DYN_MESSAGE_ID, _DYN_NAME, _DYN_ON_COMPLETE, _DYN_PROCESS_NEXT, _DYN_PUSH, _DYN_REMOVE_NOTIFICATION_0, _DYN_SPLICE, _DYN_STOP_POLLING_INTERNA3, _DYN_TEARDOWN, _DYN_UNLOAD, _DYN_VALUE, _DYN_VERSION, _DYN_WATCH } from "../__DynamicConstants"; import { doUnloadAll, runTargetUnload } from "./AsyncUtils"; import { ChannelControllerPriority } from "./Constants"; import { createCookieMgr } from "./CookieMgr"; import { createUniqueNamespace } from "./DataCacheHelper"; import { getDebugListener } from "./DbgExtensionUtils"; import { DiagnosticLogger, _InternalLogMessage, _throwInternal, _warnToConsole } from "./DiagnosticLogger"; import { getSetValue, isNotNullOrUndefined, proxyFunctionAs, proxyFunctions, toISOString } from "./HelperFuncs"; import { STR_CHANNELS, STR_CORE, STR_CREATE_PERF_MGR, STR_DISABLED, STR_EMPTY, STR_EVENTS_DISCARDED, STR_EXTENSIONS, STR_EXTENSION_CONFIG, STR_GET_PERF_MGR, STR_PRIORITY, UNDEFINED_VALUE } from "./InternalConstants"; import { NotificationManager } from "./NotificationManager"; import { PerfManager, doPerf, getGblPerfMgr } from "./PerfManager"; import { createProcessTelemetryContext, createProcessTelemetryUnloadContext, createProcessTelemetryUpdateContext, createTelemetryProxyChain } from "./ProcessTelemetryContext"; import { _getPluginState, createDistributedTraceContext, initializePlugins, sortPlugins } from "./TelemetryHelpers"; import { TelemetryInitializerPlugin } from "./TelemetryInitializerPlugin"; import { createUnloadHandlerContainer } from "./UnloadHandlerContainer"; import { createUnloadHookContainer } from "./UnloadHookContainer"; // import { IStatsBeat, IStatsBeatConfig, IStatsBeatState } from "../JavaScriptSDK.Interfaces/IStatsBeat"; // import { IStatsMgr } from "../JavaScriptSDK.Interfaces/IStatsMgr"; var strValidationError = "Plugins must provide initialize method"; var strNotificationManager = "_notificationManager"; var strSdkUnloadingError = "SDK is still unloading..."; var strSdkNotInitialized = "SDK is not initialized"; var maxInitQueueSize = 100; var maxInitTimeout = 50000; // const strPluginUnloadFailed = "Failed to unload plugin"; // /** // * Default StatsBeatMgr configuration // * @internal // */ // const defaultStatsCfg: IConfigDefaults<IStatsBeatConfig> = objDeepFreeze({ // shrtInt: UNDEFINED_VALUE, // endCfg: cfgDfMerge([]) // }); // /** // * Default SDK initialization configuration // * @internal // */ // const defaultSdkConfig: IConfigDefaults<IInternalSdkConfiguration> = objDeepFreeze({ // stats: { rdOnly: true, mrg: true, v: defaultStatsCfg } // }); /** * The default settings for the config. * WE MUST include all defaults here to ensure that the config is created with all of the properties * defined as dynamic. */ var defaultConfig = objDeepFreeze((_a = { cookieCfg: {} }, _a[STR_EXTENSIONS] = { rdOnly: true, ref: true, v: [] }, _a[STR_CHANNELS] = { rdOnly: true, ref: true, v: [] }, _a[STR_EXTENSION_CONFIG] = { ref: true, v: {} }, _a[STR_CREATE_PERF_MGR] = UNDEFINED_VALUE, _a.loggingLevelConsole = 0 /* eLoggingSeverity.DISABLED */, _a.diagnosticLogInterval = UNDEFINED_VALUE, _a)); /** * Helper to create the default performance manager * @param core - The AppInsightsCore instance * @param notificationMgr - The notification manager */ function _createPerfManager(core, notificationMgr) { return new PerfManager(notificationMgr); } function _validateExtensions(logger, channelPriority, allExtensions) { // Concat all available extensions var coreExtensions = []; var channels = []; // Check if any two extensions have the same priority, then warn to console // And extract the local extensions from the var extPriorities = {}; // Extension validation arrForEach(allExtensions, function (ext) { // Check for ext.initialize if (isNullOrUndefined(ext) || isNullOrUndefined(ext[_DYN_INITIALIZE /* @min:%2einitialize */])) { throwError(strValidationError); } var extPriority = ext[STR_PRIORITY /* @min:%2epriority */]; var identifier = ext[_DYN_IDENTIFIER /* @min:%2eidentifier */]; if (ext && extPriority) { if (!isNullOrUndefined(extPriorities[extPriority])) { _warnToConsole(logger, "Two extensions have same priority #" + extPriority + " - " + extPriorities[extPriority] + ", " + identifier); } else { // set a value extPriorities[extPriority] = identifier; } } // Split extensions to core and channels if (!extPriority || extPriority < channelPriority) { // Add to core extension that will be managed by AppInsightsCore coreExtensions[_DYN_PUSH /* @min:%2epush */](ext); } else { channels[_DYN_PUSH /* @min:%2epush */](ext); } }); return { core: coreExtensions, channels: channels }; } function _isPluginPresent(thePlugin, plugins) { var exists = false; arrForEach(plugins, function (plugin) { if (plugin === thePlugin) { exists = true; return -1; } }); return exists; } function _deepMergeConfig(details, target, newValues, merge) { // Lets assign the new values to the existing config if (newValues) { objForEachKey(newValues, function (key, value) { if (merge) { if (isPlainObject(value) && isPlainObject(target[key])) { // The target is an object and it has a value _deepMergeConfig(details, target[key], value, merge); } } if (merge && isPlainObject(value) && isPlainObject(target[key])) { // The target is an object and it has a value _deepMergeConfig(details, target[key], value, merge); } else { // Just Assign (replace) and/or make the property dynamic details.set(target, key, value); } }); } } function _findWatcher(listeners, newWatcher) { var theListener = null; var idx = -1; arrForEach(listeners, function (listener, lp) { if (listener.w === newWatcher) { theListener = listener; idx = lp; return -1; } }); return { i: idx, l: theListener }; } function _addDelayedCfgListener(listeners, newWatcher) { var theListener = _findWatcher(listeners, newWatcher).l; if (!theListener) { theListener = { w: newWatcher, rm: function () { var fnd = _findWatcher(listeners, newWatcher); if (fnd.i !== -1) { listeners[_DYN_SPLICE /* @min:%2esplice */](fnd.i, 1); } } }; listeners[_DYN_PUSH /* @min:%2epush */](theListener); } return theListener; } function _registerDelayedCfgListener(config, listeners, logger) { arrForEach(listeners, function (listener) { var unloadHdl = onConfigChange(config, listener.w, logger); delete listener.w; // Clear the listener reference so it will get garbage collected. // replace the remove function listener.rm = function () { unloadHdl.rm(); }; }); } // Moved this outside of the closure to reduce the retained memory footprint function _initDebugListener(configHandler, unloadContainer, notificationManager, debugListener) { // Will get recalled if any referenced config values are changed unloadContainer.add(configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) { var disableDbgExt = details.cfg.disableDbgExt; if (disableDbgExt === true && debugListener) { // Remove any previously loaded debug listener notificationManager[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */](debugListener); debugListener = null; } if (notificationManager && !debugListener && disableDbgExt !== true) { debugListener = getDebugListener(details.cfg); notificationManager[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */](debugListener); } })); return debugListener; } // Moved this outside of the closure to reduce the retained memory footprint function _createUnloadHook(unloadHook) { return objDefine({ rm: function () { unloadHook.rm(); } }, "toJSON", { v: function () { return "aicore::onCfgChange<" + JSON.stringify(unloadHook) + ">"; } }); } /** * @group Classes * @group Entrypoint */ var AppInsightsCore = /** @class */ (function () { function AppInsightsCore() { // NOTE!: DON'T set default values here, instead set them in the _initDefaults() function as it is also called during teardown() var _configHandler; var _isInitialized; var _logger; var _eventQueue; var _notificationManager; // let _statsBeat: IStatsBeat | null; // let _statsMgr: IStatsMgr | null; var _perfManager; var _cfgPerfManager; var _cookieManager; var _pluginChain; var _configExtensions; var _channelConfig; var _channels; var _isUnloading; var _telemetryInitializerPlugin; var _internalLogsEventName; var _evtNamespace; var _unloadHandlers; var _hookContainer; var _debugListener; var _traceCtx; var _instrumentationKey; var _cfgListeners; var _extensions; var _pluginVersionStringArr; var _pluginVersionString; var _activeStatus; // to indicate if ikey or endpoint url promised is resolved or not var _endpoint; var _initInMemoMaxSize; // max event count limit during wait for init promises to be resolved var _isStatusSet; // track if active status is set in case of init timeout and init promises setting the status twice var _initTimer; /** * Internal log poller */ var _internalLogPoller; var _internalLogPollerListening; var _forceStopInternalLogPoller; dynamicProto(AppInsightsCore, this, function (_self) { // Set the default values (also called during teardown) _initDefaults(); // Special internal method to allow the unit tests and DebugPlugin to hook embedded objects _self["_getDbgPlgTargets"] = function () { return [_extensions, _eventQueue]; }; _self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */] = function () { return _isInitialized; }; // since version 3.3.0 _self.activeStatus = function () { return _activeStatus; }; // since version 3.3.0 // internal _self._setPendingStatus = function () { _activeStatus = 3 /* eActiveStatus.PENDING */; }; // Creating the self.initialize = () _self[_DYN_INITIALIZE /* @min:%2einitialize */] = function (config, extensions, logger, notificationManager) { if (_isUnloading) { throwError(strSdkUnloadingError); } // Make sure core is only initialized once if (_self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */]()) { throwError("Core cannot be initialized more than once"); } _configHandler = createDynamicConfig(config, defaultConfig, logger || _self[_DYN_LOGGER /* @min:%2elogger */], false); // Re-assigning the local config property so we don't have any references to the passed value and it can be garbage collected config = _configHandler.cfg; // This will be "re-run" if the referenced config properties are changed _addUnloadHook(_configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) { var rootCfg = details.cfg; _initInMemoMaxSize = rootCfg.initInMemoMaxSize || maxInitQueueSize; _handleIKeyEndpointPromises(rootCfg); // Mark the extensionConfig and all first level keys as referenced // This is so that calls to getExtCfg() will always return the same object // Even when a user may "re-assign" the plugin properties (or it's unloaded/reloaded) var extCfg = details.ref(details.cfg, STR_EXTENSION_CONFIG); objForEachKey(extCfg, function (key) { details.ref(extCfg, key); }); })); _notificationManager = notificationManager; // Initialize the debug listener outside of the closure to reduce the retained memory footprint _debugListener = _initDebugListener(_configHandler, _hookContainer, _notificationManager && _self[_DYN_GET_NOTIFY_MGR /* @min:%2egetNotifyMgr */](), _debugListener); _initPerfManager(); _self[_DYN_LOGGER /* @min:%2elogger */] = logger; var cfgExtensions = config[STR_EXTENSIONS /* @min:%2eextensions */]; // Extension validation _configExtensions = []; _configExtensions[_DYN_PUSH /* @min:%2epush */].apply(_configExtensions, __spreadArray(__spreadArray([], extensions, false), cfgExtensions, false)); _channelConfig = config[STR_CHANNELS /* @min:%2echannels */]; _initPluginChain(null); if (!_channels || _channels[_DYN_LENGTH /* @min:%2elength */] === 0) { throwError("No " + STR_CHANNELS + " available"); } if (_channelConfig && _channelConfig[_DYN_LENGTH /* @min:%2elength */] > 1) { var teeController = _self[_DYN_GET_PLUGIN /* @min:%2egetPlugin */]("TeeChannelController"); if (!teeController || !teeController.plugin) { _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 28 /* _eInternalMessageId.SenderNotInitialized */, "TeeChannel required"); } } _registerDelayedCfgListener(config, _cfgListeners, _logger); _cfgListeners = null; _isInitialized = true; if (_activeStatus === ActiveStatus.ACTIVE) { _releaseQueues(); } }; _self.getChannels = function () { var controls = []; if (_channels) { arrForEach(_channels, function (channel) { controls[_DYN_PUSH /* @min:%2epush */](channel); }); } return objFreeze(controls); }; _self.track = function (telemetryItem) { doPerf(_self[STR_GET_PERF_MGR /* @min:%2egetPerfMgr */](), function () { return "AppInsightsCore:track"; }, function () { if (telemetryItem === null) { _notifyInvalidEvent(telemetryItem); // throw error throwError("Invalid telemetry item"); } // do basic validation before sending it through the pipeline if (!telemetryItem[_DYN_NAME /* @min:%2ename */] && isNullOrUndefined(telemetryItem[_DYN_NAME /* @min:%2ename */])) { _notifyInvalidEvent(telemetryItem); throwError("telemetry name required"); } // setup default iKey if not passed in telemetryItem.iKey = telemetryItem.iKey || _instrumentationKey; // add default timestamp if not passed in telemetryItem.time = telemetryItem.time || toISOString(new Date()); // Common Schema 4.0 telemetryItem.ver = telemetryItem.ver || "4.0"; if (!_isUnloading && _self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */]() && _activeStatus === ActiveStatus.ACTIVE) { // Process the telemetry plugin chain _createTelCtx()[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](telemetryItem); } else if (_activeStatus !== ActiveStatus.INACTIVE) { // Queue events until all extensions are initialized if (_eventQueue[_DYN_LENGTH /* @min:%2elength */] <= _initInMemoMaxSize) { // set limit, if full, stop adding new events _eventQueue[_DYN_PUSH /* @min:%2epush */](telemetryItem); } } }, function () { return ({ item: telemetryItem }); }, !(telemetryItem.sync)); }; _self[_DYN_GET_PROCESS_TEL_CONT2 /* @min:%2egetProcessTelContext */] = _createTelCtx; _self[_DYN_GET_NOTIFY_MGR /* @min:%2egetNotifyMgr */] = function () { if (!_notificationManager) { _notificationManager = new NotificationManager(_configHandler.cfg); // For backward compatibility only _self[strNotificationManager] = _notificationManager; } return _notificationManager; }; /** * Adds a notification listener. The SDK calls methods on the listener when an appropriate notification is raised. * The added plugins must raise notifications. If the plugins do not implement the notifications, then no methods will be * called. * @param listener - An INotificationListener object. */ _self[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */] = function (listener) { _self.getNotifyMgr()[_DYN_ADD_NOTIFICATION_LIS1 /* @min:%2eaddNotificationListener */](listener); }; /** * Removes all instances of the listener. * @param listener - INotificationListener to remove. */ _self[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */] = function (listener) { if (_notificationManager) { _notificationManager[_DYN_REMOVE_NOTIFICATION_0 /* @min:%2eremoveNotificationListener */](listener); } }; _self.getCookieMgr = function () { if (!_cookieManager) { _cookieManager = createCookieMgr(_configHandler.cfg, _self[_DYN_LOGGER /* @min:%2elogger */]); } return _cookieManager; }; _self.setCookieMgr = function (cookieMgr) { if (_cookieManager !== cookieMgr) { runTargetUnload(_cookieManager, false); _cookieManager = cookieMgr; } }; _self[STR_GET_PERF_MGR /* @min:%2egetPerfMgr */] = function () { return _perfManager || _cfgPerfManager || getGblPerfMgr(); }; _self.setPerfMgr = function (perfMgr) { _perfManager = perfMgr; }; // _self.getStatsBeat = (statsBeatState: IStatsBeatState) => { // // create a new statsbeat if not initialize yet or the endpoint is different // // otherwise, return the existing one, or null // if (statsBeatState) { // if (_statsMgr && _statsMgr.enabled) { // if (_statsBeat && _statsBeat.endpoint !== statsBeatState.endpoint) { // // Different endpoint, so unload the existing and create a new one // _statsBeat.enabled = false; // _statsBeat = null; // } // if (!_statsBeat) { // // Create a new statsbeat instance // _statsBeat = _statsMgr.newInst(statsBeatState); // } // } else if (_statsBeat) { // // Disable and remove any previously created statsbeat instance // _statsBeat.enabled = false; // _statsBeat = null; // } // // Return the current statsbeat instance or null if not created // return _statsBeat; // } // // Return null as no statsbeat state was provided // return null; // }; // _self.setStatsMgr = (statsMgr: IStatsMgr) => { // if (_statsMgr && _statsMgr !== statsMgr) { // // Disable any previously created statsbeat instance // if (_statsBeat) { // _statsBeat.enabled = false; // _statsBeat = null; // } // } // _statsMgr = statsMgr; // }; _self.eventCnt = function () { return _eventQueue[_DYN_LENGTH /* @min:%2elength */]; }; _self.releaseQueue = function () { if (_isInitialized && _eventQueue[_DYN_LENGTH /* @min:%2elength */] > 0) { var eventQueue = _eventQueue; _eventQueue = []; if (_activeStatus === 2 /* eActiveStatus.ACTIVE */) { arrForEach(eventQueue, function (event) { event.iKey = event.iKey || _instrumentationKey; _createTelCtx()[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](event); }); } else { // new one for msg ikey _throwInternal(_logger, 2 /* eLoggingSeverity.WARNING */, 20 /* _eInternalMessageId.FailedToSendQueuedTelemetry */, "core init status is not active"); } } }; _self.pollInternalLogs = function (eventName) { _internalLogsEventName = eventName || null; _forceStopInternalLogPoller = false; _internalLogPoller && _internalLogPoller[_DYN_CANCEL /* @min:%2ecancel */](); return _startLogPoller(true); }; function _handleIKeyEndpointPromises(theConfig) { // app Insights core only handle ikey and endpointurl, aisku will handle cs // But we want to reference these config values so that if any future changes are made // this will trigger the re-run of the watch function // and the ikey and endpointUrl will be set to the new values var ikey = theConfig.instrumentationKey; var endpointUrl = theConfig.endpointUrl; // do not need to validate endpoint url, if it is null, default one will be set by sender // Check if we are waiting for previous promises to be resolved, won't apply new changes if (_activeStatus !== 3 /* eActiveStatus.PENDING */) { if (isNullOrUndefined(ikey)) { _instrumentationKey = null; // if new ikey is null, set status to be inactive, all new events will be saved in memory or dropped _activeStatus = ActiveStatus.INACTIVE; var msg = "Please provide instrumentation key"; if (!_isInitialized) { // only throw error during initialization throwError(msg); } else { _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 100 /* _eInternalMessageId.InvalidInstrumentationKey */, msg); _releaseQueues(); } return; } var promises = []; if (isPromiseLike(ikey)) { promises[_DYN_PUSH /* @min:%2epush */](ikey); _instrumentationKey = null; // reset current local ikey variable (otherwise it will always be the previous ikeys if timeout is called before promise cb) } else { // string _instrumentationKey = ikey; } if (isPromiseLike(endpointUrl)) { promises[_DYN_PUSH /* @min:%2epush */](endpointUrl); _endpoint = null; // reset current local endpoint variable (otherwise it will always be the previous urls if timeout is called before promise cb) } else { // string or null _endpoint = endpointUrl; } // at least have one promise if (promises[_DYN_LENGTH /* @min:%2elength */]) { _waitForInitPromises(theConfig, promises); } else { // means no promises _setStatus(); } } } function _waitForInitPromises(theConfig, promises) { // reset to false for new dynamic changes _isStatusSet = false; _activeStatus = 3 /* eActiveStatus.PENDING */; var initTimeout = isNotNullOrUndefined(theConfig.initTimeOut) ? theConfig.initTimeOut : maxInitTimeout; // theConfig.initTimeOut could be 0 var allPromises = createSyncAllSettledPromise(promises); if (_initTimer) { // Stop any previous timer _initTimer[_DYN_CANCEL /* @min:%2ecancel */](); } _initTimer = scheduleTimeout(function () { // set _isStatusSet to true // set active status // release queues _initTimer = null; if (!_isStatusSet) { _setStatus(); } }, initTimeout); doAwaitResponse(allPromises, function (response) { try { if (_isStatusSet) { // promises take too long to resolve, ignore them // active status should be set by timeout already return; } if (!response.rejected) { var values = response[_DYN_VALUE /* @min:%2evalue */]; if (values && values[_DYN_LENGTH /* @min:%2elength */]) { // ikey var ikeyRes = values[0]; _instrumentationKey = ikeyRes && ikeyRes[_DYN_VALUE /* @min:%2evalue */]; // endpoint if (values[_DYN_LENGTH /* @min:%2elength */] > 1) { var endpointRes = values[1]; _endpoint = endpointRes && endpointRes[_DYN_VALUE /* @min:%2evalue */]; } } if (_instrumentationKey) { // if ikey is null, no need to trigger extra dynamic changes for extensions theConfig.instrumentationKey = _instrumentationKey; // set config.instrumentationKey for extensions to consume theConfig.endpointUrl = _endpoint; // set config.endpointUrl for extensions to consume } } // set _isStatusSet to true // set active status // release queues _setStatus(); } catch (e) { if (!_isStatusSet) { _setStatus(); } } }); } function _setStatus() { _isStatusSet = true; if (isNullOrUndefined(_instrumentationKey)) { _activeStatus = ActiveStatus.INACTIVE; _throwInternal(_logger, 1 /* eLoggingSeverity.CRITICAL */, 112 /* _eInternalMessageId.InitPromiseException */, "ikey can't be resolved from promises"); } else { _activeStatus = ActiveStatus.ACTIVE; } _releaseQueues(); } function _releaseQueues() { if (_isInitialized) { _self.releaseQueue(); _self.pollInternalLogs(); } } function _startLogPoller(alwaysStart) { if ((!_internalLogPoller || !_internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */]) && !_forceStopInternalLogPoller) { var shouldStart = alwaysStart || (_logger && _logger.queue[_DYN_LENGTH /* @min:%2elength */] > 0); if (shouldStart) { if (!_internalLogPollerListening) { _internalLogPollerListening = true; // listen for any configuration changes so that changes to the // interval will cause the timer to be re-initialized _addUnloadHook(_configHandler[_DYN_WATCH /* @min:%2ewatch */](function (details) { var interval = details.cfg.diagnosticLogInterval; if (!interval || !(interval > 0)) { interval = 10000; } var isRunning = false; if (_internalLogPoller) { // It was already created so remember it's running and cancel isRunning = _internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */]; _internalLogPoller[_DYN_CANCEL /* @min:%2ecancel */](); } // Create / reconfigure _internalLogPoller = createTimeout(_flushInternalLogs, interval); _internalLogPoller.unref(); // Restart if previously running _internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */] = isRunning; })); } _internalLogPoller[_DYN_ENABLED /* @min:%2eenabled */] = true; } } return _internalLogPoller; } _self[_DYN_STOP_POLLING_INTERNA3 /* @min:%2estopPollingInternalLogs */] = function () { _forceStopInternalLogPoller = true; _internalLogPoller && _internalLogPoller[_DYN_CANCEL /* @min:%2ecancel */](); _flushInternalLogs(); }; // Add addTelemetryInitializer proxyFunctions(_self, function () { return _telemetryInitializerPlugin; }, ["addTelemetryInitializer"]); _self[_DYN_UNLOAD /* @min:%2eunload */] = function (isAsync, unloadComplete, cbTimeout) { if (isAsync === void 0) { isAsync = true; } if (!_isInitialized) { // The SDK is not initialized throwError(strSdkNotInitialized); } // Check if the SDK still unloading so throw if (_isUnloading) { // The SDK is already unloading throwError(strSdkUnloadingError); } var unloadState = { reason: 50 /* TelemetryUnloadReason.SdkUnload */, isAsync: isAsync, flushComplete: false }; var result; if (isAsync && !unloadComplete) { result = createPromise(function (resolve) { // Set the callback to the promise resolve callback unloadComplete = resolve; }); } var processUnloadCtx = createProcessTelemetryUnloadContext(_getPluginChain(), _self); processUnloadCtx[_DYN_ON_COMPLETE /* @min:%2eonComplete */](function () { // if (_statsBeat) { // // Disable any statsbeat instance // _statsBeat.enabled = false; // _statsBeat = null; // } _hookContainer.run(_self[_DYN_LOGGER /* @min:%2elogger */]); // Run any "unload" functions for the _cookieManager, _notificationManager and _logger doUnloadAll([_cookieManager, _notificationManager, _logger], isAsync, function () { _initDefaults(); unloadComplete && unloadComplete(unloadState); }); }, _self); function _doUnload(flushComplete) { unloadState.flushComplete = flushComplete; _isUnloading = true; // Run all of the unload handlers first (before unloading the plugins) _unloadHandlers.run(processUnloadCtx, unloadState); // Stop polling the internal logs _self[_DYN_STOP_POLLING_INTERNA3 /* @min:%2estopPollingInternalLogs */](); // Start unloading the components, from this point onwards the SDK should be considered to be in an unstable state processUnloadCtx[_DYN_PROCESS_NEXT /* @min:%2eprocessNext */](unloadState); } _flushInternalLogs(); if (!_flushChannels(isAsync, _doUnload, 6 /* SendRequestReason.SdkUnload */, cbTimeout)) { _doUnload(false); } return result; }; _self[_DYN_GET_PLUGIN /* @min:%2egetPlugin */] = _getPlugin; _self.addPlugin = function (plugin, replaceExisting, isAsync, addCb) { if (!plugin) { addCb && addCb(false); _logOrThrowError(strValidationError); return; } var existingPlugin = _getPlugin(plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */]); if (existingPlugin && !replaceExisting) { addCb && addCb(false); _logOrThrowError("Plugin [" + plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */] + "] is already loaded!"); return; } var updateState = { reason: 16 /* TelemetryUpdateReason.PluginAdded */ }; function _addPlugin(removed) { _configExtensions[_DYN_PUSH /* @min:%2epush */](plugin); updateState.added = [plugin]; // Re-Initialize the plugin chain _initPluginChain(updateState); addCb && addCb(true); } if (existingPlugin) { var removedPlugins_1 = [existingPlugin.plugin]; var unloadState = { reason: 2 /* TelemetryUnloadReason.PluginReplace */, isAsync: !!isAsync }; _removePlugins(removedPlugins_1, unloadState, function (removed) { if (!removed) { // Previous plugin was successfully removed or was not installed addCb && addCb(false); } else { updateState.removed = removedPlugins_1; updateState.reason |= 32 /* TelemetryUpdateReason.PluginRemoved */; _addPlugin(true); } }); } else { _addPlugin(false); } }; _self.updateCfg = function (newConfig, mergeExisting) { if (mergeExisting === void 0) { mergeExisting = true; } var updateState; if (_self[_DYN_IS_INITIALIZED /* @min:%2eisInitialized */]()) { updateState = { reason: 1 /* TelemetryUpdateReason.ConfigurationChanged */, cfg: _configHandler.cfg, oldCfg: deepExtend({}, _configHandler.cfg), newConfig: deepExtend({}, newConfig), merge: mergeExisting }; newConfig = updateState.newConfig; var cfg = _configHandler.cfg; // replace the immutable (if initialized) values // We don't currently allow updating the extensions and channels via the update config // So overwriting any user provided values to reuse the existing values newConfig[STR_EXTENSIONS /* @min:%2eextensions */] = cfg[STR_EXTENSIONS /* @min:%2eextensions */]; newConfig[STR_CHANNELS /* @min:%2echannels */] = cfg[STR_CHANNELS /* @min:%2echannels */]; } // Explicitly blocking any previous config watchers so that they don't get called because // of this bulk update (Probably not necessary) _configHandler._block(function (details) { // Lets assign the new values to the existing config either overwriting or re-assigning var theConfig = details.cfg; _deepMergeConfig(details, theConfig, newConfig, mergeExisting); if (!mergeExisting) { // Remove (unassign) the values "missing" from the newConfig and also not in the default config objForEachKey(theConfig, function (key) { if (!objHasOwn(newConfig, key)) { // Set the value to undefined details.set(theConfig, key, UNDEFINED_VALUE); } }); } // Apply defaults to the new config details.setDf(theConfig, defaultConfig); }, true); // Now execute all of the listeners (synchronously) so they update their values immediately _configHandler.notify(); if (updateState) { _doUpdate(updateState); } }; _self.evtNamespace = function () { return _evtNamespace; }; _self.flush = _flushChannels; _self.getTraceCtx = function (createNew) { if (!_traceCtx) { _traceCtx = createDistributedTraceContext(); } return _traceCtx; }; _self.setTraceCtx = function (traceCtx) { _traceCtx = traceCtx || null; }; _self.addUnloadHook = _addUnloadHook; // Create the addUnloadCb proxyFunctionAs(_self, "addUnloadCb", function () { return _unloadHandlers; }, "add"); _self.onCfgChange = function (handler) { var unloadHook; if (!_isInitialized) { unloadHook = _addDelayedCfgListener(_cfgListeners, handler); } else { unloadHook = onConfigChange(_configHandler.cfg, handler, _self[_DYN_LOGGER /* @min:%2elogger */]); } return _createUnloadHook(unloadHook); }; _self.getWParam = function () { return (hasDocument() || !!_configHandler.cfg.enableWParam) ? 0 : -1; }; function _setPluginVersions() { var thePlugins = {}; _pluginVersionStringArr = []; var _addPluginVersions = function (plugins) { if (plugins) { arrForEach(plugins, function (plugin) { if (plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */] && plugin[_DYN_VERSION /* @min:%2eversion */] && !thePlugins[plugin.identifier]) { var ver = plugin[_DYN_IDENTIFIER /* @min:%2eidentifier */] + "=" + plugin[_DYN_VERSION /* @min:%2eversion */]; _pluginVersionStringArr[_DYN_PUSH /* @min:%2epush */](ver); thePlugins[plugin.identifier] = plugin; } }); } }; _addPluginVersions(_channels); if (_channelConfig) { arrForEach(_channelConfig, function (channels) { _addPluginVersions(channels); }); } _addPluginVersions(_configExtensions); } function _initDefaults() { _isInitialized = false; // Use a default logger so initialization errors are not dropped on the floor with full logging _configHandler = createDynamicConfig({}, defaultConfig, _self[_DYN_LOGGER /* @min:%2elogger */]); // Set the logging level to critical so that any critical initialization failures are displayed on the console _configHandler.cfg[_DYN_LOGGING_LEVEL_CONSOL4 /* @min:%2eloggingLevelConsole */] = 1 /* eLoggingSeverity.CRITICAL */; // Define _self.config objDefine(_self, "config", { g: function () { return _configHandler.cfg; }, s: function (newValue) { _self.updateCfg(newValue, false); } }); objDefine(_self, "pluginVersionStringArr", { g: function () { if (!_pluginVersionStringArr) { _setPluginVersions(); } return _pluginVersionStringArr; } }); objDefine(_self, "pluginVersionString", { g: function () { if (!_pluginVersionString) { if (!_pluginVersionStringArr) { _setPluginVersions(); } _pluginVersionString = _pluginVersionStringArr.join(";"); } return _pluginVersionString || STR_EMPTY; } }); objDefine(_self, "logger", { g: function () { if (!_logger) { _logger = new DiagnosticLogger(_configHandler.cfg); _configHandler[_DYN_LOGGER /* @min:%2elogger */] = _logger; } return _logger; }, s: function (newLogger) { _configHandler[_DYN_LOGGER /* @min:%2elogger */] = newLogger; if (_logger !== newLogger) { runTargetUnload(_logger, false); _logger = newLogger; } } }); _self[_DYN_LOGGER /* @min:%2elogger */] = new DiagnosticLogger(_configHandler.cfg); _extensions = []; var cfgExtensions = _self.config[STR_EXTENSIONS /* @min:%2eextensions */] || []; cfgExtensions.splice(0, cfgExtensions[_DYN_LENGTH /* @min:%2elength */]); arrAppend(cfgExtensions, _extensions); _telemetryInitializerPlugin = new TelemetryInitializerPlugin(); _eventQueue = []; runTargetUnload(_notificationManager, false); _notificationManager = null; _perfManager = null; // _statsBeat = null; _cfgPerfManager = null; runTargetUnload(_cookieManager, false); _cookieManager = null; _pluginChain = null; _configExtensions = []; _channelConfig = null; _channels = null; _isUnloading = false; _internalLogsEventName = null; _evtNamespace = createUniqueNamespace("AIBaseCore", true); _unloadHandlers = createUnloadHandlerContainer(); _traceCtx = null; _instrumentationKey = null; _hookContainer = createUnloadHookContainer(); _cfgListeners = []; _pluginVersionString = null; _pluginVersionStringArr = null; _forceStopInternalLogPoller = false; _internalLogPoller = null; _internalLogPollerListening = false; _activeStatus = 0 /* eActiveStatus.NONE */; // default is None _endpoint = null; _initInMemoMaxSize = null; _isStatusSet = false; _initTimer = null; // if (_statsBeat) { // // Unload and disable any statsbeat instance // _statsBeat.enabled = false; // } // _statsBeat = null; } function _createTelCtx() { var theCtx = createProcessTelemetryContext(_getPluginChain(), _configHandler.cfg, _self); theCtx[_DYN_ON_COMPLETE /* @min:%2eonComplete */](_startLogPoller); return theCtx; } // Initialize or Re-initialize the plugins function _initPluginChain(updateState) { // Extension validation var theExtensions = _validateExtensions(_self[_DYN_LOGGER /* @min:%2elogger */], ChannelControllerPriority, _configExtensions); _pluginChain = null; _pluginVersionString = null; _pluginVersionStringArr = null; // Get the primary channel queue and include as part of the normal extensions _channels = (_channelConfig || [])[0] || []; // Add any channels provided in the extensions and sort them _channels = sortPlugins(arrAppend(_channels, theExtensions[STR_CHANNELS /* @min:%2echannels */])); // Create an array of all extensions, including the _channels var allExtensions = arrAppend(sortPlugins(theExtensions[STR_CORE /* @min:%2ecore */]), _channels); // Required to allow plugins to call core.getPlugin() during their own initialization _extensions = objFreeze(allExtensions); // This has a side effect of adding the extensions passed during initialization // into