Skip to content

Commit

Permalink
Added first pass of telemetry & instrumentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyanziano committed Jan 25, 2019
1 parent f6de7a1 commit 43ba5dc
Show file tree
Hide file tree
Showing 67 changed files with 2,568 additions and 576 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- [docs] Added changelog in PR [#1230](https://github.com/Microsoft/BotFramework-Emulator/pull/1230)
- [style] 💅 integrate prettier and eslint ([#1240](https://github.com/Microsoft/BotFramework-Emulator/pull/1240))
- [style] 💅 Integrated prettier and eslint in PR [#1240](https://github.com/Microsoft/BotFramework-Emulator/pull/1240)
- [feat] Added app-wide instrumentation in PR [#1251](https://github.com/Microsoft/BotFramework-Emulator/pull/1251)
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions packages/app/client/src/commands/botCommands.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,25 @@ describe('The bot commands', () => {
});

it('should make the appropriate calls to switch bots', () => {
const remoteCallArgs = [];
CommandServiceImpl.remoteCall = async (...args: any[]) => {
remoteCallArgs.push(args);
return true;
};
const spy = jest.spyOn(ActiveBotHelper, 'confirmAndSwitchBots');
const { handler } = registry.getCommand(
SharedConstants.Commands.Bot.Switch
);
handler({});
expect(spy).toHaveBeenCalledWith({});
expect(remoteCallArgs[0][0]).toBe(
SharedConstants.Commands.Telemetry.TrackEvent
);
expect(remoteCallArgs[0][1]).toBe('bot_open');
expect(remoteCallArgs[0][2]).toEqual({
method: 'bots_list',
numOfServices: undefined,
});
});

it('should make the appropriate calls to close a bot', () => {
Expand Down
13 changes: 11 additions & 2 deletions packages/app/client/src/commands/botCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,17 @@ export function registerCommands(commandRegistry: CommandRegistryImpl) {
// Switches the current active bot
commandRegistry.registerCommand(
Commands.Bot.Switch,
(bot: BotConfigWithPath | string) =>
ActiveBotHelper.confirmAndSwitchBots(bot)
(bot: BotConfigWithPath | string) => {
let numOfServices;
if (typeof bot !== 'string') {
numOfServices = bot.services && bot.services.length;
}
CommandServiceImpl.remoteCall(Commands.Telemetry.TrackEvent, 'bot_open', {
method: 'bots_list',
numOfServices,
}).catch(_e => void 0);
return ActiveBotHelper.confirmAndSwitchBots(bot);
}
);

// ---------------------------------------------------------------------------
Expand Down
9 changes: 8 additions & 1 deletion packages/app/client/src/commands/emulatorCommands.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ describe('The emulator commands', () => {
const remoteCallSpy = jest
.spyOn(CommandServiceImpl, 'remoteCall')
.mockResolvedValue('transcript.transcript');
const callSpy = jest.spyOn(CommandServiceImpl, 'call');
const callSpy = jest
.spyOn(CommandServiceImpl, 'call')
.mockResolvedValue(null);

await handler();

Expand All @@ -140,6 +142,11 @@ describe('The emulator commands', () => {
title: 'Open transcript file',
}
);
expect(remoteCallSpy).toHaveBeenCalledWith(
SharedConstants.Commands.Telemetry.TrackEvent,
'transcriptFile_open',
{ method: 'file_menu' }
);

expect(callSpy).toHaveBeenCalledWith(
'transcript:open',
Expand Down
15 changes: 14 additions & 1 deletion packages/app/client/src/commands/emulatorCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { newNotification, SharedConstants } from '@bfemulator/app-shared';
import {
Activity,
CommandRegistryImpl,
isLocalHostUrl,
uniqueId,
} from '@bfemulator/sdk-shared';
import { IEndpointService } from 'botframework-config/lib/schema';
Expand All @@ -49,7 +50,10 @@ import { CommandServiceImpl } from '../platform/commands/commandServiceImpl';

/** Registers emulator (actual conversation emulation logic) commands */
export function registerCommands(commandRegistry: CommandRegistryImpl) {
const { Emulator } = SharedConstants.Commands;
const {
Emulator,
Telemetry: { TrackEvent },
} = SharedConstants.Commands;

// ---------------------------------------------------------------------------
// Open a new emulator tabbed document
Expand Down Expand Up @@ -79,6 +83,12 @@ export function registerCommands(commandRegistry: CommandRegistryImpl) {
);
}

if (!isLocalHostUrl(endpoint.endpoint)) {
CommandServiceImpl.remoteCall(TrackEvent, 'livechat_openRemote').catch(
_e => void 0
);
}

store.dispatch(
EditorActions.open({
contentType: Constants.CONTENT_TYPE_LIVE_CHAT,
Expand Down Expand Up @@ -140,6 +150,9 @@ export function registerCommands(commandRegistry: CommandRegistryImpl) {
dialogOptions
);
await CommandServiceImpl.call(Emulator.OpenTranscript, filename);
CommandServiceImpl.remoteCall(TrackEvent, 'transcriptFile_open', {
method: 'file_menu',
}).catch(_e => void 0);
} catch (e) {
const errMsg = `Error while opening transcript file: ${e}`;
const notification = newNotification(errMsg);
Expand Down
8 changes: 8 additions & 0 deletions packages/app/client/src/commands/uiCommands.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ import {
OpenBotDialogContainer,
SecretPromptDialogContainer,
} from '../ui/dialogs';
import { CommandServiceImpl } from '../platform/commands/commandServiceImpl';

import { registerCommands } from './uiCommands';

jest.mock('../ui/dialogs', () => ({
AzureLoginPromptDialogContainer: class {},
AzureLoginSuccessDialogContainer: class {},
Expand Down Expand Up @@ -153,10 +155,16 @@ describe('the uiCommands', () => {
});

it('should set the proper href on the theme tag when the SwitchTheme command is dispatched', () => {
const remoteCallSpy = jest.spyOn(CommandServiceImpl, 'remoteCall');
const link = document.createElement('link');
link.id = 'themeVars';
document.querySelector('head').appendChild(link);
registry.getCommand(Commands.SwitchTheme).handler('light', './light.css');
expect(link.href).toBe('http://localhost/light.css');
expect(remoteCallSpy).toHaveBeenCalledWith(
SharedConstants.Commands.Telemetry.TrackEvent,
'app_chooseTheme',
{ themeName: 'light' }
);
});
});
6 changes: 5 additions & 1 deletion packages/app/client/src/commands/uiCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import { switchTheme } from '../data/action/themeActions';
import { showWelcomePage } from '../data/editorHelpers';
import { AzureAuthState } from '../data/reducer/azureAuthReducer';
import { store } from '../data/store';
import { CommandServiceImpl } from '../platform/commands/commandServiceImpl';
import {
AzureLoginFailedDialogContainer,
AzureLoginPromptDialogContainer,
Expand All @@ -67,7 +68,7 @@ import {

/** Register UI commands (toggling UI) */
export function registerCommands(commandRegistry: CommandRegistry) {
const { UI } = SharedConstants.Commands;
const { UI, Telemetry } = SharedConstants.Commands;

// ---------------------------------------------------------------------------
// Shows the welcome page
Expand Down Expand Up @@ -136,6 +137,9 @@ export function registerCommands(commandRegistry: CommandRegistry) {
link => link.href
); // href is fully qualified
store.dispatch(switchTheme(themeName, themeComponents));
CommandServiceImpl.remoteCall(Telemetry.TrackEvent, 'app_chooseTheme', {
themeName,
}).catch(_e => void 0);
}
);

Expand Down
8 changes: 8 additions & 0 deletions packages/app/client/src/data/sagas/azureAuthSaga.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ describe('The azureAuthSaga', () => {
ct++;
}
expect(ct).toBe(5);
expect(remoteCallSpy).toHaveBeenCalledWith(
SharedConstants.Commands.Telemetry.TrackEvent,
'signIn_failure'
);
});

it('should contain 6 steps when the Azure login dialog prompt is confirmed and auth succeeds', async () => {
Expand Down Expand Up @@ -257,6 +261,10 @@ describe('The azureAuthSaga', () => {
expect(store.getState().azureAuth.access_token).toBe(
'a valid access_token'
);
expect(remoteCallSpy).toHaveBeenCalledWith(
SharedConstants.Commands.Telemetry.TrackEvent,
'signIn_success'
);
});
});
});
7 changes: 7 additions & 0 deletions packages/app/client/src/data/sagas/azureAuthSaga.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export function* getArmToken(
RetrieveArmToken,
PersistAzureLoginChanged,
} = SharedConstants.Commands.Azure;
const { TrackEvent } = SharedConstants.Commands.Telemetry;
azureAuth = yield call(
CommandServiceImpl.remoteCall.bind(CommandServiceImpl),
RetrieveArmToken
Expand All @@ -80,8 +81,14 @@ export function* getArmToken(
PersistAzureLoginChanged,
persistLogin
);
CommandServiceImpl.remoteCall(TrackEvent, 'signIn_success').catch(
_e => void 0
);
} else {
yield DialogService.showDialog(action.payload.loginFailedDialog);
CommandServiceImpl.remoteCall(TrackEvent, 'signIn_failure').catch(
_e => void 0
);
}
yield put(azureArmTokenDataChanged(azureAuth.access_token));
return azureAuth;
Expand Down
14 changes: 13 additions & 1 deletion packages/app/client/src/data/sagas/resourceSagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ describe('The ResourceSagas', () => {
});
});

describe(',when opening the resource in the Emulator', () => {
describe('when opening the resource in the Emulator', () => {
let mockResource;
beforeEach(() => {
mockResource = BotConfigWithPathImpl.serviceFromJSON({
Expand All @@ -259,6 +259,12 @@ describe('The ResourceSagas', () => {
args: ['the/file/path/chat.chat', true],
},
]);
expect(mockRemoteCommandsCalled).toEqual([
{
commandName: SharedConstants.Commands.Telemetry.TrackEvent,
args: ['chatFile_open'],
},
]);
});

it('should open a transcript file', async () => {
Expand All @@ -270,6 +276,12 @@ describe('The ResourceSagas', () => {
args: ['the/file/path/transcript.transcript'],
},
]);
expect(mockRemoteCommandsCalled).toEqual([
{
commandName: SharedConstants.Commands.Telemetry.TrackEvent,
args: ['transcriptFile_open', { method: 'resources_pane' }],
},
]);
});
});

Expand Down
7 changes: 7 additions & 0 deletions packages/app/client/src/data/sagas/resourcesSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,18 @@ function* doOpenResource(
action: ResourcesAction<IFileService>
): IterableIterator<any> {
const { OpenChatFile, OpenTranscript } = SharedConstants.Commands.Emulator;
const { TrackEvent } = SharedConstants.Commands.Telemetry;
const { path } = action.payload;
if (isChatFile(path)) {
yield CommandServiceImpl.call(OpenChatFile, path, true);
CommandServiceImpl.remoteCall(TrackEvent, 'chatFile_open').catch(
_e => void 0
);
} else if (isTranscriptFile(path)) {
yield CommandServiceImpl.call(OpenTranscript, path);
CommandServiceImpl.remoteCall(TrackEvent, 'transcriptFile_open', {
method: 'resources_pane',
}).catch(_e => void 0);
}
// unknown types just fall into the abyss
}
Expand Down
7 changes: 7 additions & 0 deletions packages/app/client/src/hyperlinkHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,23 @@ const Electron = (window as any).require('electron');
const { shell } = Electron;

export function navigate(url: string) {
const { TrackEvent } = SharedConstants.Commands.Telemetry;
try {
const parsed = URL.parse(url) || { protocol: '' };
if ((parsed.protocol || '').startsWith('oauth:')) {
navigateEmulatedOAuthUrl(url.substring(8));
} else if (parsed.protocol.startsWith('oauthlink:')) {
navigateOAuthUrl(url.substring(12));
} else {
CommandServiceImpl.remoteCall(TrackEvent, 'app_openLink', { url }).catch(
_e => void 0
);
shell.openExternal(url, { activate: true });
}
} catch (e) {
CommandServiceImpl.remoteCall(TrackEvent, 'app_openLink', { url }).catch(
_e => void 0
);
shell.openExternal(url, { activate: true });
}
}
Expand Down
4 changes: 4 additions & 0 deletions packages/app/client/src/inspector-preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ window.host = {
}
},

trackEvent: function(name, properties) {
ipcRenderer.sendToHost('track-event', name, properties);
},

dispatch: function(event, ...args) {
this.handlers[event].forEach(handler => handler(...args));
},
Expand Down
Loading

0 comments on commit 43ba5dc

Please sign in to comment.