2018-08-25 21:18:11 +01:00
|
|
|
import * as Bluebird from 'bluebird';
|
|
|
|
import mask = require('json-mask');
|
|
|
|
import * as _ from 'lodash';
|
2018-09-02 16:32:08 -07:00
|
|
|
import * as memoizee from 'memoizee';
|
2018-08-25 21:18:11 +01:00
|
|
|
|
|
|
|
import Mixpanel = require('mixpanel');
|
|
|
|
|
2018-09-02 16:35:46 -07:00
|
|
|
import supervisorVersion = require('./lib/supervisor-version');
|
|
|
|
|
2018-08-25 21:18:11 +01:00
|
|
|
export type EventTrackProperties = Dictionary<any>;
|
|
|
|
|
|
|
|
interface InitArgs {
|
|
|
|
uuid: string;
|
|
|
|
offlineMode: boolean;
|
2018-11-26 16:34:53 +00:00
|
|
|
mixpanelHost: { host: string; path: string } | null;
|
2018-08-25 21:18:11 +01:00
|
|
|
mixpanelToken: string;
|
|
|
|
}
|
|
|
|
|
2018-09-02 16:32:08 -07:00
|
|
|
// The minimum amount of time to wait between sending
|
|
|
|
// events of the same type
|
|
|
|
const eventDebounceTime = 60000;
|
|
|
|
|
2018-08-25 21:18:11 +01:00
|
|
|
const mixpanelMask = [
|
|
|
|
'appId',
|
|
|
|
'delay',
|
|
|
|
'error',
|
|
|
|
'interval',
|
|
|
|
'image',
|
|
|
|
'app(appId,name)',
|
|
|
|
'service(appId,serviceId,serviceName,commit,releaseId,image,labels)',
|
|
|
|
'stateDiff/local(os_version,superisor_version,ip_address,apps/*/services)',
|
|
|
|
].join(',');
|
|
|
|
|
|
|
|
export class EventTracker {
|
|
|
|
private defaultProperties: EventTrackProperties | null;
|
|
|
|
private client: any;
|
|
|
|
|
|
|
|
public constructor() {
|
|
|
|
this.client = null;
|
|
|
|
this.defaultProperties = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public init({
|
|
|
|
offlineMode,
|
|
|
|
mixpanelHost,
|
|
|
|
mixpanelToken,
|
|
|
|
uuid,
|
|
|
|
}: InitArgs): Bluebird<void> {
|
|
|
|
return Bluebird.try(() => {
|
|
|
|
this.defaultProperties = {
|
|
|
|
distinct_id: uuid,
|
|
|
|
uuid,
|
2018-09-02 16:35:46 -07:00
|
|
|
supervisorVersion,
|
2018-08-25 21:18:11 +01:00
|
|
|
};
|
2018-11-26 16:34:53 +00:00
|
|
|
if (offlineMode || mixpanelHost == null) {
|
2018-08-25 21:18:11 +01:00
|
|
|
return;
|
|
|
|
}
|
2018-11-20 17:07:46 +00:00
|
|
|
this.client = Mixpanel.init(mixpanelToken, {
|
|
|
|
host: mixpanelHost.host,
|
|
|
|
path: mixpanelHost.path,
|
|
|
|
});
|
2018-08-25 21:18:11 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-11-02 14:17:58 +00:00
|
|
|
public track(event: string, properties: EventTrackProperties | Error = {}) {
|
2018-08-25 21:18:11 +01:00
|
|
|
if (properties instanceof Error) {
|
|
|
|
properties = { error: properties };
|
|
|
|
}
|
|
|
|
|
|
|
|
properties = _.cloneDeep(properties);
|
|
|
|
if (properties.error instanceof Error) {
|
|
|
|
// Format the error for printing, to avoid display as { }
|
|
|
|
properties.error = {
|
|
|
|
message: properties.error.message,
|
|
|
|
stack: properties.error.stack,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// Don't send potentially sensitive information, by using a whitelist
|
|
|
|
properties = mask(properties, mixpanelMask);
|
|
|
|
this.logEvent('Event:', event, JSON.stringify(properties));
|
|
|
|
if (this.client == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
properties = this.assignDefaultProperties(properties);
|
2018-09-12 12:30:31 +01:00
|
|
|
this.throttleddLogger(event)(properties);
|
2018-08-25 21:18:11 +01:00
|
|
|
}
|
|
|
|
|
2018-11-02 14:17:58 +00:00
|
|
|
private throttleddLogger = memoizee(
|
|
|
|
(event: string) => {
|
|
|
|
// Call this function at maximum once every minute
|
|
|
|
return _.throttle(
|
|
|
|
properties => {
|
|
|
|
this.client.track(event, properties);
|
|
|
|
},
|
|
|
|
eventDebounceTime,
|
|
|
|
{ leading: true },
|
|
|
|
);
|
|
|
|
},
|
|
|
|
{ primitive: true },
|
|
|
|
);
|
2018-09-02 16:32:08 -07:00
|
|
|
|
2018-08-25 21:18:11 +01:00
|
|
|
private logEvent(...args: string[]) {
|
|
|
|
console.log(...args);
|
|
|
|
}
|
|
|
|
|
|
|
|
private assignDefaultProperties(
|
|
|
|
properties: EventTrackProperties,
|
|
|
|
): EventTrackProperties {
|
2018-11-02 14:17:58 +00:00
|
|
|
return _.merge({}, properties, this.defaultProperties);
|
2018-08-25 21:18:11 +01:00
|
|
|
}
|
|
|
|
}
|