Skip to content

Commit 6221056

Browse files
authored
chore: switch telemetry provider (#986)
* chore: switch telemetry * chore: ensure telemetry optout is working * chore: use proper api keys * Fix a typo
1 parent 68b01ec commit 6221056

File tree

4 files changed

+94
-147
lines changed

4 files changed

+94
-147
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"test:update": "cross-env CHAI_JEST_SNAPSHOT_UPDATE_ALL=true nr test:unit"
4242
},
4343
"dependencies": {
44+
"@amplitude/analytics-node": "^1.3.3",
4445
"@babel/parser": "^7.15.3",
4546
"@babel/traverse": "^7.15.0",
4647
"bcp-47-normalize": "^2.0.1",
@@ -1365,5 +1366,6 @@
13651366
"hidden": true
13661367
}
13671368
]
1368-
}
1369+
},
1370+
"packageManager": "[email protected]"
13691371
}

src/core/Global.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,6 @@ export class Global {
379379
commands.executeCommand('setContext', 'i18n-ally.extract.autoDetect', Config.extractAutoDetect)
380380

381381
Telemetry.track(TelemetryKey.Enabled)
382-
Telemetry.updateUserProperties()
383382

384383
await this.initLoader(this._rootpath, reload)
385384
}

src/core/Telemetry.ts

Lines changed: 64 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import axios from 'axios'
2-
import { v4 as uuid } from 'uuid'
1+
import { randomUUID } from 'crypto'
2+
import * as amplitude from '@amplitude/analytics-node'
33
import { version } from '../../package.json'
44
import { Config } from './Config'
55
import { Log } from '~/utils'
@@ -8,10 +8,17 @@ import { Global } from '~/extension'
88
import { LocaleTreeItem, ProgressSubmenuItem } from '~/views'
99
import { CommandOptions } from '~/commands/manipulations/common'
1010

11-
const HEAP_ID_DEV = '1082064308'
12-
const HEAP_ID_PROD = '4118173713'
11+
const AMPLITUDE_API = isProd
12+
? '710028b04f0f9274085eec6885e94ceb' // Prod
13+
: '63d2a7eb46b66d43e0d20b0ba2834cc3' // Dev
1314

14-
const HEAP_ID = isProd ? HEAP_ID_PROD : HEAP_ID_DEV
15+
const AMPLITUDE_SERVER_ZONE = 'EU'
16+
17+
const AMPLITUDE_FLUSH_QUEUE_SIZE = 100
18+
19+
const AMPLITUDE_FLUSH_INTERVAL_MILLIS = isProd
20+
? 5 * 60 * 1000 // 5 minutes
21+
: 10 * 1000 // 10 seconds
1522

1623
export enum TelemetryKey {
1724
Activated = 'activated',
@@ -46,96 +53,28 @@ export enum ActionSource {
4653
Review = 'review'
4754
}
4855

49-
export interface TelemetryEvent {
50-
event: TelemetryKey
51-
timestamp: number
52-
identity: string
53-
properties?: Record<string, any>
54-
}
55-
5656
export class Telemetry {
57-
private static _id: string
58-
private static _timer: any = null
59-
60-
static events: TelemetryEvent[] = []
61-
62-
static get userId() {
63-
if (this._id)
64-
return this._id
65-
this._id = Config.ctx.globalState.get('i18n-ally.telemetry-user-id')!
66-
if (!this._id) {
67-
this._id = uuid()
68-
Config.ctx.globalState.update('i18n-ally.telemetry-user-id', this._id)
69-
}
70-
Log.info(`📈 Telemetry id: ${this._id}`)
71-
72-
return this._id
73-
}
74-
75-
static checkVersionChange() {
76-
const previousVersion = Config.ctx.globalState.get('i18n-ally.previous-version')
77-
78-
if (!previousVersion)
79-
Telemetry.track(TelemetryKey.Installed, { new_version: version })
80-
else if (previousVersion !== version)
81-
Telemetry.track(TelemetryKey.Updated, { new_version: version, previous_version: previousVersion })
82-
83-
Config.ctx.globalState.update('i18n-ally.previous-version', version)
84-
}
85-
86-
static get isEnabled() {
87-
return Config.telemetry && !isTest
88-
}
57+
private static _userProperties: object
58+
private static _amplitude: amplitude.Types.NodeClient
8959

9060
static async track(key: TelemetryKey, properties?: Record<string, any>, immediate = false) {
91-
if (!this.isEnabled)
61+
const isEnabled = Config.telemetry && !isTest
62+
if (!isEnabled)
9263
return
9364

94-
const event: TelemetryEvent = {
95-
event: key,
96-
identity: this.userId,
97-
timestamp: +new Date(),
98-
properties,
99-
}
65+
try {
66+
this._initializeAmplitude()
10067

101-
if (isDev)
102-
Log.info(`[telemetry] ${key}: ${JSON.stringify(properties)}`)
103-
104-
if (immediate) {
105-
try {
106-
await axios({
107-
url: 'https://heapanalytics.com/api/track',
108-
method: 'POST',
109-
headers: {
110-
'Content-Type': 'application/json',
111-
},
112-
data: {
113-
app_id: HEAP_ID,
114-
...event,
115-
},
116-
})
117-
}
118-
catch (e) {
119-
Log.error(e, false)
120-
}
121-
}
122-
else {
123-
this.events.push(event)
124-
this.schedule()
125-
}
126-
}
68+
this._amplitude.track(key, properties, this._getUserProperties())
69+
70+
if (immediate)
71+
this._amplitude.flush()
12772

128-
static schedule() {
129-
if (this.events.length >= 100) {
130-
this.sendBulk()
73+
if (isDev)
74+
Log.info(`[telemetry] ${key}: ${JSON.stringify(properties)}`)
13175
}
132-
else if (!this._timer && this.events.length) {
133-
this._timer = setInterval(
134-
() => this.sendBulk(),
135-
isDev
136-
? 10 * 1000 // 10 seconds
137-
: 5 * 60 * 1000, // 5 minutes
138-
)
76+
catch (e) {
77+
Log.error(e, false)
13978
}
14079
}
14180

@@ -145,73 +84,53 @@ export class Telemetry {
14584
: item?.actionSource || ActionSource.CommandPattele
14685
}
14786

148-
static async updateUserProperties() {
149-
if (!this.isEnabled)
87+
private static _initializeAmplitude() {
88+
if (this._amplitude)
15089
return
15190

152-
const data = {
153-
version,
154-
feature_auto_detection: !!Config.autoDetection,
155-
feature_annotation_in_place: !!Config.annotationInPlace,
156-
feature_annotations: !!Config.annotations,
157-
feature_disable_path_parsing: !!Config.disablePathParsing,
158-
feature_extract_auto_detect: !!Config.extractAutoDetect,
159-
feature_keep_fulfilled: !!Config.keepFulfilled,
160-
feature_prefer_editor: !!Config.preferEditor,
161-
feature_review_enabled: !!Config.reviewEnabled,
162-
feature_has_path_matcher: !!Config._pathMatcher,
163-
feature_has_custom_framework: !!Global.enabledFrameworks.find(i => i.id === 'custom'),
164-
}
91+
this._amplitude = amplitude.createInstance()
16592

166-
if (isDev)
167-
Log.info(`[telemetry] user: ${JSON.stringify(data)}`)
93+
this._amplitude.init(AMPLITUDE_API, {
94+
optOut: !Config.telemetry || isTest,
95+
serverZone: AMPLITUDE_SERVER_ZONE,
96+
flushQueueSize: AMPLITUDE_FLUSH_QUEUE_SIZE,
97+
flushIntervalMillis: AMPLITUDE_FLUSH_INTERVAL_MILLIS,
98+
})
16899

169-
try {
170-
await axios({
171-
url: 'https://heapanalytics.com/api/add_user_properties',
172-
method: 'POST',
173-
headers: {
174-
'Content-Type': 'application/json',
175-
},
176-
data: {
177-
app_id: HEAP_ID,
178-
identity: this.userId,
179-
properties: data,
180-
},
181-
})
182-
}
183-
catch (e) {
184-
Log.error(e, false)
185-
}
100+
this._amplitude.identify(new amplitude.Identify(), this._getUserProperties())
186101
}
187102

188-
static async sendBulk() {
189-
if (!this.events.length) {
190-
clearInterval(this._timer)
191-
this._timer = null
192-
return
103+
private static _getUserId() {
104+
let userId = Config.ctx.globalState.get('i18n-ally.telemetry-user-id') ?? ''
105+
if (!userId) {
106+
userId = randomUUID()
107+
Config.ctx.globalState.update('i18n-ally.telemetry-user-id', userId)
193108
}
109+
Log.info(`📈 Telemetry id: ${userId}`)
110+
return userId
111+
}
194112

195-
if (isDev)
196-
Log.info('[telemetry] sending bulk')
197-
198-
const events = Array.from(this.events)
199-
this.events.length = 0
200-
try {
201-
await axios({
202-
url: 'https://heapanalytics.com/api/track',
203-
method: 'POST',
204-
headers: {
205-
'Content-Type': 'application/json',
206-
},
207-
data: {
208-
app_id: HEAP_ID,
209-
events,
113+
private static _getUserProperties() {
114+
if (!this._userProperties) {
115+
this._userProperties = {
116+
user_id: this._getUserId(),
117+
app_version: version,
118+
user_properties: {
119+
feature_auto_detection: !!Config.autoDetection,
120+
feature_annotation_in_place: !!Config.annotationInPlace,
121+
feature_annotations: !!Config.annotations,
122+
feature_disable_path_parsing: !!Config.disablePathParsing,
123+
feature_extract_auto_detect: !!Config.extractAutoDetect,
124+
feature_keep_fulfilled: !!Config.keepFulfilled,
125+
feature_prefer_editor: !!Config.preferEditor,
126+
feature_review_enabled: !!Config.reviewEnabled,
127+
feature_has_path_matcher: !!Config._pathMatcher,
128+
feature_has_custom_framework: !!Global.enabledFrameworks.find(i => i.id === 'custom'),
129+
feature_frameworks: Global.enabledFrameworks.map(i => i.display),
210130
},
211-
})
212-
}
213-
catch (e) {
214-
Log.error(e, false)
131+
}
215132
}
133+
134+
return this._userProperties
216135
}
217136
}

yarn.lock

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,28 @@
22
# yarn lockfile v1
33

44

5+
"@amplitude/analytics-core@^1.2.3":
6+
version "1.2.3"
7+
resolved "https://registry.yarnpkg.com/@amplitude/analytics-core/-/analytics-core-1.2.3.tgz#ab7adbb07a18190d5cfad992962a430679575c98"
8+
integrity sha512-3WADE8IcxU7ZERMkBb0+JP7t6EekyFPM0djtNKXQaxgGgH3oqQzMmBCg19UnYYiBSHrZkpiMBLHNAvXL6HM7zg==
9+
dependencies:
10+
"@amplitude/analytics-types" "^1.3.3"
11+
tslib "^2.4.1"
12+
13+
"@amplitude/analytics-node@^1.3.3":
14+
version "1.3.3"
15+
resolved "https://registry.yarnpkg.com/@amplitude/analytics-node/-/analytics-node-1.3.3.tgz#cc91f3512caedd8d5f1d14f1a2bbe1541adb743c"
16+
integrity sha512-G+5EoGcVOOclcNRR57AQcGqg46xNXjG6tsSdF71+Npzc6zTfvDzKDY97ZULBju9TT/FXvhP8LnppAI8umT6qkQ==
17+
dependencies:
18+
"@amplitude/analytics-core" "^1.2.3"
19+
"@amplitude/analytics-types" "^1.3.3"
20+
tslib "^2.4.1"
21+
22+
"@amplitude/analytics-types@^1.3.3":
23+
version "1.3.3"
24+
resolved "https://registry.yarnpkg.com/@amplitude/analytics-types/-/analytics-types-1.3.3.tgz#c7b2a21e6ab0eb1670cce4d03127b62c373c6ed4"
25+
integrity sha512-V4/h+izhG7NyVfIva1uhe6bToI/l5n+UnEomL3KEO9DkFoKiOG7KmXo/fmzfU6UmD1bUEWmy//hUFF16BfrEww==
26+
527
"@antfu/eslint-config-basic@^0.7.0":
628
version "0.7.0"
729
resolved "https://registry.yarnpkg.com/@antfu/eslint-config-basic/-/eslint-config-basic-0.7.0.tgz#ad786cd27076d3f6b7c0df16af6cdc254139309c"
@@ -10670,6 +10692,11 @@ tslib@^2.0.3, tslib@^2.2.0:
1067010692
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
1067110693
integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
1067210694

10695+
tslib@^2.4.1:
10696+
version "2.6.2"
10697+
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
10698+
integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
10699+
1067310700
tsutils@^3.21.0:
1067410701
version "3.21.0"
1067510702
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"

0 commit comments

Comments
 (0)