From 41ac4bd082ad08961500e9a637af9323768d27e3 Mon Sep 17 00:00:00 2001 From: hveldstra Date: Thu, 19 Oct 2023 11:36:03 +0100 Subject: [PATCH] feat(skytrace): add event pings --- packages/skytrace/package.json | 2 + packages/skytrace/src/commands/run.ts | 10 +++ packages/skytrace/src/telemetry.ts | 115 ++++++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 packages/skytrace/src/telemetry.ts diff --git a/packages/skytrace/package.json b/packages/skytrace/package.json index 69c1be81c1..7b2bc718b7 100644 --- a/packages/skytrace/package.json +++ b/packages/skytrace/package.json @@ -27,6 +27,7 @@ "artillery-plugin-expect": "*", "chalk": "^4.1.2", "cheerio": "^1.0.0-rc.10", + "ci-info": "^3.9.0", "cli-highlight": "^2.1.11", "debug": "^4.3.1", "gradient-string": "^2.0.2", @@ -34,6 +35,7 @@ "jmespath": "^0.16.0", "js-yaml": "^3.13.1", "mime-types": "2.1.35", + "posthog-node": "^3.1.2", "sprintf-js": "^1.1.2", "temp": "^0.9.4" }, diff --git a/packages/skytrace/src/commands/run.ts b/packages/skytrace/src/commands/run.ts index fbe1d55276..4dea5bcb6a 100644 --- a/packages/skytrace/src/commands/run.ts +++ b/packages/skytrace/src/commands/run.ts @@ -12,6 +12,8 @@ import { Plugin, formatters } from 'artillery-plugin-expect'; import * as gradientString from 'gradient-string'; +import * as telemetry from '../telemetry'; + class RunCommand extends Command { static aliases = ['test']; static strict = false; @@ -122,6 +124,12 @@ SKYTRACE ──━━★ const opts = { target: flags.target, showHTTPTimings: flags.timings }; + const ping = telemetry.init(); + await ping.capture('run-flow', { + cliTarget: flags.target, + cliHTTPTimings: flags.timings, + }); + if (flags.reload) { console.log('> Running flow (reload mode on)'); console.log(); @@ -161,6 +169,8 @@ SKYTRACE ──━━★ console.log(''); await this.runFlow(flowFilePaths[0], opts); } + + await ping.shutdown(); } } diff --git a/packages/skytrace/src/telemetry.ts b/packages/skytrace/src/telemetry.ts new file mode 100644 index 0000000000..a49b1d349b --- /dev/null +++ b/packages/skytrace/src/telemetry.ts @@ -0,0 +1,115 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + 'use strict'; + + const { version: skytraceVersion } = require('../package.json'); + const { isCI, name: ciName } = require('ci-info'); + const chalk = require('chalk'); + const debug = require('debug')('telemetry'); + + const POSTHOG_TOKEN = '_uzX-_WJoVmE_tsLvu0OFD2tpd0HGz72D5sU1zM2hbs'; + + const noop = () => {}; + + const notice = () => { + console.log( + 'Anonymized telemetry is on. Learn more: https://skytrace.dev/docs/resources/core/telemetry.html' + ); + }; + + const isEnabled = () => { + return typeof process.env.SKYTRACE_DISABLE_TELEMETRY === 'undefined'; + }; + + const init = () => { + const telemetryDisabled = !isEnabled(); + + const debugEnabled = + typeof process.env.SKYTRACE_TELEMETRY_DEBUG !== 'undefined'; + + let telemetryDefaults = {}; + try { + telemetryDefaults = JSON.parse(process.env.SKYTRACE_TELEMETRY_DEFAULTS); + } catch (err) { + // fail silently + } + + const telemetry: any = { + capture: noop, + shutdown: noop + }; + + const capture = (client) => { + return (event, data: any = {}) => { + let eventPayload; + + if (telemetryDisabled) { + eventPayload = { + event, + distinctId: 'skytrace' + }; + } else { + eventPayload = { + event, + distinctId: data.distinctId || 'skytrace', + properties: { + ...data, + version: skytraceVersion, + os: process.platform, + isCi: isCI, + $ip: null + } + }; + + eventPayload.properties = Object.assign( + eventPayload.properties, + telemetryDefaults + ); + + if (isCI) { + eventPayload.properties.ciName = ciName; + } + } + + if (debugEnabled) { + console.log( + chalk.yellow(`Telemetry data: ${JSON.stringify(eventPayload)}`) + ); + } + + try { + debug({ eventPayload }); + client.capture(eventPayload); + } catch (err) { + debug(err); + } + }; + }; + + const shutdown = (client) => async () => { + try { + await client.shutdownAsync(); + } catch (err) { + debug(err); + } + }; + + try { + const PostHog = require('posthog-node').PostHog; + const client = new PostHog(POSTHOG_TOKEN, { + flushInterval: 100 + }); + + telemetry.capture = capture(client); + telemetry.shutdown = shutdown(client); + } catch (err) { + debug(err); + } + + return telemetry; + }; + + export { init, notice, isEnabled }; + \ No newline at end of file