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;
|
|
|
|
mixpanelHost: string;
|
|
|
|
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
|
|
|
};
|
|
|
|
if (offlineMode) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.client = Mixpanel.init(mixpanelToken, { host: mixpanelHost });
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public track(
|
|
|
|
event: string,
|
2018-09-04 15:57:50 -07:00
|
|
|
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-02 16:32:08 -07:00
|
|
|
this.debouncedLogger(event)(properties);
|
2018-08-25 21:18:11 +01:00
|
|
|
}
|
|
|
|
|
2018-09-02 16:32:08 -07:00
|
|
|
private debouncedLogger = memoizee((event: string) => {
|
|
|
|
// Call this function at maximum once every minute
|
|
|
|
return _.debounce((properties) => {
|
|
|
|
this.client.track(event, properties);
|
|
|
|
}, eventDebounceTime, { leading: true });
|
|
|
|
}, { primitive: true });
|
|
|
|
|
2018-08-25 21:18:11 +01:00
|
|
|
private logEvent(...args: string[]) {
|
|
|
|
console.log(...args);
|
|
|
|
}
|
|
|
|
|
|
|
|
private assignDefaultProperties(
|
|
|
|
properties: EventTrackProperties,
|
|
|
|
): EventTrackProperties {
|
|
|
|
return _.merge({ }, properties, this.defaultProperties);
|
|
|
|
}
|
|
|
|
}
|