diff --git a/README.md b/README.md
index ddbfb8ac..4a1a8467 100644
--- a/README.md
+++ b/README.md
@@ -274,6 +274,9 @@ Most configuration fields are named such that they can be defaulted to falsey. A
| ajaxPerfLookupDelay | 25 | Defaults to 25ms. The amount of time to wait before re-attempting to find the windows.performance timings for an ajax request, time is in milliseconds and is passed directly to setTimeout().
| distributedTracingMode | `DistributedTracingModes.AI` | Sets the distributed tracing mode. If AI_AND_W3C mode or W3C mode is set, W3C trace context headers (traceparent/tracestate) will be generated and included in all outgoing requests. AI_AND_W3C is provided for back-compatibility with any legacy Application Insights instrumented services.
| enableUnhandledPromiseRejectionTracking | false | If true, unhandled promise rejections will be autocollected and reported as a javascript error. When disableExceptionTracking is true (dont track exceptions) the config value will be ignored and unhandled promise rejections will not be reported.
+| enablePerfMgr | false | [Optional] When enabled (true) this will create local perfEvents for code that has been instrumented to emit perfEvents (via the doPerf() helper). This can be used to identify performance issues within the SDK based on your usage or optionally within your own instrumented code. [More details are available by the basic documentation](./docs/PerformanceMonitoring.md). Since v2.5.7
+| perfEvtsSendAll | false | [Optional] When _enablePerfMgr_ is enabled and the [IPerfManager](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IPerfManager.ts) fires a [INotificationManager](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/INotificationManager.ts).perfEvent() this flag determines whether an event is fired (and sent to all listeners) for all events (true) or only for 'parent' events (false <default>).
A parent [IPerfEvent](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IPerfEvent.ts) is an event where no other IPerfEvent is still running at the point of this event being created and it's _parent_ property is not null or undefined. Since v2.5.7
+
## Single Page Applications
By default, this SDK will **not** handle state based route changing that occurs in single page applications. To enable automatic route change tracking for your single page application, you can add `enableAutoRouteTracking: true` to your setup configuration.
@@ -402,7 +405,7 @@ ITelemetryPlugin has a simpler base type IPlugin that you can instantiate for in
## Performance
-At just ~28 KB gzipped, and taking only ~15 ms to initialize, Application Insights JS adds a negligible amount of loadtime to your website. By using the snippet, minimal components of the library are quickly loaded. In the meantime, the full script is downloaded in the background.
+Application Insights JS adds a negligible amount of load time to your website. By using the snippet, minimal components of the library are quickly loaded. In the meantime, the full script is downloaded in the background.
While the script downloads from the CDN, all tracking of your page is queued. Once the downloaded script finishes asynchronously initializing, all events that were queued are tracked. As a result, you will not lose any telemetry during the entire life cycle of your page. This setup process provides your page with a seamless analytics system, invisible to your users.
@@ -410,7 +413,7 @@ While the script downloads from the CDN, all tracking of your page is queued. On
>
> - ![current npm version](https://badge.fury.io/js/%40microsoft%2Fapplicationinsights-web.svg)
> - ![gzip compressed size](https://img.badgesize.io/https://js.monitor.azure.com/scripts/b/ai.2.min.js.svg?compression=gzip)
-> - **15 ms** overall initialization time
+> - **~15 ms** overall initialization time
> - **Zero** tracking missed during life cycle of page
## Browser Support
diff --git a/RELEASES.md b/RELEASES.md
index 06050dd5..89f0aeb6 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -5,7 +5,8 @@
### Changelog
- #1335 Add Performance / Testing support
- - Added IPerfManager and IPerfEvent interfaces to allow performance review / monitoring of the internal operations
+ - Added IPerfManager and IPerfEvent interfaces to allow performance review / monitoring of the internal operations
+ - [Performance Manager Documentation](./docs/PerformanceMonitoring.md)
- #1334 [BUG] Getting XMLHttpRequest and XDomainRequest is not defined errors for gatsby environment
- #1333 [BUG] DebugPlugin various updates
- #1331 AppInsightsCore: Enable setting NotificationManager during initialization
@@ -26,12 +27,14 @@
- Update Core dependency to ^2.5.7 Core changes
- #1335 Add Performance / Testing support
- Added IPerfManager and IPerfEvent interfaces to allow performance review / monitoring of the internal operations
+ - [Performance Manager Documentation](./docs/PerformanceMonitoring.md)
### Updated React Native plugin to v2.2.6
- Update Core dependency to ^2.5.7 Core changes
- #1335 Add Performance / Testing support
- Added IPerfManager and IPerfEvent interfaces to allow performance review / monitoring of the internal operations
+ - [Performance Manager Documentation](./docs/PerformanceMonitoring.md)
- #1324 [BUG] Type 'ReactNativePlugin' is not assignable to type 'ITelemetryPlugin'
- Refactored the Plugin to extend BaseTelemetryPlugin (part of the #1076 work)
- #1076 Refactor code to provide better tree shaking and minification of generated code
diff --git a/docs/PerformanceMonitoring.md b/docs/PerformanceMonitoring.md
new file mode 100644
index 00000000..fa97aca4
--- /dev/null
+++ b/docs/PerformanceMonitoring.md
@@ -0,0 +1,98 @@
+# Performance Monitoring (since v2.5.7)
+
+The SDK now provides support for local client side performance monitoring and testing, this support does not send any telemetry or events to Azure Monitor as it has been designed to help developers validate and measure the performance of the SDK and any optional user instrumented code.
+
+It can be enabled via configuration (_enablePerfMgr_) during initialization or by setting the performance manager directly on the Application Insights instance (_setPerfMgr()_).
+
+The SDK comes with a default implementation of the performance manager which will fire the new [_perfEvent_ on the INotificationManager](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/INotificationManager.ts#L51), so you can receive a notification of these events by adding a INotificationListener which contains a [_perfEvent_](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/INotificationListener.ts#L38) implementation.
+
+The easiest way to view and monitor these events in your running application/website would be to use the new [DebugPlugin extension](https://github.com/microsoft/ApplicationInsights-JS/blob/master/extensions/applicationinsights-debugplugin-js/README.md), which now listens and displays to the INotificationManager events.
+
+The default INotificationManager implementation will (by default) only fire a _perfEvent_ for top level events, which are defined as events that have not occurred within the same execution cycle of a previous (incomplete) perf event. This behaviour can be changed to fire a _perfEvent_ for every instrumented section of code via the _perfEvtsSendAll_ configuration setting. Where the tracking of the current execution cycle of a performance event is automatically handled by the provided doPerf() helper.
+
+Example of the IPerfEvents captured by the default IPerfManager using the [DebugPlugin extension](https://github.com/microsoft/ApplicationInsights-JS/blob/master/extensions/applicationinsights-debugplugin-js/README.md) to visualize the captured events.
+![DebugPlugin Example](./media/DebugPlugin-PerfEvent1.png)
+
+## The interfaces
+
+The SDK avoids (as much as possible) from directly using hard coded implementations and only uses the following interfaces as part of instrumenting the code for performance monitoring. This allows you to provide your own implementation to support your requirements at runtime and testing.
+
+The only directly named class references are in the ApplicationInsight Core instances where they will create a [PerfManager](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK/PerfManager.ts) instances when the _enablePerfMgr_ configuration is enabled. If you want to use your own performance implementation then do not enable the _enablePerfMgr_ configuration setting, and just call the _setPerfMgr()_ with your IPerfManager after the ApplicationInsights has been created.
+
+### [IPerfManager](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IPerfManager.ts)
+
+#### Provides the basic interface for creating, monitoring and firing performance events
+
+This interface is used by the system to start "create()" and complete "fire()" performance events, the default provided performance manager [PerfManager](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK/PerfManager.ts) provides a simple implementation that will create a new [IPerfEvent](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IPerfEvent.ts) instance for every call to it's create() function and will complete and fire a INotificationManager.perfEvent in response to calling it's fire() function.
+
+The basic usage is that you call "create()" at the beginning of the segment of code that you want to measure and when the code is complete just call the "fire()" method with the IPerfEvent object returned from the create(). By following this pattern the implementation of the IPerfManager can control the exact implementation of IPerfEvent instance that is used for tracking the performance.
+
+#### Methods of the IPerfManager
+
+ * create(src: string, payloadDetails?: () => any, isAsync?: boolean): IPerfEvent - [Required] If the manager wants to instrument the named (_src_) code then it should return an IPerfEvent instance based on the _src; _payloadDetails_ and _isAsync_ arguments. The implementation may return null or undefined if it does not want to monitor this source (named) code.
+ * src - [string] The source / name to be used for the performance event. May be used to determine whether the manager wants to create a IPerfEvent for the code.
+ * payloadDetails - [() => any] This is an optional callback function which is used to assign the _payload_ value of the IPerfEvent, to limit the performance impacts the implementation should only call this callback if it is returning an IPerfEvent AND it needs the value.
+ * isAsync - [Boolean] An optional flag identifying whether the code is being executed as part of a synchronous / asynchronous request, used by the default implementation to determine how it should fire the INotification.perfEvent. Defaults to true when not supplied.
+ * fire(perfEvent:IPerfEvent): void - [Required] The performance manager should mark the passed _perfEvent_ as complete and fire the performance event.
+ * perfEvent - [IPerfEvent] This will be the value returned by the create() function.
+* setCtx(key: string, value: any): void - [Required] Allows users to set a named context value, setting the same named value will overwrite any previous value, it should also allow setting the value to null or undefined. This is used via the doPerf() helper to track the currently executing IPerfEvent instance for identifying the parent / children for each event.
+* getCtx(key: string): any - [Required] Return any previously named value that was set.
+
+### [IPerfEvent](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IPerfEvent.ts)
+
+#### The basic interface used to generate performance event metrics for instrumented code
+
+This is a generic interface for holding the details about the instrumented chunk of code, the SDK does not directly create instances of this interface but rather uses the instances returned via the IPerfManager.create().
+
+#### The fields of the IPerfEvent
+
+ * name - [string] The name of the performance event. Examples "AppInsightsCore:track" "AppInsightsPropertiesPlugin:processTelemetry
+ * start - [number] The start time of the event, the actual value is dependent on the IPerfManager implementation, it could be in relative, absolute in milliseconds or nanoseconds. The provided default IPerfManager currently uses the absolute time in milliseconds (via Date.now()).
+ * payload - [object] This is a copy / reference to the value provided during the call to the IPerfManager.create().
+ * isAsync - [boolean] Identifies if the perfEvent is occurring via a synchronous or asynchronous execution path, primarily used to determine how to fire the _INotificationManager.perfEvent()_.
+ * time - [number] Identifies the total amount of time (since the start to end) that this perfEvent represents. This value may be undefined until the event has completed (depending on the IPerfManager implementation).
+ * exTime - [number] Identifies the exclusive amount of time (since the start to end) that this perfEvent represents. This effectively is the "time" less the sum of the "time" of all children.
+ * parent - [IPerfEvent] An optional reference to the parent event that was active when this event was created.
+ * childEvts - [Array<IPerfEvent>] An optional array of all child events started before this event completed.
+
+#### Methods of the IPerfEvent
+
+ * getCtx?: (key: string) => any - [Optional] Returns any previously set context for the event, can be used by the instrumented code to set additional context to be reported or tracked for the performance event. The doPerf() Helper uses this function to get the child event value array for appending.
+ * setCtx?: (key: string, value: any) => void - [Optional] Allows the instrumented code to set additional context to be reported or tracked for the performance event. The doPerf() Helper uses this function to set the parent, child event values and if an exception occurred during execution.
+ * complete: () => void - [Required] - When called, the tracked event should be marked as complete. The default provided IPerfManager calls this method during it's call to fire() to mark the event as complete.
+
+## Provided Implementation helper
+
+### [doPerf()](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK/CoreUtils.ts#L498)
+
+#### Helper method that is used by the SDK to wrap the code to be measured
+
+This is the primary helper used by the SDK to instrument a block of code that we have identified as a critical block that should be monitored / tested. We have exported this helper to allow you to instrument your own code as part of the normal execution cycle.
+
+It is designed as a wrapper implementation where the 3rd argument _func_ is the code that is being monitored. The implementation handles cases where a performance manager is not enabled or available, so it is safe for you to include this into production code.
+
+##### Signature
+
+The helper uses callback functions for constructing the source (_name_ of the event) and details (_payload_ of the event) to avoid any expensive string or object construction when performance monitoring is not enabled.
+
+doPerf(mgrSource: IPerfManagerProvider | IPerfManager, getSource: () => string, func: (perfEvt?: IPerfEvent) => T, details?: () => any, isAsync?: boolean) => T
+
+ * mgrSource - [[IPerfManager|IPerfManagerProvider](https://github.com/microsoft/ApplicationInsights-JS/blob/master/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IPerfManager.ts)] This can be either the IPerfManager or a provider that returns the IPerfManager (via the _getPerfMgr()_) instance. All Application Insights core instances are IPerfManagerProvider instances, so you can just the current Application Insights instance. The value may also be null or undefined, which means no perf event will be tracked.
+ * getSource - [() => string] Callback function to return the _name_ for the perf event, this is only called when the performance monitoring is enabled and the value is passed to the IPerfManager.create() function.
+ * func - [() => T] This is the actual code whose performance will be monitored / tracked, the return value of this function is the value returned by the doPerf() helper.
+ * details - [() => any] This is an optional callback function which is used to assign the _payload_ value of the IPerfEvent, the callback function is passed to the IPerfManager.create() method and will only be called if the performance mananger creates an IPerfEvent for the request, to limit the performance impact that monitoring can introduce.
+ * isAsync - [Boolean] An optional flag identifying whether the code is being executed as part of a synchronous / asynchronous request. Defaults to true when not supplied.
+
+Example usage
+```typescript
+
+public myFunction(someArgument: any) {
+ return doPerf(appInsights, () => rootName + ":myFunction", () => {
+ // This is the code that will be instrumented
+
+ // As a wrapper the doPerf supports returning the value returned by the func argument
+ return true;
+ }, () => ({ details: someArgument, retry: 1 }));
+}
+
+```
diff --git a/docs/media/DebugPlugin-PerfEvent1.png b/docs/media/DebugPlugin-PerfEvent1.png
new file mode 100644
index 00000000..b50fd924
Binary files /dev/null and b/docs/media/DebugPlugin-PerfEvent1.png differ