Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Master] Add ability to disable the pollInternalLogs via config and change to stop using setInterval #2055 #2056

Merged
merged 1 commit into from
Apr 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions AISKU/Tests/Unit/src/applicationinsights.e2e.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,8 @@ export class ApplicationInsightsTests extends AITestClass {
this.testCaseAsync({
name: "TelemetryContext: auto collection of ajax requests",
stepDelay: 1,
useFakeServer: true,
fakeServerAutoRespond: true,
steps: [
() => {
const xhr = new XMLHttpRequest();
Expand All @@ -627,6 +629,8 @@ export class ApplicationInsightsTests extends AITestClass {
this.testCaseAsync({
name: "DependenciesPlugin: auto collection of outgoing fetch requests " + (this.isFetchPolyfill ? " using polyfill " : ""),
stepDelay: 5000,
useFakeFetch: true,
fakeFetchAutoRespond: true,
steps: [
() => {
fetch('https://httpbin.org/status/200', { method: 'GET', headers: { 'header': 'value'} });
Expand All @@ -640,8 +644,7 @@ export class ApplicationInsightsTests extends AITestClass {
fetch('https://httpbin.org/status/200');
Assert.ok(true, "fetch monitoring is instrumented");
}
]
.concat(this.asserts(3, false, false))
].concat(this.asserts(3, false, false))
.concat(() => {
let args = [];
this.trackSpy.args.forEach(call => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class PageViewManager {
pageViewPerformanceManager: PageViewPerformanceManager) {

dynamicProto(PageViewManager, this, (_self) => {
let intervalHandle: any = null;
let queueTimer: any = null;
let itemQueue: Array<() => boolean> = [];
let pageViewPerformanceSent: boolean = false;
let _logger: IDiagnosticLogger;
Expand All @@ -63,11 +63,10 @@ export class PageViewManager {
}
}

function _addQueue(cb:() => boolean) {
itemQueue.push(cb);

if (!intervalHandle) {
intervalHandle = setInterval((() => {
function _startTimer() {
if (!queueTimer) {
queueTimer = setTimeout((() => {
queueTimer = null;
let allItems = itemQueue.slice(0);
let doFlush = false;
itemQueue = [];
Expand All @@ -80,9 +79,8 @@ export class PageViewManager {
}
});

if (itemQueue.length === 0) {
clearInterval(intervalHandle);
intervalHandle = null;
if (itemQueue.length > 0) {
_startTimer();
}

if (doFlush) {
Expand All @@ -93,6 +91,12 @@ export class PageViewManager {
}
}

function _addQueue(cb:() => boolean) {
itemQueue.push(cb);

_startTimer();
}

_self.trackPageView = (pageView: IPageViewTelemetry, customProperties?: { [key: string]: any }) => {
let name = pageView.name;
if (isNullOrUndefined(name) || typeof name !== "string") {
Expand Down Expand Up @@ -227,9 +231,9 @@ export class PageViewManager {
};

_self.teardown = (unloadCtx?: IProcessTelemetryUnloadContext, unloadState?: ITelemetryUnloadState) => {
if (intervalHandle) {
clearInterval(intervalHandle);
intervalHandle = null;
if (queueTimer) {
clearTimeout(queueTimer);
queueTimer = null;

let allItems = itemQueue.slice(0);
let doFlush = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { Assert, AITestClass } from "@microsoft/ai-test-framework";
import * as pako from "pako";

export class AppInsightsCoreSizeCheck extends AITestClass {
private readonly MAX_RAW_SIZE = 45;
private readonly MAX_BUNDLE_SIZE = 45;
private readonly MAX_RAW_SIZE = 46;
private readonly MAX_BUNDLE_SIZE = 46;
private readonly MAX_RAW_DEFLATE_SIZE = 19;
private readonly MAX_BUNDLE_DEFLATE_SIZE = 19;
private readonly rawFilePath = "../dist/applicationinsights-core-js.min.js";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export interface IConfiguration {
connectionString?: string;

/**
* Polling interval (in ms) for internal logging queue
* Set the timer interval (in ms) for internal logging queue, this is the
* amount of time to wait after logger.queue messages are detected to be sent.
* Note: since 2.8.13 and 3.0.1 the diagnostic logger timer is a normal timeout timer
* and not an interval timer. So this now represents the timer "delay" and not
* the frequency at which the events are sent.
*/
diagnosticLogInterval?: number;

Expand Down
67 changes: 45 additions & 22 deletions shared/AppInsightsCore/src/JavaScriptSDK/BaseCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export class BaseCore implements IAppInsightsCore {
* Internal log poller
*/
let _internalLogPoller: number = 0;
let _forceStopInternalLogPoller = false;

dynamicProto(BaseCore, this, (_self) => {

Expand Down Expand Up @@ -331,30 +332,40 @@ export class BaseCore implements IAppInsightsCore {
}
};

/**
* Periodically check logger.queue for log messages to be flushed
*/
_self.pollInternalLogs = (eventName?: string): number => {
_internalLogsEventName = eventName || null;

let interval: number = getCfgValue(_config.diagnosticLogInterval);
if (!interval || !(interval > 0)) {
interval = 10000;
}
_forceStopInternalLogPoller = false;
if(_internalLogPoller) {
clearInterval(_internalLogPoller);
_internalLogPoller = null;
}

return _startInternalLogTimer(true);
}

function _startInternalLogTimer(alwaysStart?: boolean) {
if (!_internalLogPoller && !_forceStopInternalLogPoller) {
let shouldStart = alwaysStart || (_self.logger && _self.logger.queue.length > 0);
if (shouldStart) {
let interval: number = getCfgValue(_config.diagnosticLogInterval);
if (!interval || !(interval > 0)) {
interval = 10000;
}

// Keeping as an interval timer for backward compatibility as it returns the result
_internalLogPoller = setInterval(() => {
clearInterval(_internalLogPoller);
_internalLogPoller = 0;
_flushInternalLogs();
}, interval) as any;
}
}
_internalLogPoller = setInterval(() => {
_flushInternalLogs();
}, interval) as any;

return _internalLogPoller;
}

/**
* Stop polling log messages from logger.queue
*/
_self.stopPollingInternalLogs = (): void => {
_forceStopInternalLogPoller = true;
if(_internalLogPoller) {
clearInterval(_internalLogPoller);
_internalLogPoller = 0;
Expand Down Expand Up @@ -403,6 +414,8 @@ export class BaseCore implements IAppInsightsCore {
processUnloadCtx.processNext(unloadState);
}

_flushInternalLogs();

if (!_flushChannels(isAsync, _doUnload, SendRequestReason.SdkUnload, cbTimeout)) {
_doUnload(false);
}
Expand Down Expand Up @@ -510,7 +523,10 @@ export class BaseCore implements IAppInsightsCore {
}

function _createTelCtx(): IProcessTelemetryContext {
return createProcessTelemetryContext(_getPluginChain(), _config, _self);
let theCtx = createProcessTelemetryContext(_getPluginChain(), _config, _self);
theCtx.onComplete(_startInternalLogTimer);

return theCtx;
}

// Initialize or Re-initialize the plugins
Expand Down Expand Up @@ -556,7 +572,8 @@ export class BaseCore implements IAppInsightsCore {
// Initialize the controls
_channelControl.initialize(_config, _self, allExtensions);

initializePlugins(_createTelCtx(), allExtensions);
let initCtx = _createTelCtx();
initializePlugins(initCtx, allExtensions);

// Now reset the extensions to just those being managed by Basecore
_self._extensions = objFreeze(sortPlugins(_coreExtensions || [])).slice();
Expand Down Expand Up @@ -674,6 +691,7 @@ export class BaseCore implements IAppInsightsCore {
}

removeComplete && removeComplete(removed);
_startInternalLogTimer();
});

unloadCtx.processNext(unloadState);
Expand All @@ -683,8 +701,10 @@ export class BaseCore implements IAppInsightsCore {
}

function _flushInternalLogs() {
let queue: _InternalLogMessage[] = _self.logger ? _self.logger.queue : [];
if (queue) {
if (_self.logger && _self.logger.queue) {
let queue: _InternalLogMessage[] = _self.logger.queue.slice(0);
_self.logger.queue.length = 0;

arrForEach(queue, (logMessage: _InternalLogMessage) => {
const item: ITelemetryItem = {
name: _internalLogsEventName ? _internalLogsEventName : "InternalMessageId: " + logMessage.messageId,
Expand All @@ -695,8 +715,6 @@ export class BaseCore implements IAppInsightsCore {
};
_self.track(item);
});

queue.length = 0;
}
}

Expand Down Expand Up @@ -745,6 +763,7 @@ export class BaseCore implements IAppInsightsCore {

function _doUpdate(updateState: ITelemetryUpdateState): void {
let updateCtx = createProcessTelemetryUpdateContext(_getPluginChain(), _self);
updateCtx.onComplete(_startInternalLogTimer);

if (!_self._updateHook || _self._updateHook(updateCtx, updateState) !== true) {
updateCtx.processNext(updateState);
Expand All @@ -756,6 +775,7 @@ export class BaseCore implements IAppInsightsCore {
if (logger) {
// there should always be a logger
_throwInternal(logger, eLoggingSeverity.WARNING, _eInternalMessageId.PluginException, message);
_startInternalLogTimer();
} else {
throwError(message);
}
Expand Down Expand Up @@ -835,15 +855,18 @@ export class BaseCore implements IAppInsightsCore {
}

/**
* Periodically check logger.queue for
* Enable the timer that checks the logger.queue for log messages to be flushed.
* Note: Since 3.0.1 and 2.8.13 this is no longer an interval timer but is a normal
* timer that is only started when this function is called and then subsequently
* only _if_ there are any logger.queue messages to be sent.
*/
public pollInternalLogs(eventName?: string): number {
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
return 0;
}

/**
* Periodically check logger.queue for
* Stop the timer that log messages from logger.queue when available
*/
public stopPollingInternalLogs(): void {
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging
Expand Down