Skip to content

Commit 1617c6c

Browse files
GatsbyJS Botjamo
GatsbyJS Bot
andauthored
chore(telemetry): allow sharing tags in a file and read it only when things change (#28953) (#28992)
* chore(telemetry): allow sharing tags in a file and read it only when things change * Types (cherry picked from commit 9cb8eeb) Co-authored-by: Jarmo Isotalo <[email protected]>
1 parent c172848 commit 1617c6c

File tree

2 files changed

+143
-0
lines changed

2 files changed

+143
-0
lines changed

packages/gatsby-telemetry/src/__tests__/telemetry.ts

+119
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
jest.mock(`../event-storage`)
22
import { EventStorage } from "../event-storage"
33
import { AnalyticsTracker } from "../telemetry"
4+
import * as fs from "fs-extra"
5+
import * as os from "os"
6+
import * as path from "path"
7+
import uuidv4 from "uuid/v4"
48

59
let telemetry
610
beforeEach(() => {
@@ -57,4 +61,119 @@ describe(`Telemetry`, () => {
5761
)
5862
})
5963
})
64+
65+
describe(`allows reading tags from path`, () => {
66+
it(`getTagsFromPath should read the file and detect updates`, async () => {
67+
const t = new AnalyticsTracker({
68+
componentId: `component`,
69+
})
70+
71+
// Test it when env not set
72+
let res = t.getTagsFromPath()
73+
expect(res).toMatchObject({})
74+
expect(t.lastEnvTagsFromFileTime).toBe(0)
75+
76+
// create file and write initial data
77+
const filePath = path.join(fs.realpathSync(os.tmpdir()), uuidv4())
78+
console.log(filePath)
79+
process.env.GATSBY_TELEMETRY_METADATA_PATH = filePath
80+
81+
fs.writeFileSync(filePath, JSON.stringify({ componentId: `test` }))
82+
await new Promise(resolve => {
83+
setTimeout(resolve, 2000)
84+
})
85+
// get it and make sure we see it and the ts matches
86+
res = t.getTagsFromPath()
87+
expect(res).toMatchObject({ componentId: `test` })
88+
let stat = fs.statSync(filePath)
89+
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
90+
91+
// Update the file
92+
fs.writeFileSync(filePath, JSON.stringify({ componentId: `test2` }))
93+
94+
await new Promise(resolve => {
95+
setTimeout(resolve, 2000)
96+
})
97+
stat = fs.statSync(filePath)
98+
// make sure we see the change
99+
res = t.getTagsFromPath()
100+
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
101+
expect(res).toMatchObject({ componentId: `test2` })
102+
103+
// read it with out updating
104+
res = t.getTagsFromPath()
105+
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
106+
expect(res).toMatchObject({ componentId: `test2` })
107+
fs.unlinkSync(filePath)
108+
109+
const filePath2 = path.join(fs.realpathSync(os.tmpdir()), uuidv4())
110+
process.env.GATSBY_TELEMETRY_METADATA_PATH = filePath2
111+
res = t.getTagsFromPath()
112+
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
113+
expect(res).toMatchObject({})
114+
}, 10000)
115+
})
116+
117+
it(`getTagsFromPath is used for buildEvent`, async () => {
118+
const t = new AnalyticsTracker({
119+
componentId: `component`,
120+
})
121+
t.buildAndStoreEvent(`demo`, {})
122+
expect(
123+
(EventStorage as jest.Mock).mock.instances[1].addEvent
124+
).toHaveBeenCalledWith(
125+
expect.objectContaining({
126+
eventType: `demo`,
127+
componentId: `component`,
128+
})
129+
)
130+
const filePath = path.join(fs.realpathSync(os.tmpdir()), uuidv4())
131+
process.env.GATSBY_TELEMETRY_METADATA_PATH = filePath
132+
fs.writeFileSync(filePath, JSON.stringify({ componentId: `test` }))
133+
await new Promise(resolve => {
134+
setTimeout(resolve, 2000)
135+
})
136+
const stat = fs.statSync(filePath)
137+
t.buildAndStoreEvent(`demo2`, {})
138+
139+
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
140+
expect(
141+
(EventStorage as jest.Mock).mock.instances[1].addEvent
142+
).toHaveBeenCalledWith(
143+
expect.objectContaining({
144+
eventType: `demo2`,
145+
componentId: `test`,
146+
})
147+
)
148+
149+
t.buildAndStoreEvent(`demo3`, {})
150+
expect(
151+
(EventStorage as jest.Mock).mock.instances[1].addEvent
152+
).toHaveBeenCalledWith(
153+
expect.objectContaining({
154+
eventType: `demo3`,
155+
componentId: `test`,
156+
})
157+
)
158+
159+
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
160+
161+
fs.writeFileSync(filePath, JSON.stringify({ componentId: `4` }))
162+
await new Promise(resolve => {
163+
setTimeout(resolve, 2000)
164+
})
165+
const stat2 = fs.statSync(filePath)
166+
167+
t.buildAndStoreEvent(`demo4`, {})
168+
expect(t.lastEnvTagsFromFileTime).toBe(stat2.mtimeMs)
169+
expect(
170+
(EventStorage as jest.Mock).mock.instances[1].addEvent
171+
).toHaveBeenCalledWith(
172+
expect.objectContaining({
173+
eventType: `demo4`,
174+
componentId: `4`,
175+
})
176+
)
177+
fs.unlinkSync(filePath)
178+
}, 10000)
60179
})

packages/gatsby-telemetry/src/telemetry.ts

+24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import uuidv4 from "uuid/v4"
2+
import * as fs from "fs-extra"
23
import os from "os"
34
import {
45
isCI,
@@ -136,6 +137,8 @@ export class AnalyticsTracker {
136137
features = new Set<string>()
137138
machineId: string
138139
siteHash?: string = createContentDigest(process.cwd())
140+
lastEnvTagsFromFileTime = 0
141+
lastEnvTagsFromFileValue: ITelemetryTagsPayload = {}
139142

140143
constructor({
141144
componentId,
@@ -347,6 +350,7 @@ export class AnalyticsTracker {
347350
dbEngine,
348351
features: Array.from(this.features),
349352
...this.getRepositoryId(),
353+
...this.getTagsFromPath(),
350354
}
351355
this.store.addEvent(event)
352356
if (this.isFinalEvent(eventType)) {
@@ -356,6 +360,26 @@ export class AnalyticsTracker {
356360
}
357361
}
358362

363+
getTagsFromPath(): ITelemetryTagsPayload {
364+
const path = process.env.GATSBY_TELEMETRY_METADATA_PATH
365+
366+
if (!path) {
367+
return {}
368+
}
369+
try {
370+
const stat = fs.statSync(path)
371+
if (this.lastEnvTagsFromFileTime < stat.mtimeMs) {
372+
this.lastEnvTagsFromFileTime = stat.mtimeMs
373+
const data = fs.readFileSync(path, `utf8`)
374+
this.lastEnvTagsFromFileValue = JSON.parse(data)
375+
}
376+
} catch (e) {
377+
// nop
378+
return {}
379+
}
380+
return this.lastEnvTagsFromFileValue
381+
}
382+
359383
getIsTTY(): boolean {
360384
return Boolean(process.stdout?.isTTY)
361385
}

0 commit comments

Comments
 (0)