-
Notifications
You must be signed in to change notification settings - Fork 237
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
Beta Part 1: Part of Mega Dynamic Load/Unload support #1766
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,8 +10,11 @@ import { IDiagnosticLogger } from "./IDiagnosticLogger"; | |
import { IProcessTelemetryContext } from "./IProcessTelemetryContext"; | ||
import { IPerfManagerProvider } from "./IPerfManager"; | ||
import { ICookieMgr } from "./ICookieMgr"; | ||
import { ITelemetryInitializerHandler, TelemetryInitializerFunction } from "./ITelemetryInitializers"; | ||
|
||
"use strict"; | ||
export interface ILoadedPlugin<T extends IPlugin> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While this seems like overkill, it will have some additional functions added in future "Parts" of this bigger change added. |
||
plugin: T; | ||
} | ||
|
||
export interface IAppInsightsCore extends IPerfManagerProvider { | ||
|
||
|
@@ -72,6 +75,13 @@ export interface IAppInsightsCore extends IPerfManagerProvider { | |
*/ | ||
removeNotificationListener?(listener: INotificationListener): void; | ||
|
||
/** | ||
* Add a telemetry processor to decorate or drop telemetry events. | ||
* @param telemetryInitializer - The Telemetry Initializer function | ||
* @returns - A ITelemetryInitializerHandler to enable the initializer to be removed | ||
*/ | ||
addTelemetryInitializer(telemetryInitializer: TelemetryInitializerFunction): ITelemetryInitializerHandler | void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is moving the telemetry initializer to the Core so all Sku's will have the telemetry initializer functionality not just the Web Analytics. |
||
|
||
pollInternalLogs?(eventName?: string): number; | ||
|
||
stopPollingInternalLogs?(): void; | ||
|
@@ -80,4 +90,10 @@ export interface IAppInsightsCore extends IPerfManagerProvider { | |
* Return a new instance of the IProcessTelemetryContext for processing events | ||
*/ | ||
getProcessTelContext() : IProcessTelemetryContext; | ||
|
||
/** | ||
* Find and return the (first) plugin with the specified identifier if present | ||
* @param pluginIdentifier | ||
*/ | ||
getPlugin<T extends IPlugin = IPlugin>(pluginIdentifier: string): ILoadedPlugin<T>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Creating a unified "lookup" for a plugin, this happens throughout the code by lookup at the passed config. But as we are going to be updating the loaded extensions that's going to get problematic in later PR's |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,9 +6,15 @@ import { IAppInsightsCore } from "./IAppInsightsCore"; | |
import { IDiagnosticLogger } from "./IDiagnosticLogger"; | ||
import { IConfiguration } from "./IConfiguration"; | ||
import { ITelemetryItem } from "./ITelemetryItem"; | ||
import { IPlugin } from "./ITelemetryPlugin"; | ||
import { IPlugin, ITelemetryPlugin } from "./ITelemetryPlugin"; | ||
import { ITelemetryPluginChain } from "./ITelemetryPluginChain"; | ||
|
||
export const enum GetExtCfgMergeType { | ||
None = 0, | ||
MergeDefaultOnly = 1, | ||
MergeDefaultFromRootOrDefault = 2, | ||
} | ||
|
||
/** | ||
* The current context for the current call to processTelemetry(), used to support sharing the same plugin instance | ||
* between multiple AppInsights instances | ||
|
@@ -27,12 +33,12 @@ export interface IProcessTelemetryContext { | |
/** | ||
* Gets the current core config instance | ||
*/ | ||
getCfg: ()=> IConfiguration; | ||
getCfg: () => IConfiguration; | ||
|
||
/** | ||
* Gets the named extension config | ||
*/ | ||
getExtCfg: <T>(identifier: string, defaultValue?:T|any) => T; | ||
getExtCfg: <T>(identifier: string, defaultValue?: T | any, mergeDefault?: GetExtCfgMergeType) => T; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moving some code that was repeated across the code bases into the central location. |
||
|
||
/** | ||
* Gets the named config from either the named identifier extension or core config if neither exist then the | ||
|
@@ -41,7 +47,7 @@ export interface IProcessTelemetryContext { | |
* @param field The config field name | ||
* @param defaultValue The default value to return if no defined config exists | ||
*/ | ||
getConfig: (identifier: string, field: string, defaultValue?: number | string | boolean) => number | string | boolean; | ||
getConfig: (identifier: string, field: string, defaultValue?: number | string | boolean | string[] | RegExp[] | Function) => number | string | boolean | string[] | RegExp[] | Function; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding some more of the actual types so that users don't need to say "any" or "unknown" |
||
|
||
/** | ||
* Helper to allow plugins to check and possibly shortcut executing code only | ||
|
@@ -57,14 +63,21 @@ export interface IProcessTelemetryContext { | |
/** | ||
* Helper to set the next plugin proxy | ||
*/ | ||
setNext: (nextCtx:ITelemetryPluginChain) => void; | ||
setNext: (nextCtx: ITelemetryPluginChain) => void; | ||
|
||
/** | ||
* Call back for telemetry processing before it it is sent | ||
* @param env - This is the current event being reported | ||
*/ | ||
processNext: (env: ITelemetryItem) => void; | ||
|
||
/** | ||
* Synchronously iterate over the context chain running the callback for each plugin, once | ||
* every plugin has been executed via the callback, any associated onComplete will be called. | ||
* @param callback - The function call for each plugin in the context chain | ||
*/ | ||
iterate: <T extends ITelemetryPlugin = ITelemetryPlugin>(callback: (plugin: T) => void) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This iterates over all of the "loaded" plugins, calling the callback function for each plugin |
||
|
||
/** | ||
* Create a new context using the core and config from the current instance | ||
* @param plugins - The execution order to process the plugins, if null or not supplied | ||
|
@@ -73,4 +86,9 @@ export interface IProcessTelemetryContext { | |
* order then the next plugin will be NOT set. | ||
*/ | ||
createNew: (plugins?:IPlugin[]|ITelemetryPluginChain, startAt?:IPlugin) => IProcessTelemetryContext; | ||
|
||
/** | ||
* Set the function to call when the current chain has executed all processNext or unloadNext items. | ||
*/ | ||
onComplete: (onComplete: () => void) => void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding a "callback" that will be called once all of the plugins have been processed with the current context. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { ITelemetryItem } from "./ITelemetryItem"; | ||
|
||
export declare type TelemetryInitializerFunction = <T extends ITelemetryItem>(item: T) => boolean | void; | ||
|
||
export interface ITelemetryInitializerHandler { | ||
remove(): void; | ||
} | ||
|
||
export interface ITelemetryInitializerContainer { | ||
/** | ||
* Add a telemetry processor to decorate or drop telemetry events. | ||
* @param telemetryInitializer - The Telemetry Initializer function | ||
* @returns - A ITelemetryInitializerHandler to enable the initializer to be removed | ||
*/ | ||
addTelemetryInitializer(telemetryInitializer: TelemetryInitializerFunction): ITelemetryInitializerHandler | void; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updating the signature to return a "handler" for any added initializer, this will be used to allow the caller to "remove" the added initializer, which is required for "unloading" the entire SDK. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,25 +5,20 @@ import { BaseCore } from "./BaseCore"; | |
import { IConfiguration } from "../JavaScriptSDK.Interfaces/IConfiguration"; | ||
import { IPlugin } from "../JavaScriptSDK.Interfaces/ITelemetryPlugin"; | ||
import { ITelemetryItem } from "../JavaScriptSDK.Interfaces/ITelemetryItem"; | ||
import { INotificationListener } from "../JavaScriptSDK.Interfaces/INotificationListener"; | ||
import { EventsDiscardedReason } from "../JavaScriptSDK.Enums/EventsDiscardedReason"; | ||
import { NotificationManager } from "./NotificationManager"; | ||
import { doPerf } from "./PerfManager"; | ||
import { INotificationManager } from "../JavaScriptSDK.Interfaces/INotificationManager"; | ||
import { IDiagnosticLogger } from "../JavaScriptSDK.Interfaces/IDiagnosticLogger"; | ||
import { _InternalLogMessage, DiagnosticLogger } from "./DiagnosticLogger"; | ||
import { DiagnosticLogger } from "./DiagnosticLogger"; | ||
import dynamicProto from "@microsoft/dynamicproto-js"; | ||
import { arrForEach, isNullOrUndefined, toISOString, throwError } from "./HelperFuncs"; | ||
import { isNullOrUndefined, throwError } from "./HelperFuncs"; | ||
|
||
"use strict"; | ||
|
||
export class AppInsightsCore extends BaseCore implements IAppInsightsCore { | ||
constructor() { | ||
super(); | ||
/** | ||
* Internal log poller | ||
*/ | ||
let _internalLogPoller: number = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moving to BaseCore. |
||
|
||
dynamicProto(AppInsightsCore, this, (_self, _base) => { | ||
|
||
|
@@ -46,67 +41,6 @@ export class AppInsightsCore extends BaseCore implements IAppInsightsCore { | |
}, () => ({ item: telemetryItem }), !((telemetryItem as any).sync)); | ||
}; | ||
|
||
/** | ||
* 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 {INotificationListener} listener - An INotificationListener object. | ||
*/ | ||
_self.addNotificationListener = (listener: INotificationListener): void => { | ||
let manager = _self.getNotifyMgr(); | ||
if (manager) { | ||
manager.addNotificationListener(listener); | ||
} | ||
}; | ||
|
||
/** | ||
* Removes all instances of the listener. | ||
* @param {INotificationListener} listener - INotificationListener to remove. | ||
*/ | ||
_self.removeNotificationListener = (listener: INotificationListener): void => { | ||
let manager = _self.getNotifyMgr(); | ||
if (manager) { | ||
manager.removeNotificationListener(listener); | ||
} | ||
} | ||
|
||
/** | ||
* Periodically check logger.queue for log messages to be flushed | ||
*/ | ||
_self.pollInternalLogs = (eventName?: string): number => { | ||
let interval = _self.config.diagnosticLogInterval; | ||
if (!interval || !(interval > 0)) { | ||
interval = 10000; | ||
} | ||
if(_internalLogPoller) { | ||
_self.stopPollingInternalLogs(); | ||
} | ||
_internalLogPoller = setInterval(() => { | ||
const queue: _InternalLogMessage[] = _self.logger ? _self.logger.queue : []; | ||
arrForEach(queue, (logMessage: _InternalLogMessage) => { | ||
const item: ITelemetryItem = { | ||
name: eventName ? eventName : "InternalMessageId: " + logMessage.messageId, | ||
iKey: _self.config.instrumentationKey, | ||
time: toISOString(new Date()), | ||
baseType: _InternalLogMessage.dataType, | ||
baseData: { message: logMessage.message } | ||
}; | ||
_self.track(item); | ||
}); | ||
queue.length = 0; | ||
}, interval) as any; | ||
return _internalLogPoller; | ||
} | ||
|
||
/** | ||
* Stop polling log messages from logger.queue | ||
*/ | ||
_self.stopPollingInternalLogs = (): void => { | ||
if(!_internalLogPoller) return; | ||
clearInterval(_internalLogPoller); | ||
_internalLogPoller = 0; | ||
} | ||
|
||
function _validateTelemetryItem(telemetryItem: ITelemetryItem) { | ||
if (isNullOrUndefined(telemetryItem.name)) { | ||
_notifyInvalidEvent(telemetryItem); | ||
|
@@ -130,37 +64,4 @@ export class AppInsightsCore extends BaseCore implements IAppInsightsCore { | |
public track(telemetryItem: ITelemetryItem) { | ||
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging | ||
} | ||
|
||
/** | ||
* 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 {INotificationListener} listener - An INotificationListener object. | ||
*/ | ||
public addNotificationListener(listener: INotificationListener): void { | ||
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging | ||
} | ||
|
||
/** | ||
* Removes all instances of the listener. | ||
* @param {INotificationListener} listener - INotificationListener to remove. | ||
*/ | ||
public removeNotificationListener(listener: INotificationListener): void { | ||
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging | ||
} | ||
|
||
/** | ||
* Periodically check logger.queue for | ||
*/ | ||
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 | ||
*/ | ||
public stopPollingInternalLogs(): void { | ||
// @DynamicProtoStub -- DO NOT add any code as this will be removed during packaging | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a functional change, to support "unloading" the complete SDK we want to make sure that when polling is stopped any queued messages are flushed.