fix(mixpanel): Critical fix for mixpanel users all having the same distinct_id alias

Summary: Mixpanel API misuse makes me sad.

Test Plan: No tests, but easy to check with Mixpanel.com

Reviewers: dillon, evan

Reviewed By: dillon, evan

Differential Revision: https://phab.nylas.com/D1978
This commit is contained in:
Ben Gotow 2015-09-03 19:30:08 -07:00
parent 2aebd5f43b
commit 1daeaff367
2 changed files with 58 additions and 67 deletions

View file

@ -13,17 +13,17 @@
}, },
"electronVersion": "0.29.2", "electronVersion": "0.29.2",
"dependencies": { "dependencies": {
"asar": "^0.5.0",
"6to5-core": "^3.5", "6to5-core": "^3.5",
"asar": "^0.5.0",
"async": "^0.9", "async": "^0.9",
"atom-keymap": "^5.1", "atom-keymap": "^5.1",
"aws-sdk": "2.1.28", "aws-sdk": "2.1.28",
"bluebird": "^2.9", "bluebird": "^2.9",
"classnames": "1.2.1",
"clear-cut": "0.4.0", "clear-cut": "0.4.0",
"coffee-react": "^2.0.0", "coffee-react": "^2.0.0",
"coffee-script": "1.9.0", "coffee-script": "1.9.0",
"coffeestack": "^1.1", "coffeestack": "^1.1",
"classnames": "1.2.1",
"color": "^0.7.3", "color": "^0.7.3",
"delegato": "^1", "delegato": "^1",
"emissary": "^1.3.1", "emissary": "^1.3.1",
@ -41,8 +41,8 @@
"juice": "^1.4", "juice": "^1.4",
"less-cache": "0.21", "less-cache": "0.21",
"marked": "^0.3", "marked": "^0.3",
"mixpanel": "0.0.20",
"mkdirp": "^0.5", "mkdirp": "^0.5",
"mixpanel": "^0.0.20",
"moment": "^2.8", "moment": "^2.8",
"moment-timezone": "^0.3", "moment-timezone": "^0.3",
"nslog": "^2.0.0", "nslog": "^2.0.0",
@ -52,8 +52,8 @@
"q": "^1.0.1", "q": "^1.0.1",
"raven": "0.7.2", "raven": "0.7.2",
"react": "^0.13.2", "react": "^0.13.2",
"react-hot-api": "0.4.5",
"react-atom-fork": "^0.11.5", "react-atom-fork": "^0.11.5",
"react-hot-api": "0.4.5",
"reactionary-atom-fork": "^1.0.0", "reactionary-atom-fork": "^1.0.0",
"reflux": "0.1.13", "reflux": "0.1.13",
"request": "^2.53", "request": "^2.53",
@ -81,8 +81,7 @@
"proxyquire": "git+https://github.com/bengotow/proxyquire", "proxyquire": "git+https://github.com/bengotow/proxyquire",
"jasmine-react-helpers": "^0.2" "jasmine-react-helpers": "^0.2"
}, },
"packageDependencies": { "packageDependencies": {},
},
"private": true, "private": true,
"scripts": { "scripts": {
"preinstall": "node -e 'process.exit(0)'" "preinstall": "node -e 'process.exit(0)'"

View file

@ -7,35 +7,6 @@ AccountStore = require './account-store'
printToConsole = false printToConsole = false
module.exports =
AnalyticsStore = Reflux.createStore
init: ->
@listenAndTrack = (dispatcher=Actions) => (callback, action) =>
@listenTo dispatcher[action], (args...) =>
@track(action, callback(args...))
@analytics = Mixpanel.init("625e2300ef07cb4eb70a69b3638ca579")
@listenTo AccountStore, => @identify()
@identify()
@_listenToCoreActions()
@_setupGlobalPackageActions()
addPackageActions: (listeners, dispatcher=Actions) ->
_.each listeners, @listenAndTrack(dispatcher)
addGlobalPackageActions: (listeners) ->
@_globalPackageActions = _.extend @_globalPackageActions, listeners
_setupGlobalPackageActions: ->
@_globalPackageActions = {}
@listenTo Actions.sendToAllWindows, (actionData={}) =>
return unless atom.isMainWindow()
callback = @_globalPackageActions[actionData.action]
if callback?
@track(actionData.action, callback(actionData))
# We white list actions to track. # We white list actions to track.
# #
# The Key is the action and the value is the callback function for that # The Key is the action and the value is the callback function for that
@ -47,47 +18,68 @@ AnalyticsStore = Reflux.createStore
# #
# Only completely anonymous data essential to future metrics or # Only completely anonymous data essential to future metrics or
# debugging may be sent. # debugging may be sent.
coreWindowActions: -> coreWindowActions =
showDeveloperConsole: -> {} showDeveloperConsole: -> {}
composeReply: ({threadId, messageId}) -> {threadId, messageId} composeReply: -> ['Compose Draft', {'type': 'reply'}]
composeForward: ({threadId, messageId}) -> {threadId, messageId} composeForward: -> ['Compose Draft', {'type': 'forward'}]
composeReplyAll: ({threadId, messageId}) -> {threadId, messageId} composeReplyAll: -> ['Compose Draft', {'type': 'reply-all'}]
composePopoutDraft: (draftClientId) -> {draftClientId: draftClientId} composeNewBlankDraft: -> ['Compose Draft', {'type': 'blank'}]
composeNewBlankDraft: -> {} composePopoutDraft: -> ['Popout Draft', {}]
sendDraft: (draftClientId) -> {draftClientId} sendDraft: -> ['Send Draft', {}]
destroyDraft: (draftClientId) -> {draftClientId} destroyDraft: -> ['Delete Draft', {}]
searchQueryCommitted: (query) -> {} searchQueryCommitted: (query) -> ['Commit Search Query', {}]
fetchAndOpenFile: -> {} attachFile: -> ['Attach File', {}]
fetchAndSaveFile: -> {} attachFilePath: -> ['Attach File Path', {}]
abortFetchFile: -> {} fetchAndOpenFile: -> ['Download and Open File', {}]
fileDownloaded: -> {} fetchAndSaveFile: -> ['Download and Save File', {}]
abortFetchFile: -> ['Cancel Download', {}]
fileDownloaded: -> ['Download Complete', {}]
coreGlobalActions: -> module.exports =
fileAborted: (uploadData={}) -> {fileSize: uploadData.fileSize} AnalyticsStore = Reflux.createStore
fileUploaded: (uploadData={}) -> {fileSize: uploadData.fileSize}
sendDraftSuccess: ({draftClientId}) -> {draftClientId}
track: (action, data={}) -> init: ->
@analytics = Mixpanel.init("9a2137b80c098b3d594e39b776ebe085")
@listenTo AccountStore, => @identify()
@identify()
@trackActions(Actions, coreWindowActions)
@trackTasks()
trackActions: (dispatcher, listeners) ->
_.each listeners, (mappingFunction, actionName) =>
@listenTo dispatcher[actionName], (args...) =>
[eventName, eventArgs] = mappingFunction(args...)
@track(eventName, eventArgs)
trackTasks: ->
@listenTo Actions.queueTask, (task) =>
return unless task
eventName = task.constructor.name
eventArgs = {}
eventArgs['item_count'] = task.messages.length if task.messages?
eventArgs['item_count'] = task.threads.length if task.threads?
@track(eventName, eventArgs)
track: (eventName, eventArgs={}) ->
_.defer => _.defer =>
# send to the analytics service # send to the analytics service
@analytics.track(action, _.extend(data, { @analytics.track(eventName, _.extend(eventArgs, {
accountId: AccountStore.current()?.id platform: process.platform
version: atom.getVersion()
distinct_id: AccountStore.current()?.id distinct_id: AccountStore.current()?.id
accountId: AccountStore.current()?.id
})) }))
# send to the logs that we ship to LogStash # send to the logs that we ship to LogStash
console.debug(printToConsole, {action, data}) console.debug(printToConsole, {eventName, eventArgs})
identify: -> identify: ->
account = AccountStore.current() account = AccountStore.current()
if account if account
@analytics.alias("distinct_id", account.id) @analytics.people.set(account.id, {
@analytics.people.set account.id,
"$email": account.me().email "$email": account.me().email
"$first_name": account.me().firstName() "$first_name": account.me().firstName()
"$last_name": account.me().lastName() "$last_name": account.me().lastName()
"accountId": account.id "accountId": account.id
})
_listenToCoreActions: ->
_.each @coreWindowActions(), @listenAndTrack()
_.each @coreGlobalActions(), @listenAndTrack() if atom.isMainWindow()