Skip to content

Commit

Permalink
chore(telemetry): allow sharing tags in a file and read it only when …
Browse files Browse the repository at this point in the history
…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]>
  • Loading branch information
GatsbyJS Bot and jamo authored Jan 13, 2021
1 parent c172848 commit 1617c6c
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 0 deletions.
119 changes: 119 additions & 0 deletions packages/gatsby-telemetry/src/__tests__/telemetry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
jest.mock(`../event-storage`)
import { EventStorage } from "../event-storage"
import { AnalyticsTracker } from "../telemetry"
import * as fs from "fs-extra"
import * as os from "os"
import * as path from "path"
import uuidv4 from "uuid/v4"

let telemetry
beforeEach(() => {
Expand Down Expand Up @@ -57,4 +61,119 @@ describe(`Telemetry`, () => {
)
})
})

describe(`allows reading tags from path`, () => {
it(`getTagsFromPath should read the file and detect updates`, async () => {
const t = new AnalyticsTracker({
componentId: `component`,
})

// Test it when env not set
let res = t.getTagsFromPath()
expect(res).toMatchObject({})
expect(t.lastEnvTagsFromFileTime).toBe(0)

// create file and write initial data
const filePath = path.join(fs.realpathSync(os.tmpdir()), uuidv4())
console.log(filePath)
process.env.GATSBY_TELEMETRY_METADATA_PATH = filePath

fs.writeFileSync(filePath, JSON.stringify({ componentId: `test` }))
await new Promise(resolve => {
setTimeout(resolve, 2000)
})
// get it and make sure we see it and the ts matches
res = t.getTagsFromPath()
expect(res).toMatchObject({ componentId: `test` })
let stat = fs.statSync(filePath)
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)

// Update the file
fs.writeFileSync(filePath, JSON.stringify({ componentId: `test2` }))

await new Promise(resolve => {
setTimeout(resolve, 2000)
})
stat = fs.statSync(filePath)
// make sure we see the change
res = t.getTagsFromPath()
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
expect(res).toMatchObject({ componentId: `test2` })

// read it with out updating
res = t.getTagsFromPath()
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
expect(res).toMatchObject({ componentId: `test2` })
fs.unlinkSync(filePath)

const filePath2 = path.join(fs.realpathSync(os.tmpdir()), uuidv4())
process.env.GATSBY_TELEMETRY_METADATA_PATH = filePath2
res = t.getTagsFromPath()
expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
expect(res).toMatchObject({})
}, 10000)
})

it(`getTagsFromPath is used for buildEvent`, async () => {
const t = new AnalyticsTracker({
componentId: `component`,
})
t.buildAndStoreEvent(`demo`, {})
expect(
(EventStorage as jest.Mock).mock.instances[1].addEvent
).toHaveBeenCalledWith(
expect.objectContaining({
eventType: `demo`,
componentId: `component`,
})
)
const filePath = path.join(fs.realpathSync(os.tmpdir()), uuidv4())
process.env.GATSBY_TELEMETRY_METADATA_PATH = filePath
fs.writeFileSync(filePath, JSON.stringify({ componentId: `test` }))
await new Promise(resolve => {
setTimeout(resolve, 2000)
})
const stat = fs.statSync(filePath)
t.buildAndStoreEvent(`demo2`, {})

expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)
expect(
(EventStorage as jest.Mock).mock.instances[1].addEvent
).toHaveBeenCalledWith(
expect.objectContaining({
eventType: `demo2`,
componentId: `test`,
})
)

t.buildAndStoreEvent(`demo3`, {})
expect(
(EventStorage as jest.Mock).mock.instances[1].addEvent
).toHaveBeenCalledWith(
expect.objectContaining({
eventType: `demo3`,
componentId: `test`,
})
)

expect(t.lastEnvTagsFromFileTime).toBe(stat.mtimeMs)

fs.writeFileSync(filePath, JSON.stringify({ componentId: `4` }))
await new Promise(resolve => {
setTimeout(resolve, 2000)
})
const stat2 = fs.statSync(filePath)

t.buildAndStoreEvent(`demo4`, {})
expect(t.lastEnvTagsFromFileTime).toBe(stat2.mtimeMs)
expect(
(EventStorage as jest.Mock).mock.instances[1].addEvent
).toHaveBeenCalledWith(
expect.objectContaining({
eventType: `demo4`,
componentId: `4`,
})
)
fs.unlinkSync(filePath)
}, 10000)
})
24 changes: 24 additions & 0 deletions packages/gatsby-telemetry/src/telemetry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import uuidv4 from "uuid/v4"
import * as fs from "fs-extra"
import os from "os"
import {
isCI,
Expand Down Expand Up @@ -136,6 +137,8 @@ export class AnalyticsTracker {
features = new Set<string>()
machineId: string
siteHash?: string = createContentDigest(process.cwd())
lastEnvTagsFromFileTime = 0
lastEnvTagsFromFileValue: ITelemetryTagsPayload = {}

constructor({
componentId,
Expand Down Expand Up @@ -347,6 +350,7 @@ export class AnalyticsTracker {
dbEngine,
features: Array.from(this.features),
...this.getRepositoryId(),
...this.getTagsFromPath(),
}
this.store.addEvent(event)
if (this.isFinalEvent(eventType)) {
Expand All @@ -356,6 +360,26 @@ export class AnalyticsTracker {
}
}

getTagsFromPath(): ITelemetryTagsPayload {
const path = process.env.GATSBY_TELEMETRY_METADATA_PATH

if (!path) {
return {}
}
try {
const stat = fs.statSync(path)
if (this.lastEnvTagsFromFileTime < stat.mtimeMs) {
this.lastEnvTagsFromFileTime = stat.mtimeMs
const data = fs.readFileSync(path, `utf8`)
this.lastEnvTagsFromFileValue = JSON.parse(data)
}
} catch (e) {
// nop
return {}
}
return this.lastEnvTagsFromFileValue
}

getIsTTY(): boolean {
return Boolean(process.stdout?.isTTY)
}
Expand Down

0 comments on commit 1617c6c

Please sign in to comment.