UNPKG

2.69 kBJavaScriptView Raw
1const os = require(`os`)
2const path = require(`path`)
3const Store = require(`./store`)
4const fetch = require(`node-fetch`)
5const Configstore = require(`configstore`)
6const { ensureDirSync } = require(`fs-extra`)
7
8const isTruthy = require(`./is-truthy`)
9
10/* The events data collection is a spooled process that
11 * buffers events to a local fs based buffer
12 * which then is asynchronously flushed to the server.
13 * This both increases the fault tolerancy and allows collection
14 * to continue even when working offline.
15 */
16module.exports = class EventStorage {
17 analyticsApi =
18 process.env.GATSBY_TELEMETRY_API || `https://analytics.gatsbyjs.com/events`
19 constructor() {
20 try {
21 this.config = new Configstore(`gatsby`, {}, { globalConfigPath: true })
22 } catch (e) {
23 // This should never happen
24 this.config = {
25 get: key => this.config[key],
26 set: (key, value) => (this.config[key] = value),
27 all: this.config,
28 path: path.join(os.tmpdir(), `gatsby`),
29 "telemetry.enabled": true,
30 "telemetry.machineId": `not-a-machine-id`,
31 }
32 }
33
34 const baseDir = path.dirname(this.config.path)
35
36 try {
37 ensureDirSync(baseDir)
38 } catch (e) {
39 // TODO: Log this event
40 }
41
42 this.store = new Store(baseDir)
43 this.verbose = isTruthy(process.env.GATSBY_TELEMETRY_VERBOSE)
44 this.debugEvents = isTruthy(process.env.GATSBY_TELEMETRY_DEBUG)
45 this.disabled = isTruthy(process.env.GATSBY_TELEMETRY_DISABLED)
46 }
47
48 isTrackingDisabled() {
49 return this.disabled
50 }
51
52 addEvent(event) {
53 if (this.disabled) {
54 return
55 }
56
57 const eventString = JSON.stringify(event)
58
59 if (this.debugEvents || this.verbose) {
60 console.error(`Captured event:`, JSON.parse(eventString))
61
62 if (this.debugEvents) {
63 // Bail because we don't want to send debug events
64 return
65 }
66 }
67
68 this.store.appendToBuffer(eventString + `\n`)
69 }
70
71 async sendEvents() {
72 return this.store.startFlushEvents(async eventsData => {
73 const events = eventsData
74 .split(`\n`)
75 .filter(e => e && e.length > 2) // drop empty lines
76 .map(e => JSON.parse(e))
77
78 return this.submitEvents(events)
79 })
80 }
81
82 async submitEvents(events) {
83 try {
84 const res = await fetch(this.analyticsApi, {
85 method: `POST`,
86 headers: { "content-type": `application/json` },
87 body: JSON.stringify(events),
88 })
89 return res.ok
90 } catch (e) {
91 return false
92 }
93 }
94
95 getConfig(key) {
96 if (key) {
97 return this.config.get(key)
98 }
99 return this.config.all
100 }
101
102 updateConfig(key, value) {
103 return this.config.set(key, value)
104 }
105}