Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #6132 from trufflesuite/add-mixpanel
Browse files Browse the repository at this point in the history
replace google analytics with mixpanel
  • Loading branch information
eggplantzzz authored Jul 5, 2023
2 parents a6fb238 + 9a4007c commit cc509af
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 242 deletions.
10 changes: 5 additions & 5 deletions packages/core/lib/commands/config/run.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const analyticsUtils = require("./utils");
const userLevelSettings = ["analytics"];
/**
* run config commands to get/set/list Truffle config options
* @param {Object} options
**/
module.exports = async function (options) {
const googleAnalytics = require("../../services/analytics/google.js");
const Config = require("@truffle/config");
const OS = require("os");

Expand All @@ -31,14 +31,14 @@ module.exports = async function (options) {
}

if (command === null) {
return await googleAnalytics.setUserConfigViaPrompt();
return await analyticsUtils.setUserConfigViaPrompt();
} else if (command.userLevel) {
switch (command.key) {
case "analytics": {
if (command.set) {
googleAnalytics.setAnalytics(command.value);
analyticsUtils.setAnalytics(command.value);
} else {
log(googleAnalytics.getAnalytics());
log(analyticsUtils.getAnalytics());
}
break;
}
Expand All @@ -47,7 +47,7 @@ module.exports = async function (options) {
return;
} else if (command.list) {
log("Truffle config values");
log(`analytics = ${googleAnalytics.getAnalytics()}`);
log(`analytics = ${analyticsUtils.getAnalytics()}`);
} else {
const config = Config.detect(options);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
/**
* @module googleAnalytics;
* @requires module:@truffle/config
* @requires module:universal-analytics
* @requires module:uuid
* @requires module:inquirer
* @requires module:../version
*/

const Config = require("@truffle/config");
const userConfig = Config.getUserConfig();
const ua = require("universal-analytics");
const { v4: uuid } = require("uuid");

const inquirer = require("inquirer");

const version = require("../../version").info();

//set truffleAnalyticsId depending on whether version is bundled
const truffleAnalyticsId = version.bundle ? "UA-83874933-6" : "UA-83874933-7";
const { v4: uuid } = require("uuid");

const analyticsInquiry = [
{
Expand Down Expand Up @@ -45,14 +28,17 @@ const analyticsEnable = [
}
];

const googleAnalytics = {
module.exports = {
getUserConfig: function () {
return Config.getUserConfig();
},
/**
* set user-level unique id
*/
setUserId: function () {
if (!userConfig.get("uniqueId")) {
let userId = uuid();
userConfig.set({ uniqueId: userId });
if (!this.getUserConfig().get("uniqueId")) {
const userId = uuid();
this.getUserConfig().set({ uniqueId: userId });
}
},
/**
Expand All @@ -61,7 +47,7 @@ const googleAnalytics = {
* @returns {bool}
*/
getAnalytics: function () {
return userConfig.get("enableAnalytics");
return this.getUserConfig().get("enableAnalytics");
},
/**
* set user-level options for analytics
Expand All @@ -72,14 +58,14 @@ const googleAnalytics = {
if (analyticsBool === true) {
this.setUserId();
console.log("Analytics enabled");
userConfig.set({
this.getUserConfig().set({
enableAnalytics: true,
analyticsSet: true,
analyticsMessageDateTime: Date.now()
});
} else if (analyticsBool === false) {
console.log("Analytics disabled");
userConfig.set({
this.getUserConfig().set({
enableAnalytics: false,
analyticsSet: true,
analyticsMessageDateTime: Date.now()
Expand All @@ -98,16 +84,19 @@ const googleAnalytics = {
* @param {Object} userConfig
*/
setUserConfigViaPrompt: async function () {
if (!userConfig.get("analyticsSet") && process.stdin.isTTY === true) {
if (
!this.getUserConfig().get("analyticsSet") &&
process.stdin.isTTY === true
) {
let answer = await inquirer.prompt(analyticsInquiry);
if (answer.analyticsInquiry === analyticsInquiry[0].choices[0]) {
this.setAnalytics(true);
} else {
this.setAnalytics(false);
}
} else if (
userConfig.get("analyticsSet") &&
userConfig.get("enableAnalytics") &&
this.getUserConfig().get("analyticsSet") &&
this.getUserConfig().get("enableAnalytics") &&
process.stdin.isTTY === true
) {
let answer = await inquirer.prompt(analyticsDisable);
Expand All @@ -117,8 +106,8 @@ const googleAnalytics = {
this.setAnalytics(true);
}
} else if (
userConfig.get("analyticsSet") &&
!userConfig.get("enableAnalytics") &&
this.getUserConfig().get("analyticsSet") &&
!this.getUserConfig().get("enableAnalytics") &&
process.stdin.isTTY === true
) {
let answer = await inquirer.prompt(analyticsEnable);
Expand All @@ -128,60 +117,6 @@ const googleAnalytics = {
this.setAnalytics(false);
}
}
return true;
},
/**
* check user-level config to see if user has enabled analytics
* @returns {bool}
*/
checkIfAnalyticsEnabled: function () {
if (userConfig.get("enableAnalytics")) {
return true;
} else {
return false;
}
},

/**
* set data that will be the same in future calls
* @returns {Object} visitor
*/
setPersistentAnalyticsData: function () {
if (this.checkIfAnalyticsEnabled() === true) {
let userId = userConfig.get("uniqueId");
let visitor = ua(truffleAnalyticsId, { cid: userId });
return visitor;
}
},

/**
* send event to Google Analytics
* @param {Object}
*/
// eslint-disable-next-line no-unused-vars
sendAnalyticsEvent: function (eventObject, callback) {
let visitor = this.setPersistentAnalyticsData();
let sendObject = {};
if (eventObject["command"]) {
sendObject["ec"] = eventObject["command"];
sendObject["ea"] = JSON.stringify(eventObject["args"]);
sendObject["el"] = eventObject["version"];
sendObject["dp"] = "/" + eventObject["command"];
} else {
sendObject["ec"] = "Error";
sendObject["ea"] = "nonzero exit code";
sendObject["el"] =
eventObject["version"] + " " + eventObject["exception"];
sendObject["dp"] = "/error";
}

if (visitor) {
// eslint-disable-next-line no-unused-vars
visitor.event(sendObject, function (err) {});
}

return true;
}
};

module.exports = googleAnalytics;
2 changes: 1 addition & 1 deletion packages/core/lib/services/analytics/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require("source-map-support/register");
const analytics = require("./google.js");
const analytics = require("./mixpanel.js");

const PROCESS_TIMEOUT = 5000; // ms

Expand Down
40 changes: 40 additions & 0 deletions packages/core/lib/services/analytics/mixpanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const Config = require("@truffle/config");
const userConfig = Config.getUserConfig();
const version = require("../../version").info();
const TRUFFLE_TOKEN = version.bundled
? "1d07dcde31267402f4ad0740bcc0d797"
: "2247a338c6bbd7e9a65bb3923e5b10b8";
const Mixpanel = require("mixpanel");

module.exports = {
sendAnalyticsEvent: function (eventObject) {
const { userId } = this.getUserId();
const sendObject = {};
const eventType = eventObject.command ? "command" : "error";
if (eventObject.command) {
sendObject["ec"] = eventObject["command"];
sendObject["ea"] = JSON.stringify(eventObject["args"]);
sendObject["el"] = eventObject["version"];
sendObject["dp"] = "/" + eventObject["command"];
} else {
sendObject["ec"] = "Error";
sendObject["ea"] = "nonzero exit code";
sendObject["el"] =
eventObject["version"] + " " + eventObject["exception"];
sendObject["dp"] = "/error";
}

if (userId) {
const mixpanel = Mixpanel.init(TRUFFLE_TOKEN, {
keepAlive: false
});
mixpanel.track(eventType, eventObject);
}

return true;
},

getUserId: function () {
return { userId: userConfig.get("uniqueId") };
}
};
4 changes: 2 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
},
"scripts": {
"prepare": "exit 0",
"test": "mocha ./test/** ./test/**/*"
"test": "mocha ./test/** ./test/**/*.js ./test/**/**/*.js"
},
"dependencies": {
"@truffle/artifactor": "^4.0.194",
Expand Down Expand Up @@ -73,6 +73,7 @@
"iter-tools": "^7.5.0",
"js-interpreter": "2.2.0",
"lodash": "^4.17.21",
"mixpanel": "^0.17.0",
"mocha": "10.1.0",
"node-emoji": "^1.8.1",
"original-require": "^1.0.1",
Expand All @@ -81,7 +82,6 @@
"source-map-support": "^0.5.19",
"spawn-args": "0.2.0",
"tmp": "^0.2.1",
"universal-analytics": "^0.4.17",
"uuid": "^9.0.0",
"web3": "1.10.0",
"web3-utils": "1.10.0",
Expand Down
98 changes: 98 additions & 0 deletions packages/core/test/lib/commands/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ const path = require("path");
const fse = require("fs-extra");
const Config = require("@truffle/config");
const { createTestProject } = require("../../helpers");
const sinon = require("sinon");
const analyticsUtils = require("../../../lib/commands/config/utils");
const inquirer = require("inquirer");
let mockUserConfig;

describe("config", function () {
let config;
Expand Down Expand Up @@ -53,4 +57,98 @@ describe("config", function () {
const expected = path.join(config.working_directory, "./a-different-dir");
assert.equal(output, expected);
});

describe("config", function () {
describe("#run", function () {
beforeEach(() => {
sinon.stub(inquirer, "prompt").returns({ then: () => 1 });
sinon.stub(analyticsUtils, "setAnalytics").resolves();
sinon.stub(analyticsUtils, "setUserConfigViaPrompt").resolves();
});
afterEach(() => {
inquirer.prompt.restore();
analyticsUtils.setAnalytics.restore();
analyticsUtils.setUserConfigViaPrompt.restore();
sinon.restore();
});
it("calls analyticsUtils.setAnalytics() when provided with enableAnalytics option", function () {
command.run({ enableAnalytics: true, _: [] }, () => {});
sinon.assert.calledOnce(analyticsUtils.setAnalytics);
});
it("calls analyticsUtils.setAnalytics() when provided with disableAnalytics option", function () {
command.run({ disableAnalytics: true, _: [] }, () => {});
sinon.assert.calledOnce(analyticsUtils.setAnalytics);
});
it("calls analyticsUtils.setuserConfigViaPrompt() if not provided with options", function () {
command.run({ _: [] });
sinon.assert.calledOnce(analyticsUtils.setUserConfigViaPrompt);
});
});
});

describe("analyticsUtils", function () {
describe("#setUserId", function () {
beforeEach(() => {
mockUserConfig = {
get: () => false,
set: sinon.spy()
};
sinon.stub(inquirer, "prompt").returns({ then: () => 1 });
sinon.stub(analyticsUtils, "getUserConfig").returns(mockUserConfig);
sinon.stub(analyticsUtils, "setUserConfigViaPrompt").resolves();
});
afterEach(() => {
inquirer.prompt.restore();
analyticsUtils.getUserConfig.restore();
analyticsUtils.setUserConfigViaPrompt.restore();
});

it("sets a userId if one does not exist", function () {
analyticsUtils.setUserId();
assert(mockUserConfig.set.calledOnce);
});
});

describe("#setAnalytics", function () {
beforeEach(function () {
mockUserConfig = {
get: sinon.spy(),
set: sinon.spy()
};
sinon.stub(analyticsUtils, "getUserConfig").returns(mockUserConfig);
});
afterEach(function () {
analyticsUtils.getUserConfig.restore();
});

it("sets user-level analytics preferences when passed enableAnalytics option", async function () {
sinon.stub(analyticsUtils, "setAnalytics").resolves();
await command.run({ enableAnalytics: true }, () => {});
let stubArg = analyticsUtils.setAnalytics.getCall(0).args[0];
assert.equal(stubArg, true);
analyticsUtils.setAnalytics.restore();
});
it("sets user-level analytics preferences when passed disableAnalytics option", async function () {
sinon.stub(analyticsUtils, "setAnalytics").resolves();
await command.run({ disableAnalytics: true }, () => {});
let stubArg = analyticsUtils.setAnalytics.getCall(0).args[0];
assert.equal(stubArg, false);
analyticsUtils.setAnalytics.restore();
});
it("sets user-level configuration of enableAnalytics to true if passed true", function () {
analyticsUtils.setAnalytics(true);
assert.equal(
mockUserConfig.set.getCall(1).args[0].enableAnalytics,
true
);
});
it("sets user-level configuration of enableAnalytics to false if passed false", function () {
analyticsUtils.setAnalytics(false);
assert.equal(
mockUserConfig.set.getCall(0).args[0].enableAnalytics,
false
);
});
});
});
});
Loading

0 comments on commit cc509af

Please sign in to comment.