Skip to content

Commit 600d6ab

Browse files
committed
add custom logger support
update types
1 parent c093a6b commit 600d6ab

9 files changed

+190
-33
lines changed

.npmignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
test/
2+
.github/

lib/mixpanel-node.d.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,24 @@ declare namespace mixpanel {
66

77
type Scalar = string | number | boolean;
88

9+
export interface CustomLogger {
10+
trace(message?: any, ...optionalParams: any[]): void;
11+
debug(message?: any, ...optionalParams: any[]): void;
12+
info(message?: any, ...optionalParams: any[]): void;
13+
warn(message?: any, ...optionalParams: any[]): void;
14+
error(message?: any, ...optionalParams: any[]): void;
15+
}
16+
917
export interface InitConfig {
10-
[key: string]: any;
18+
test: boolean;
19+
debug: boolean;
20+
verbose: boolean;
21+
host: string;
22+
protocol: string;
23+
path: string;
24+
keepAlive: boolean;
25+
geolocate: boolean;
26+
logger: CustomLogger;
1127
}
1228

1329
export interface PropertyDict {
@@ -45,7 +61,7 @@ declare namespace mixpanel {
4561
}
4662

4763
interface Mixpanel {
48-
init(mixpanelToken: string, config?: InitConfig): Mixpanel;
64+
init(mixpanelToken: string, config?: Partial<InitConfig>): Mixpanel;
4965

5066
track(eventName: string, callback?: Callback): void;
5167
track(eventName: string, properties: PropertyDict, callback?: Callback): void;

lib/mixpanel-node.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const HttpsProxyAgent = require('https-proxy-agent');
1515
const url = require('url');
1616
const packageInfo = require('../package.json')
1717

18-
const {async_all, ensure_timestamp} = require('./utils');
18+
const {async_all, ensure_timestamp, assert_logger} = require('./utils');
1919
const {MixpanelGroups} = require('./groups');
2020
const {MixpanelPeople} = require('./people');
2121

@@ -30,6 +30,7 @@ const DEFAULT_CONFIG = {
3030
// set this to true to automatically geolocate based on the client's ip.
3131
// e.g., when running under electron
3232
geolocate: false,
33+
logger: console,
3334
};
3435

3536
var create_client = function(token, config) {
@@ -152,7 +153,7 @@ var create_client = function(token, config) {
152153

153154
request.on('error', function(e) {
154155
if (metrics.config.debug) {
155-
console.log("Got Error: " + e.message);
156+
metrics.config.logger.error("Got Error: " + e.message);
156157
}
157158
callback(e);
158159
});
@@ -181,7 +182,7 @@ var create_client = function(token, config) {
181182
};
182183

183184
if (metrics.config.debug) {
184-
console.log("Sending the following event to Mixpanel:\n", data);
185+
metrics.config.logger.debug("Sending the following event to Mixpanel", { data });
185186
}
186187

187188
metrics.send_request({ method: "GET", endpoint: endpoint, data: data }, callback);
@@ -269,7 +270,7 @@ var create_client = function(token, config) {
269270
send_next_request_batch(0);
270271

271272
if (metrics.config.debug) {
272-
console.log(
273+
metrics.config.logger.debug(
273274
"Sending " + event_list.length + " events to Mixpanel in " +
274275
total_event_batches + " batches of events and " +
275276
total_request_batches + " batches of requests"
@@ -446,6 +447,9 @@ var create_client = function(token, config) {
446447
mixpanel client config
447448
*/
448449
metrics.set_config = function(config) {
450+
if (config && config.logger !== undefined) {
451+
assert_logger(config.logger);
452+
}
449453
Object.assign(metrics.config, config);
450454
if (config.host) {
451455
// Split host into host and port

lib/people.js

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,10 @@ class MixpanelPeople extends ProfileHelpers() {
8181
for (const [key, val] of Object.entries(prop)) {
8282
if (isNaN(parseFloat(val))) {
8383
if (this.mixpanel.config.debug) {
84-
console.error("Invalid increment value passed to mixpanel.people.increment - must be a number");
85-
console.error("Passed " + key + ":" + val);
84+
this.mixpanel.config.logger.error(
85+
"Invalid increment value passed to mixpanel.people.increment - must be a number",
86+
{key, value: val}
87+
);
8688
}
8789
} else {
8890
$add[key] = val;
@@ -114,8 +116,7 @@ class MixpanelPeople extends ProfileHelpers() {
114116
data = merge_modifiers(data, modifiers);
115117

116118
if (this.mixpanel.config.debug) {
117-
console.log("Sending the following data to Mixpanel (Engage):");
118-
console.log(data);
119+
this.mixpanel.config.logger.debug("Sending the following data to Mixpanel (Engage)", { data });
119120
}
120121

121122
this.mixpanel.send_request({ method: "GET", endpoint: "/engage", data: data }, callback);
@@ -168,8 +169,7 @@ class MixpanelPeople extends ProfileHelpers() {
168169
data = merge_modifiers(data, modifiers);
169170

170171
if (this.mixpanel.config.debug) {
171-
console.log("Sending the following data to Mixpanel (Engage):");
172-
console.log(data);
172+
this.mixpanel.config.logger.debug("Sending the following data to Mixpanel (Engage)", { data });
173173
}
174174

175175
this.mixpanel.send_request({ method: "GET", endpoint: "/engage", data: data }, callback);
@@ -209,7 +209,7 @@ class MixpanelPeople extends ProfileHelpers() {
209209
if (typeof(amount) !== 'number') {
210210
amount = parseFloat(amount);
211211
if (isNaN(amount)) {
212-
console.error("Invalid value passed to mixpanel.people.track_charge - must be a number");
212+
this.mixpanel.config.logger.error("Invalid value passed to mixpanel.people.track_charge - must be a number");
213213
return;
214214
}
215215
}
@@ -232,8 +232,7 @@ class MixpanelPeople extends ProfileHelpers() {
232232
data = merge_modifiers(data, modifiers);
233233

234234
if (this.mixpanel.config.debug) {
235-
console.log("Sending the following data to Mixpanel (Engage):");
236-
console.log(data);
235+
this.mixpanel.config.logger.debug("Sending the following data to Mixpanel (Engage)", { data });
237236
}
238237

239238
this.mixpanel.send_request({ method: "GET", endpoint: "/engage", data: data }, callback);
@@ -260,7 +259,7 @@ class MixpanelPeople extends ProfileHelpers() {
260259
data = merge_modifiers(data, modifiers);
261260

262261
if (this.mixpanel.config.debug) {
263-
console.log("Clearing this user's charges:", distinct_id);
262+
this.mixpanel.config.logger.debug("Clearing this user's charges", { '$distinct_id': distinct_id });
264263
}
265264

266265
this.mixpanel.send_request({ method: "GET", endpoint: "/engage", data: data }, callback);

lib/profile_helpers.js

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
7676
data = merge_modifiers(data, modifiers);
7777

7878
if (this.config.debug) {
79-
console.log(`Sending the following data to Mixpanel (${this.endpoint}):`);
80-
console.log(data);
79+
this.mixpanel.config.logger.debug(`Sending the following data to Mixpanel (${this.endpoint})`, { data });
8180
}
8281

8382
this.mixpanel.send_request({ method: "GET", endpoint: this.endpoint, data }, callback);
@@ -95,7 +94,7 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
9594
data = merge_modifiers(data, modifiers);
9695

9796
if (this.config.debug) {
98-
console.log(`Deleting profile ${JSON.stringify(identifiers)}`);
97+
this.mixpanel.config.logger.debug('Deleting profile', { identifiers });
9998
}
10099

101100
this.mixpanel.send_request({ method: "GET", endpoint: this.endpoint, data }, callback);
@@ -106,7 +105,7 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
106105

107106
if (typeof(data) !== 'object' || util.isArray(data)) {
108107
if (this.config.debug) {
109-
console.error("Invalid value passed to #remove - data must be an object with scalar values");
108+
this.mixpanel.config.logger.error("Invalid value passed to #remove - data must be an object with scalar values");
110109
}
111110
return;
112111
}
@@ -116,8 +115,10 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
116115
$remove[key] = val;
117116
} else {
118117
if (this.config.debug) {
119-
console.error("Invalid argument passed to #remove - values must be scalar");
120-
console.error("Passed " + key + ':', val);
118+
this.mixpanel.config.logger.error(
119+
"Invalid argument passed to #remove - values must be scalar",
120+
{ key, value: val }
121+
);
121122
}
122123
return;
123124
}
@@ -140,8 +141,10 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
140141
data = merge_modifiers(data, modifiers);
141142

142143
if (this.config.debug) {
143-
console.log(`Sending the following data to Mixpanel (${this.endpoint}):`);
144-
console.log(data);
144+
this.mixpanel.config.logger.debug(
145+
`Sending the following data to Mixpanel (${this.endpoint})`,
146+
{ data }
147+
);
145148
}
146149

147150
this.mixpanel.send_request({ method: "GET", endpoint: this.endpoint, data }, callback);
@@ -152,7 +155,7 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
152155

153156
if (typeof(data) !== 'object' || util.isArray(data)) {
154157
if (this.config.debug) {
155-
console.error("Invalid value passed to #union - data must be an object with scalar or array values");
158+
this.mixpanel.config.logger.error("Invalid value passed to #union - data must be an object with scalar or array values");
156159
}
157160
return;
158161
}
@@ -169,8 +172,10 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
169172
$union[key] = [val];
170173
} else {
171174
if (this.config.debug) {
172-
console.error("Invalid argument passed to #union - values must be a scalar value or array");
173-
console.error("Passed " + key + ':', val);
175+
this.mixpanel.config.logger.error(
176+
"Invalid argument passed to #union - values must be a scalar value or array",
177+
{ key, value: val }
178+
);
174179
}
175180
}
176181
}
@@ -192,8 +197,10 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
192197
data = merge_modifiers(data, modifiers);
193198

194199
if (this.config.debug) {
195-
console.log(`Sending the following data to Mixpanel (${this.endpoint}):`);
196-
console.log(data);
200+
this.mixpanel.config.logger.debug(
201+
`Sending the following data to Mixpanel (${this.endpoint})`,
202+
{ data }
203+
);
197204
}
198205

199206
this.mixpanel.send_request({ method: "GET", endpoint: this.endpoint, data }, callback);
@@ -208,8 +215,10 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
208215
$unset = [prop];
209216
} else {
210217
if (this.config.debug) {
211-
console.error("Invalid argument passed to #unset - must be a string or array");
212-
console.error("Passed: " + prop);
218+
this.mixpanel.config.logger.error(
219+
"Invalid argument passed to #unset - must be a string or array",
220+
{ prop }
221+
);
213222
}
214223
return;
215224
}
@@ -227,8 +236,10 @@ exports.ProfileHelpers = (Base = Object) => class extends Base {
227236
data = merge_modifiers(data, modifiers);
228237

229238
if (this.config.debug) {
230-
console.log(`Sending the following data to Mixpanel (${this.endpoint}):`);
231-
console.log(data);
239+
this.mixpanel.config.logger.debug(
240+
`Sending the following data to Mixpanel (${this.endpoint})`,
241+
{ data }
242+
);
232243
}
233244

234245
this.mixpanel.send_request({ method: "GET", endpoint: this.endpoint, data }, callback);

lib/utils.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,21 @@ exports.ensure_timestamp = function(time) {
4141
}
4242
return time instanceof Date ? time.getTime() : time;
4343
};
44+
45+
/**
46+
* Asserts that the provided logger object is valid
47+
* @param {CustomLogger} logger - The logger object to be validated
48+
* @throws {TypeError} If the logger object is not a valid Logger object or
49+
* if it is missing any of the required methods
50+
*/
51+
exports.assert_logger = function(logger) {
52+
if (typeof logger !== 'object') {
53+
throw new TypeError(`"logger" must be a valid Logger object`);
54+
}
55+
56+
['trace', 'debug', 'info', 'warn', 'error'].forEach((method) => {
57+
if (typeof logger[method] !== 'function') {
58+
throw new TypeError(`Logger object missing "${method}" method`);
59+
}
60+
});
61+
};

readme.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ var mixpanel = Mixpanel.init('<YOUR_TOKEN>', {
3030
keepAlive: false,
3131
});
3232

33+
// pass the custom logger (default is console)
34+
var mixpanel = Mixpanel.init('<YOUR_TOKEN>', {
35+
debug: true,
36+
logger: pinoLogger, // or bunyan, or any other logger that implements the same interface
37+
});
38+
3339
// track an event with optional properties
3440
mixpanel.track('my event', {
3541
distinct_id: 'some unique client id',

test/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ exports.config = {
1616
path: '',
1717
keepAlive: true,
1818
geolocate: false,
19+
logger: console,
1920
}, "default config is incorrect");
2021
test.done();
2122
},

0 commit comments

Comments
 (0)