Skip to content

Commit

Permalink
Add Dialog / PageView telemetry (#2145)
Browse files Browse the repository at this point in the history
* Update app insights package version

* Add PageView logging

* move TelemetryView helper to botTelemetryClient.ts

* remove telemetry Extensions class, harden helper method, add tests

Co-authored-by: Steven Gum <14935595+stevengum@users.noreply.github.com>
  • Loading branch information
garypretty and stevengum committed May 6, 2020
1 parent c3f7e33 commit b64b61d
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 8 deletions.
2 changes: 1 addition & 1 deletion libraries/botbuilder-applicationinsights/package.json
Expand Up @@ -21,7 +21,7 @@
"main": "./lib/index.js",
"typings": "./lib/index.d.ts",
"dependencies": {
"applicationinsights": "1.2.0",
"applicationinsights": "1.7.5",
"botbuilder-core": "4.1.6",
"cls-hooked": "^4.2.2"
},
Expand Down
Expand Up @@ -6,7 +6,7 @@
* Licensed under the MIT License.
*/
import * as appInsights from 'applicationinsights';
import { Activity, BotTelemetryClient, TelemetryDependency, TelemetryEvent, TelemetryException, TelemetryTrace } from 'botbuilder-core';
import { Activity, BotTelemetryClient, BotPageViewTelemetryClient, TelemetryDependency, TelemetryEvent, TelemetryException, TelemetryTrace, TelemetryPageView } from 'botbuilder-core';
import * as cls from 'cls-hooked';
import * as crypto from 'crypto';
const ns: any = cls.createNamespace('my.request');
Expand Down Expand Up @@ -61,7 +61,7 @@ export const ApplicationInsightsWebserverMiddleware: any = (req: any, res: any,
* myDialog.telemetryClient = appInsightsClient;
* ```
*/
export class ApplicationInsightsTelemetryClient implements BotTelemetryClient {
export class ApplicationInsightsTelemetryClient implements BotTelemetryClient, BotPageViewTelemetryClient {

private client: appInsights.TelemetryClient;
private config: appInsights.Configuration;
Expand Down Expand Up @@ -117,6 +117,10 @@ export class ApplicationInsightsTelemetryClient implements BotTelemetryClient {
this.defaultClient.trackTrace(telemetry as appInsights.Contracts.TraceTelemetry);
}

public trackPageView(telemetry: TelemetryPageView): void {
this.defaultClient.trackPageView(telemetry as appInsights.Contracts.PageViewTelemetry);
}

public flush(): void {
this.defaultClient.flush();
}
Expand Down
42 changes: 40 additions & 2 deletions libraries/botbuilder-core/src/botTelemetryClient.ts
Expand Up @@ -27,6 +27,10 @@ export interface BotTelemetryClient {
flush();
}

export interface BotPageViewTelemetryClient {
trackPageView(telemetry: TelemetryPageView);
}

export interface TelemetryDependency {
dependencyTypeName: string;
target: string;
Expand Down Expand Up @@ -57,11 +61,21 @@ export interface TelemetryTrace {
severityLevel?: Severity;
}

export class NullTelemetryClient implements BotTelemetryClient {
export interface TelemetryPageView {
name: string;
properties?: {[key: string]: string};
metrics?: {[key: string]: number };
}

export class NullTelemetryClient implements BotTelemetryClient, BotPageViewTelemetryClient {

constructor(settings?: any) {
// noop
}

trackPageView(telemetry: TelemetryPageView) {
// noop
}

trackDependency(telemetry: TelemetryDependency) {
// noop
Expand All @@ -74,12 +88,36 @@ export class NullTelemetryClient implements BotTelemetryClient {
trackException(telemetry: TelemetryException) {
// noop
}

trackTrace(telemetry: TelemetryTrace) {
// noop
}

flush() {
// noop
}
}

export function telemetryTrackDialogView(telemetryClient: BotTelemetryClient, dialogName: string, properties?: {[key: string]: any}, metrics?: {[key: string]: number }): void {
if (!clientSupportsTrackDialogView(telemetryClient)) {
throw new TypeError('"telemetryClient" parameter does not have methods trackPageView() or trackTrace()');
}
if (instanceOfBotPageViewTelemetryClient(telemetryClient)) {
telemetryClient.trackPageView({ name: dialogName, properties: properties, metrics: metrics });
}
else {
telemetryClient.trackTrace({ message: 'Dialog View: ' + dialogName, severityLevel: Severity.Information } );
}
}

function instanceOfBotPageViewTelemetryClient(object: any): object is BotPageViewTelemetryClient {
return 'trackPageView' in object;
}

}
function clientSupportsTrackDialogView(client: any): boolean {
if (!client) { return false; }
if (typeof client.trackPageView !== 'function' && typeof client.trackTrace !== 'function') {
return false;
}
return true;
}
46 changes: 46 additions & 0 deletions libraries/botbuilder-core/tests/botTelemetryClient.test.js
@@ -0,0 +1,46 @@
const { ok, strictEqual } = require('assert');
const { Severity, telemetryTrackDialogView } = require('../');

describe('BotTelemetryClient', function() {
this.timeout(3000);

describe('"telemetryTrackDialogView" helper', () => {
it('should call client.trackPageView if it exists', () => {
const testClient = {
trackPageView({ name, properties, metrics }) {
ok(name);
ok(properties);
ok(metrics);
}
};
const testProps = { description: 'value' };
const testMetrics = { duration: 1 };
telemetryTrackDialogView(testClient, 'dialogName', testProps, testMetrics);
});

it('should call client.trackTrace if trackPageView is not supported', () => {
const testClient = {
trackTrace({ message, severityLevel }) {
ok(message);
strictEqual(severityLevel, Severity.Information);
}
};
telemetryTrackDialogView(testClient, 'dialogName');
});

it('should throw TypeError if trackTrace and trackPageView do not exist', () => {
try {
telemetryTrackDialogView(undefined, 'dialogName');
} catch (err) {
strictEqual(err.message, '"telemetryClient" parameter does not have methods trackPageView() or trackTrace()');
}

try {
telemetryTrackDialogView({}, 'dialogName');
} catch (err) {
strictEqual(err.message, '"telemetryClient" parameter does not have methods trackPageView() or trackTrace()');
}

});
});
});
4 changes: 3 additions & 1 deletion libraries/botbuilder-dialogs/src/componentDialog.ts
Expand Up @@ -5,7 +5,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { TurnContext, BotTelemetryClient, NullTelemetryClient } from 'botbuilder-core';
import { BotTelemetryClient, NullTelemetryClient, telemetryTrackDialogView, TurnContext } from 'botbuilder-core';
import { Dialog, DialogInstance, DialogReason, DialogTurnResult, DialogTurnStatus } from './dialog';
import { DialogContext } from './dialogContext';
import { DialogContainer } from './dialogContainer';
Expand Down Expand Up @@ -81,6 +81,8 @@ export class ComponentDialog<O extends object = {}> extends DialogContainer<O> {
public async beginDialog(outerDC: DialogContext, options?: O): Promise<DialogTurnResult> {
await this.checkForVersionChange(outerDC);

telemetryTrackDialogView(this.telemetryClient, this.id);

// Start the inner dialog.
const innerDC: DialogContext = this.createChildContext(outerDC)
const turnResult: DialogTurnResult<any> = await this.onBeginDialog(innerDC, options);
Expand Down
6 changes: 4 additions & 2 deletions libraries/botbuilder-dialogs/src/waterfallDialog.ts
Expand Up @@ -5,8 +5,8 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { ActivityTypes } from 'botbuilder-core';
import { TurnContext } from 'botbuilder-core';
import { ActivityTypes, Severity } from 'botbuilder-core';
import { TurnContext, telemetryTrackDialogView } from 'botbuilder-core';
import { DialogInstance } from './dialog';
import { Dialog, DialogReason, DialogTurnResult } from './dialog';
import { DialogContext } from './dialogContext';
Expand Down Expand Up @@ -151,6 +151,8 @@ export class WaterfallDialog<O extends object = {}> extends Dialog<O> {
'InstanceId': state.values['instanceId']
}});

telemetryTrackDialogView(this.telemetryClient, this.id);

// Run the first step
return await this.runStep(dc, 0, DialogReason.beginCalled);
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -26,6 +26,7 @@
"@types/lodash": "^4.14.134",
"@typescript-eslint/eslint-plugin": "^1.10.2",
"@typescript-eslint/parser": "^1.10.2",
"applicationinsights": "^1.7.5",
"coveralls": "^3.0.4",
"eslint": "^5.16.0",
"eslint-plugin-only-warn": "^1.0.1",
Expand Down

0 comments on commit b64b61d

Please sign in to comment.