feat(analytics): add mixpanel
This commit is contained in:
parent
2c1b512e40
commit
893d6176c3
10 changed files with 83 additions and 1 deletions
30
.pnp.cjs
generated
30
.pnp.cjs
generated
|
@ -2715,6 +2715,7 @@ const RAW_RUNTIME_STATE =
|
||||||
["@standardnotes/time", "workspace:packages/time"],\
|
["@standardnotes/time", "workspace:packages/time"],\
|
||||||
["@types/ioredis", "npm:5.0.0"],\
|
["@types/ioredis", "npm:5.0.0"],\
|
||||||
["@types/jest", "npm:29.1.1"],\
|
["@types/jest", "npm:29.1.1"],\
|
||||||
|
["@types/mixpanel", "npm:2.14.4"],\
|
||||||
["@types/newrelic", "npm:7.0.4"],\
|
["@types/newrelic", "npm:7.0.4"],\
|
||||||
["@types/node", "npm:18.11.9"],\
|
["@types/node", "npm:18.11.9"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.30.5"],\
|
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.30.5"],\
|
||||||
|
@ -2726,6 +2727,7 @@ const RAW_RUNTIME_STATE =
|
||||||
["inversify", "npm:6.0.1"],\
|
["inversify", "npm:6.0.1"],\
|
||||||
["ioredis", "npm:5.2.4"],\
|
["ioredis", "npm:5.2.4"],\
|
||||||
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
||||||
|
["mixpanel", "npm:0.17.0"],\
|
||||||
["mysql2", "npm:2.3.3"],\
|
["mysql2", "npm:2.3.3"],\
|
||||||
["newrelic", "npm:9.6.0"],\
|
["newrelic", "npm:9.6.0"],\
|
||||||
["reflect-metadata", "npm:0.1.13"],\
|
["reflect-metadata", "npm:0.1.13"],\
|
||||||
|
@ -3899,6 +3901,15 @@ const RAW_RUNTIME_STATE =
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["@types/mixpanel", [\
|
||||||
|
["npm:2.14.4", {\
|
||||||
|
"packageLocation": "./.yarn/cache/@types-mixpanel-npm-2.14.4-34bd98306f-a2bf6e633e.zip/node_modules/@types/mixpanel/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["@types/mixpanel", "npm:2.14.4"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["@types/newrelic", [\
|
["@types/newrelic", [\
|
||||||
["npm:7.0.4", {\
|
["npm:7.0.4", {\
|
||||||
"packageLocation": "./.yarn/cache/@types-newrelic-npm-7.0.4-4f0b179b51-b44215b3ab.zip/node_modules/@types/newrelic/",\
|
"packageLocation": "./.yarn/cache/@types-newrelic-npm-7.0.4-4f0b179b51-b44215b3ab.zip/node_modules/@types/newrelic/",\
|
||||||
|
@ -8349,6 +8360,15 @@ const RAW_RUNTIME_STATE =
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
["https-proxy-agent", [\
|
["https-proxy-agent", [\
|
||||||
|
["npm:5.0.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/https-proxy-agent-npm-5.0.0-bb777903c3-77d11b0e2c.zip/node_modules/https-proxy-agent/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["https-proxy-agent", "npm:5.0.0"],\
|
||||||
|
["agent-base", "npm:6.0.2"],\
|
||||||
|
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
["npm:5.0.1", {\
|
["npm:5.0.1", {\
|
||||||
"packageLocation": "./.yarn/cache/https-proxy-agent-npm-5.0.1-42d65f358e-8e767faec9.zip/node_modules/https-proxy-agent/",\
|
"packageLocation": "./.yarn/cache/https-proxy-agent-npm-5.0.1-42d65f358e-8e767faec9.zip/node_modules/https-proxy-agent/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
|
@ -10636,6 +10656,16 @@ const RAW_RUNTIME_STATE =
|
||||||
"linkType": "HARD"\
|
"linkType": "HARD"\
|
||||||
}]\
|
}]\
|
||||||
]],\
|
]],\
|
||||||
|
["mixpanel", [\
|
||||||
|
["npm:0.17.0", {\
|
||||||
|
"packageLocation": "./.yarn/cache/mixpanel-npm-0.17.0-3073ce9949-5a945bdbdd.zip/node_modules/mixpanel/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["mixpanel", "npm:0.17.0"],\
|
||||||
|
["https-proxy-agent", "npm:5.0.0"]\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}]\
|
||||||
|
]],\
|
||||||
["mkdirp", [\
|
["mkdirp", [\
|
||||||
["npm:1.0.4", {\
|
["npm:1.0.4", {\
|
||||||
"packageLocation": "./.yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-1233611198.zip/node_modules/mkdirp/",\
|
"packageLocation": "./.yarn/cache/mkdirp-npm-1.0.4-37f6ef56b9-1233611198.zip/node_modules/mkdirp/",\
|
||||||
|
|
BIN
.yarn/cache/@types-mixpanel-npm-2.14.4-34bd98306f-a2bf6e633e.zip
vendored
Normal file
BIN
.yarn/cache/@types-mixpanel-npm-2.14.4-34bd98306f-a2bf6e633e.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/https-proxy-agent-npm-5.0.0-bb777903c3-77d11b0e2c.zip
vendored
Normal file
BIN
.yarn/cache/https-proxy-agent-npm-5.0.0-bb777903c3-77d11b0e2c.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/mixpanel-npm-0.17.0-3073ce9949-5a945bdbdd.zip
vendored
Normal file
BIN
.yarn/cache/mixpanel-npm-0.17.0-3073ce9949-5a945bdbdd.zip
vendored
Normal file
Binary file not shown.
|
@ -10,6 +10,8 @@ DB_DATABASE=analytics
|
||||||
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
|
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
|
||||||
DB_MIGRATIONS_PATH=dist/migrations/*.js
|
DB_MIGRATIONS_PATH=dist/migrations/*.js
|
||||||
|
|
||||||
|
ADMIN_EMAILS=test@standardnotes.com
|
||||||
|
|
||||||
REDIS_URL=redis://cache
|
REDIS_URL=redis://cache
|
||||||
REDIS_EVENTS_CHANNEL=events
|
REDIS_EVENTS_CHANNEL=events
|
||||||
|
|
||||||
|
@ -26,3 +28,6 @@ NEW_RELIC_NO_CONFIG_FILE=true
|
||||||
NEW_RELIC_DISTRIBUTED_TRACING_ENABLED=false
|
NEW_RELIC_DISTRIBUTED_TRACING_ENABLED=false
|
||||||
NEW_RELIC_LOG_ENABLED=false
|
NEW_RELIC_LOG_ENABLED=false
|
||||||
NEW_RELIC_LOG_LEVEL=info
|
NEW_RELIC_LOG_LEVEL=info
|
||||||
|
|
||||||
|
# (Optional) Mixpanel
|
||||||
|
MIXPANEL_TOKEN=
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ioredis": "^5.0.0",
|
"@types/ioredis": "^5.0.0",
|
||||||
"@types/jest": "^29.1.1",
|
"@types/jest": "^29.1.1",
|
||||||
|
"@types/mixpanel": "^2.14.4",
|
||||||
"@types/newrelic": "^7.0.4",
|
"@types/newrelic": "^7.0.4",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.9",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"inversify": "^6.0.1",
|
"inversify": "^6.0.1",
|
||||||
"ioredis": "^5.2.4",
|
"ioredis": "^5.2.4",
|
||||||
|
"mixpanel": "^0.17.0",
|
||||||
"mysql2": "^2.3.3",
|
"mysql2": "^2.3.3",
|
||||||
"newrelic": "^9.6.0",
|
"newrelic": "^9.6.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
|
|
|
@ -8,6 +8,8 @@ import {
|
||||||
DomainEventSubscriberFactoryInterface,
|
DomainEventSubscriberFactoryInterface,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { MapperInterface } from '@standardnotes/domain-core'
|
import { MapperInterface } from '@standardnotes/domain-core'
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const Mixpanel = require('mixpanel')
|
||||||
|
|
||||||
import { Env } from './Env'
|
import { Env } from './Env'
|
||||||
import TYPES from './Types'
|
import TYPES from './Types'
|
||||||
|
@ -134,6 +136,7 @@ export class ContainerConfigLoader {
|
||||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||||
container.bind(TYPES.ADMIN_EMAILS).toConstantValue(env.get('ADMIN_EMAILS').split(','))
|
container.bind(TYPES.ADMIN_EMAILS).toConstantValue(env.get('ADMIN_EMAILS').split(','))
|
||||||
|
container.bind(TYPES.MIXPANEL_TOKEN).toConstantValue(env.get('MIXPANEL_TOKEN', true))
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
container.bind<DomainEventFactory>(TYPES.DomainEventFactory).to(DomainEventFactory)
|
container.bind<DomainEventFactory>(TYPES.DomainEventFactory).to(DomainEventFactory)
|
||||||
|
@ -157,6 +160,9 @@ export class ContainerConfigLoader {
|
||||||
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
if (env.get('MIXPANEL_TOKEN', true)) {
|
||||||
|
container.bind<Mixpanel>(TYPES.MixpanelClient).toConstantValue(Mixpanel.init(env.get('MIXPANEL_TOKEN', true)))
|
||||||
|
}
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
container
|
container
|
||||||
|
|
|
@ -12,6 +12,7 @@ const TYPES = {
|
||||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||||
ADMIN_EMAILS: Symbol.for('ADMIN_EMAILS'),
|
ADMIN_EMAILS: Symbol.for('ADMIN_EMAILS'),
|
||||||
|
MIXPANEL_TOKEN: Symbol.for('MIXPANEL_TOKEN'),
|
||||||
// Repositories
|
// Repositories
|
||||||
AnalyticsEntityRepository: Symbol.for('AnalyticsEntityRepository'),
|
AnalyticsEntityRepository: Symbol.for('AnalyticsEntityRepository'),
|
||||||
RevenueModificationRepository: Symbol.for('RevenueModificationRepository'),
|
RevenueModificationRepository: Symbol.for('RevenueModificationRepository'),
|
||||||
|
@ -48,6 +49,7 @@ const TYPES = {
|
||||||
StatisticsStore: Symbol.for('StatisticsStore'),
|
StatisticsStore: Symbol.for('StatisticsStore'),
|
||||||
Timer: Symbol.for('Timer'),
|
Timer: Symbol.for('Timer'),
|
||||||
PeriodKeyGenerator: Symbol.for('PeriodKeyGenerator'),
|
PeriodKeyGenerator: Symbol.for('PeriodKeyGenerator'),
|
||||||
|
MixpanelClient: Symbol.for('MixpanelClient'),
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TYPES
|
export default TYPES
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { DomainEventHandlerInterface, UserRegisteredEvent } from '@standardnotes/domain-events'
|
import { DomainEventHandlerInterface, UserRegisteredEvent } from '@standardnotes/domain-events'
|
||||||
import { inject, injectable } from 'inversify'
|
import { inject, injectable, optional } from 'inversify'
|
||||||
|
import { Mixpanel } from 'mixpanel'
|
||||||
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
|
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
|
||||||
|
@ -13,6 +14,7 @@ export class UserRegisteredEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.AnalyticsEntityRepository) private analyticsEntityRepository: AnalyticsEntityRepositoryInterface,
|
@inject(TYPES.AnalyticsEntityRepository) private analyticsEntityRepository: AnalyticsEntityRepositoryInterface,
|
||||||
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
|
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
|
||||||
|
@inject(TYPES.MixpanelClient) @optional() private mixpanelClient: Mixpanel | null,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: UserRegisteredEvent): Promise<void> {
|
async handle(event: UserRegisteredEvent): Promise<void> {
|
||||||
|
@ -26,5 +28,12 @@ export class UserRegisteredEventHandler implements DomainEventHandlerInterface {
|
||||||
Period.ThisWeek,
|
Period.ThisWeek,
|
||||||
Period.ThisMonth,
|
Period.ThisMonth,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
if (this.mixpanelClient !== null) {
|
||||||
|
this.mixpanelClient.track(event.type, {
|
||||||
|
distinct_id: analyticsEntity.id,
|
||||||
|
protocol_version: event.payload.protocolVersion,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
yarn.lock
28
yarn.lock
|
@ -1963,6 +1963,7 @@ __metadata:
|
||||||
"@standardnotes/time": "workspace:*"
|
"@standardnotes/time": "workspace:*"
|
||||||
"@types/ioredis": "npm:^5.0.0"
|
"@types/ioredis": "npm:^5.0.0"
|
||||||
"@types/jest": "npm:^29.1.1"
|
"@types/jest": "npm:^29.1.1"
|
||||||
|
"@types/mixpanel": "npm:^2.14.4"
|
||||||
"@types/newrelic": "npm:^7.0.4"
|
"@types/newrelic": "npm:^7.0.4"
|
||||||
"@types/node": "npm:^18.11.9"
|
"@types/node": "npm:^18.11.9"
|
||||||
"@typescript-eslint/eslint-plugin": "npm:^5.30.0"
|
"@typescript-eslint/eslint-plugin": "npm:^5.30.0"
|
||||||
|
@ -1974,6 +1975,7 @@ __metadata:
|
||||||
inversify: "npm:^6.0.1"
|
inversify: "npm:^6.0.1"
|
||||||
ioredis: "npm:^5.2.4"
|
ioredis: "npm:^5.2.4"
|
||||||
jest: "npm:^29.1.2"
|
jest: "npm:^29.1.2"
|
||||||
|
mixpanel: "npm:^0.17.0"
|
||||||
mysql2: "npm:^2.3.3"
|
mysql2: "npm:^2.3.3"
|
||||||
newrelic: "npm:^9.6.0"
|
newrelic: "npm:^9.6.0"
|
||||||
reflect-metadata: "npm:^0.1.13"
|
reflect-metadata: "npm:^0.1.13"
|
||||||
|
@ -3049,6 +3051,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/mixpanel@npm:^2.14.4":
|
||||||
|
version: 2.14.4
|
||||||
|
resolution: "@types/mixpanel@npm:2.14.4"
|
||||||
|
checksum: a2bf6e633e5c88dfade72e07a190fe760d3b7ac1308d148b56ab4b350aee5c2b75912c21b534551d3cbb4b078b2ac3e8c787e3eff9f667567a5b5c7091821558
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/newrelic@npm:^7.0.4":
|
"@types/newrelic@npm:^7.0.4":
|
||||||
version: 7.0.4
|
version: 7.0.4
|
||||||
resolution: "@types/newrelic@npm:7.0.4"
|
resolution: "@types/newrelic@npm:7.0.4"
|
||||||
|
@ -6547,6 +6556,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"https-proxy-agent@npm:5.0.0":
|
||||||
|
version: 5.0.0
|
||||||
|
resolution: "https-proxy-agent@npm:5.0.0"
|
||||||
|
dependencies:
|
||||||
|
agent-base: "npm:6"
|
||||||
|
debug: "npm:4"
|
||||||
|
checksum: 77d11b0e2c164d1f63f689247551b821b67c3daa7f13fe2d0445989d9ad224f67f2af8ebda09599de3f4be490b343c82bb37024d8a669c004fd4f38dc12a4d23
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"https-proxy-agent@npm:^5.0.0":
|
"https-proxy-agent@npm:^5.0.0":
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
resolution: "https-proxy-agent@npm:5.0.1"
|
resolution: "https-proxy-agent@npm:5.0.1"
|
||||||
|
@ -8530,6 +8549,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"mixpanel@npm:^0.17.0":
|
||||||
|
version: 0.17.0
|
||||||
|
resolution: "mixpanel@npm:0.17.0"
|
||||||
|
dependencies:
|
||||||
|
https-proxy-agent: "npm:5.0.0"
|
||||||
|
checksum: 5a945bdbdd6093f7f4dda66b0e0ae2aa081bce4627c9a367b00b7f52a5daeae0031a579850117fd603112555160f56fb50e75afa6af8598b61a806bd8dd3f0e8
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4":
|
"mkdirp@npm:^1.0.3, mkdirp@npm:^1.0.4":
|
||||||
version: 1.0.4
|
version: 1.0.4
|
||||||
resolution: "mkdirp@npm:1.0.4"
|
resolution: "mkdirp@npm:1.0.4"
|
||||||
|
|
Loading…
Reference in a new issue