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

replace google analytics with mixpanel #6132

Merged
merged 6 commits into from
Jul 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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