Skip to content

Commit

Permalink
feat: provide telemetry to console plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
vsavkin committed Nov 9, 2018
1 parent 33b85fa commit a5049b4
Show file tree
Hide file tree
Showing 13 changed files with 729 additions and 536 deletions.
21 changes: 12 additions & 9 deletions apps/angular-console/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import {
} from '@angular-console/feature-settings';
import { UiModule } from '@angular-console/ui';
import {
AnalyticsCollector,
Telemetry,
IsNodeJsInstalledGuard,
Messenger
} from '@angular-console/utils';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { NgModule, Inject } from '@angular/core';
import {
MatIconModule,
MatListModule,
Expand All @@ -36,27 +36,27 @@ import { onError } from 'apollo-link-error';
import { AppComponent } from './app.component';

export function initApollo(
analytics: AnalyticsCollector,
telemetry: Telemetry,
messenger: Messenger,
httpLink: HttpLink
) {
analytics.setUpRouterLogging();
telemetry.setUpRouterLogging();

const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message }) => {
messenger.error(message);
analytics.reportException(message);
telemetry.reportException(message);
});
} else if (networkError) {
const n: any = networkError;
if (n.error && n.error.errors && n.error.errors.length > 0) {
const message = n.error.errors[0].message;
messenger.error(message);
analytics.reportException(message);
telemetry.reportException(message);
} else {
messenger.error(n.message);
analytics.reportException(n.message);
telemetry.reportException(n.message);
}
}
});
Expand Down Expand Up @@ -112,11 +112,14 @@ export function initApollo(
],
providers: [
IsNodeJsInstalledGuard,
AnalyticsCollector,
{
provide: 'telemetry',
useClass: Telemetry
},
{
provide: APOLLO_OPTIONS,
useFactory: initApollo,
deps: [AnalyticsCollector, Messenger, HttpLink]
deps: [[new Inject('telemetry')], Messenger, HttpLink]
}
],
bootstrap: [AppComponent]
Expand Down
8 changes: 4 additions & 4 deletions libs/feature-settings/src/lib/settings/settings.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { Component, Inject, OnInit } from '@angular/core';
import { ContextualActionBarService } from '@nrwl/angular-console-enterprise-frontend';
import { AnalyticsCollector, Settings } from '@angular-console/utils';
import { Telemetry, Settings } from '@angular-console/utils';

@Component({
selector: 'angular-console-settings',
Expand All @@ -11,7 +11,7 @@ export class SettingsComponent implements OnInit {
constructor(
private readonly contextActionService: ContextualActionBarService,
private readonly settingsService: Settings,
private readonly analytics: AnalyticsCollector
@Inject('telemetry') private readonly telemetry: Telemetry
) {}

ngOnInit() {
Expand All @@ -24,7 +24,7 @@ export class SettingsComponent implements OnInit {

toggleDataCollection(x: boolean) {
this.settingsService.setCanCollectData(x);
this.analytics.reportDataCollectionEvent(x);
this.telemetry.reportDataCollectionEvent(x);
}

enableDetailedStatus() {
Expand Down
8 changes: 4 additions & 4 deletions libs/ui/src/lib/data-collection/data-collection.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { AnalyticsCollector, Settings } from '@angular-console/utils';
import { Component, Inject } from '@angular/core';
import { Telemetry, Settings } from '@angular-console/utils';

@Component({
selector: 'ui-data-collection',
Expand All @@ -8,7 +8,7 @@ import { AnalyticsCollector, Settings } from '@angular-console/utils';
})
export class DataCollectionComponent {
constructor(
private readonly analytics: AnalyticsCollector,
@Inject('telemetry') private readonly telemetry: Telemetry,
private readonly settings: Settings
) {}

Expand All @@ -18,6 +18,6 @@ export class DataCollectionComponent {

close(value: boolean) {
this.settings.setCanCollectData(value);
this.analytics.reportDataCollectionEvent(value);
this.telemetry.reportDataCollectionEvent(value);
}
}
2 changes: 1 addition & 1 deletion libs/utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './lib/analytics-collector.service';
export * from './lib/telemetry.service';
export * from './lib/completion.service';
export * from './lib/command-runner.service';
export * from './lib/editor-support.service';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { cleanUpUrl } from './analytics-collector.service';
import { cleanUpUrl } from './telemetry.service';

describe('AnalyticsCollector', () => {
describe('Telemetry', () => {
it('should remove workspace path from the url', () => {
expect(cleanUpUrl('/workspace/secret/aa/bb')).toEqual(
'/workspace/PATH/aa/bb'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { filter } from 'rxjs/operators';
declare var global: any;

@Injectable()
export class AnalyticsCollector {
export class Telemetry {
private readonly ipc: any;

constructor(private readonly router: Router) {
Expand Down Expand Up @@ -40,6 +40,12 @@ export class AnalyticsCollector {
}
}

reportEvent(category: string, action: string, label: string, value: string) {
if (this.ipc) {
this.ipc.send('event', { category, action, label, value });
}
}

private reportPageView(path: string) {
if (this.ipc) {
this.ipc.send('reportPageView', { path });
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
"@angular/platform-browser": "7.0.2",
"@angular/platform-browser-dynamic": "7.0.2",
"@angular/router": "7.0.2",
"@nrwl/angular-console-enterprise-electron": "0.0.13",
"@nrwl/angular-console-enterprise-frontend": "0.0.13",
"@nrwl/angular-console-enterprise-electron": "0.0.15",
"@nrwl/angular-console-enterprise-frontend": "0.0.15",
"@nrwl/schematics": "7.0.2",
"@types/express": "4.16.0",
"@types/graphql": "0.13.0",
Expand Down
2 changes: 1 addition & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"license": "MIT",
"dependencies": {
"@angular/cli": "7.0.4",
"@nrwl/angular-console-enterprise-electron": "0.0.13",
"@nrwl/angular-console-enterprise-electron": "0.0.15",
"@nrwl/schematics": "7.0.2",
"@types/tmp": "0.0.33",
"apollo-server-express": "2.1.0",
Expand Down
36 changes: 25 additions & 11 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@ import * as path from 'path';
import { statSync } from 'fs';
import * as os from 'os';
import { autoUpdater } from 'electron-updater';
import {
reportEvent,
reportException,
setupEvents
} from './analytics_and_settings';
import { telemetry } from './telemetry';

import { ipcMain } from 'electron';

const fixPath = require('fix-path');
const getPort = require('get-port');
Expand All @@ -21,6 +19,22 @@ const store = new Store();
fixPath();
const currentDirectory = process.cwd();

function setupEvents() {
process.env.trackingID = 'UA-88380372-8';
ipcMain.on('event', (event: any, arg: any) =>
telemetry.reportEvent(arg.category, arg.action, arg.label, arg.value)
);
ipcMain.on('dataCollectionEvent', (event: any, arg: any) =>
telemetry.dataCollectionEvent(arg.value)
);
ipcMain.on('reportPageView', (event: any, arg: any) =>
telemetry.reportPageView(arg.path)
);
ipcMain.on('reportException', (event: any, arg: any) =>
telemetry.reportException(arg.description)
);
}

function createMenu() {
let menu = [];
const name = app.getName();
Expand Down Expand Up @@ -129,7 +143,7 @@ function createWindow() {
}
} catch (e) {
showCloseDialog(`Error when starting Angular Console: ${e.message}`);
reportException(`Start failed: ${e.message}`);
telemetry.reportException(`Start failed: ${e.message}`);
}
});

Expand All @@ -145,7 +159,7 @@ function startServer(port: number) {
const { start } = require('./server');
start(port);
} catch (e) {
reportException(`Start Server: ${e.message}`);
telemetry.reportException(`Start Server: ${e.message}`);
throw e;
}
}
Expand Down Expand Up @@ -181,7 +195,7 @@ function showRestartDialog() {
dialog.showMessageBox(dialogOptions, i => {
if (i === 0) {
// Restart
reportEvent('Lifecycle', 'QuitAndInstall');
telemetry.reportLifecycleEvent('QuitAndInstall');
autoUpdater.quitAndInstall();
}
});
Expand All @@ -205,14 +219,14 @@ function checkForUpdates() {
console.log('checkForUpdates is called. downloadPromise is null.');
}
} catch (e) {
reportException(e);
telemetry.reportException(e);
}
}
}, 0);
}

function startSession() {
reportEvent('Lifecycle', 'StartSession');
telemetry.reportLifecycleEvent('StartSession');
}

function quit() {
Expand All @@ -227,7 +241,7 @@ function saveWindowInfo() {
try {
store.set('windowBounds', JSON.stringify(mainWindow.getBounds()));
} catch (e) {
reportException(`Saving window bounds failed: ${e.message}`);
telemetry.reportException(`Saving window bounds failed: ${e.message}`);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import { schema } from './schema';
import { createSchema } from '@nrwl/angular-console-enterprise-electron';
import { commands } from './api/run-command';
import { readSettings } from './api/read-settings';
import { telemetry } from './telemetry';

const apollo = new ApolloServer({
schema: mergeSchemas({
schemas: [
schema,
createSchema({
readSettings,
commands
commands,
telemetry
})
]
}),
Expand Down
86 changes: 86 additions & 0 deletions server/src/telemetry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* tslint:disable */

import * as ua from 'universal-analytics';
const uuidv4 = require('uuid/v4');
const Store = require('electron-store');

export class Telemetry {
private readonly store = new Store();
private readonly visitor = new ua.Visitor('UA-88380372-8', this.getUuiId(), {
https: true
});

dataCollectionEvent(value: boolean) {
try {
this.visitor
.event('DataCollection', 'DataCollectionResponse', value.toString())
.send();
} catch (e) {
console.error('dataCollectionEvent', e);
}
}

reportEvent(
category: string,
action: string,
label?: string,
value?: number
) {
try {
if (value) {
this.visitor.event(category, action, label!, value, {}).send();
} else {
this.visitor.event(category, action, label!).send();
}
} catch (e) {
console.error('reportEvent', e);
}
}

reportLifecycleEvent(action: string) {
try {
if (this.canCollectData()) {
this.visitor.event('Lifecycle', action).send();
}
} catch (e) {
console.error('reportLifecycleEvent', e);
}
}

reportException(description: string) {
try {
if (this.canCollectData()) {
console.error(description);
this.visitor.exception(description).send();
}
} catch (e) {
console.error('reportException', e);
}
}

reportPageView(path: string) {
try {
if (this.canCollectData()) {
this.visitor.pageview(path, 'Angular Console', '6.0.0').send();
}
} catch (e) {
console.error('reportPageView', e);
}
}

private getUuiId() {
if (this.store.get('uuid')) {
return this.store.get('uuid');
}
const uuid = uuidv4();
this.store.set('uuid', uuid);
return uuid;
}

private canCollectData(): boolean {
const settings = this.store.get('settings');
return settings && settings.canCollectData;
}
}

export const telemetry = new Telemetry();
2 changes: 2 additions & 0 deletions server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"sourceMap": false,
"declaration": false,
"moduleResolution": "node",
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"target": "es2017",
"types": ["jasmine"],
"typeRoots": ["../node_modules/@types"],
Expand Down
Loading

0 comments on commit a5049b4

Please sign in to comment.