From 4da339ae3f7d9ce7d3e9fc24ddd442fc19157c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=B6ran=20Sander?= Date: Thu, 17 Aug 2023 16:28:43 +0000 Subject: [PATCH] feat(telemetry): Change to using PostHog for telemetry collection Implements #744 --- package-lock.json | 27 +++ package.json | 1 + src/lib/telemetry.js | 538 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 465 insertions(+), 101 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8cf1db93..0e1835aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,6 +55,7 @@ "nodemailer-express-handlebars": "^6.1.0", "npm": "^9.7.1", "os": "^0.1.2", + "posthog-node": "^3.1.1", "promise": "^8.3.0", "qrs-interact": "^6.3.1", "rate-limiter-flexible": "^2.4.1", @@ -10046,6 +10047,27 @@ "node": ">=4" } }, + "node_modules/posthog-node": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-3.1.1.tgz", + "integrity": "sha512-OUSYcnLHbzvY/dxNsbUGoYuTZz5XNx48BkfiCkOIJZMFvot5VPQ0KWEjX+kzYxEwHeXbjW9plqsOVcYCYfidgg==", + "dependencies": { + "axios": "^0.27.0", + "rusha": "^0.8.14" + }, + "engines": { + "node": ">=15.0.0" + } + }, + "node_modules/posthog-node/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -10461,6 +10483,11 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/rusha": { + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/rusha/-/rusha-0.8.14.tgz", + "integrity": "sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==" + }, "node_modules/safe-array-concat": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", diff --git a/package.json b/package.json index 3bfd5b9e..f862b375 100644 --- a/package.json +++ b/package.json @@ -88,6 +88,7 @@ "nodemailer-express-handlebars": "^6.1.0", "npm": "^9.7.1", "os": "^0.1.2", + "posthog-node": "^3.1.1", "promise": "^8.3.0", "qrs-interact": "^6.3.1", "rate-limiter-flexible": "^2.4.1", diff --git a/src/lib/telemetry.js b/src/lib/telemetry.js index 69cd0428..1bf21858 100644 --- a/src/lib/telemetry.js +++ b/src/lib/telemetry.js @@ -1,116 +1,440 @@ -/* eslint-disable prettier/prettier */ -const axios = require('axios'); +/* eslint-disable camelcase */ +const { PostHog } = require('posthog-node'); const globals = require('../globals'); -// const telemetryBaseUrl = 'http://localhost:7071/'; -const telemetryBaseUrl = 'https://ptarmiganlabs-telemetry.azurewebsites.net/'; -const telemetryUrl = '/api/butlerTelemetry'; +// Define variable to hold the PostHog client +let posthogClient; const callRemoteURL = async () => { try { + let heartbeat = 'null'; + let dockerHealthCheck = 'null'; + let uptimeMonitor = 'null'; + let uptimeMonitorStoreInInfluxdb = 'null'; + let uptimeMonitorStoreInNewRelic = 'null'; + + let api_apiListEnbledEndpoints = 'null'; + let api_base62ToBase16 = 'null'; + let api_base16ToBase62 = 'null'; + let api_butlerPing = 'null'; + let api_createDir = 'null'; + let api_createDirQvd = 'null'; + let api_fileDelete = 'null'; + let api_fileMove = 'null'; + let api_fileCopy = 'null'; + let api_keyValueStore = 'null'; + let api_mqttPublishMessage = 'null'; + let api_newRelic_postNewRelicMetric = 'null'; + let api_newRelic_postNewRelicEvent = 'null'; + let api_scheduler_createNewSchedule = 'null'; + let api_scheduler_getSchedule = 'null'; + let api_scheduler_getScheduleStatusAll = 'null'; + let api_scheduler_updateSchedule = 'null'; + let api_scheduler_deleteSchedule = 'null'; + let api_scheduler_startSchedule = 'null'; + let api_scheduler_stopSchedule = 'null'; + let api_senseAppReload = 'null'; + let api_senseAppDump = 'null'; + let api_senseListApps = 'null'; + let api_senseStartTask = 'null'; + let api_slackPostMessage = 'null'; + + let teamsNotification_reloadTaskFailure = 'null'; + let teamsNotification_reloadTaskAborted = 'null'; + + let slackNotification_reloadTaskFailure = 'null'; + let slackNotification_reloadTaskAborted = 'null'; + + let emailNotification_reloadTaskFailure = 'null'; + let emailNotification_reloadTaskAborted = 'null'; + + let webhookNotification_reloadTaskFailure = 'null'; + let webhookNotification_reloadTaskAborted = 'null'; + + let signl4Notification_reloadTaskFailure = 'null'; + let signl4Notification_reloadTaskAborted = 'null'; + + let newRelicNotification_reloadTaskFailure = 'null'; + let newRelicNotification_reloadTaskAborted = 'null'; + + let scheduler = 'null'; + let mqtt = 'null'; + let serviceMonitor = 'null'; + let keyValueStore = 'null'; + let udpServer = 'null'; + let restServer = 'null'; + + // Gather info on what features are enabled/disabled + if ( + (globals.config.has('Butler.heartbeat.enabled') && globals.config.get('Butler.heartbeat.enabled') === true) || + (globals.config.has('Butler.heartbeat.enable') && globals.config.get('Butler.heartbeat.enable') === true) + ) { + heartbeat = true; + } + + if ( + (globals.config.has('Butler.dockerHealthCheck.enabled') && globals.config.get('Butler.dockerHealthCheck.enabled') === true) || + (globals.config.has('Butler.dockerHealthCheck.enable') && globals.config.get('Butler.dockerHealthCheck.enable') === true) + ) { + dockerHealthCheck = true; + } + + if ( + (globals.config.has('Butler.uptimeMonitor.enabled') && globals.config.get('Butler.uptimeMonitor.enabled') === true) || + (globals.config.has('Butler.uptimeMonitor.enable') && globals.config.get('Butler.uptimeMonitor.enable') === true) + ) { + uptimeMonitor = true; + } + + if ( + (globals.config.has('Butler.uptimeMonitor.storeInInfluxdb.enabled') && + globals.config.get('Butler.uptimeMonitor.storeInInfluxdb.enabled') === true) || + (globals.config.has('Butler.uptimeMonitor.storeInInfluxdb.enable') && + globals.config.get('Butler.uptimeMonitor.storeInInfluxdb.enable') === true) + ) { + uptimeMonitorStoreInInfluxdb = true; + } + + // API endpoints + if (globals.config.has('Butler.uptimeMonitor.storeNewRelic.enable')) { + uptimeMonitorStoreInNewRelic = globals.config.get('Butler.uptimeMonitor.storeNewRelic.enable'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.apiListEnbledEndpoints')) { + api_apiListEnbledEndpoints = globals.config.get('Butler.restServerEndpointsEnable.apiListEnbledEndpoints'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.base62ToBase16')) { + api_base62ToBase16 = globals.config.get('Butler.restServerEndpointsEnable.base62ToBase16'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.base16ToBase62')) { + api_base16ToBase62 = globals.config.get('Butler.restServerEndpointsEnable.base16ToBase62'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.butlerping')) { + api_butlerPing = globals.config.get('Butler.restServerEndpointsEnable.butlerping'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.createDir')) { + api_createDir = globals.config.get('Butler.restServerEndpointsEnable.createDir'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.createDirQVD')) { + api_createDirQvd = globals.config.get('Butler.restServerEndpointsEnable.createDirQVD'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.fileDelete')) { + api_fileDelete = globals.config.get('Butler.restServerEndpointsEnable.fileDelete'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.fileMove')) { + api_fileMove = globals.config.get('Butler.restServerEndpointsEnable.fileMove'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.fileCopy')) { + api_fileCopy = globals.config.get('Butler.restServerEndpointsEnable.fileCopy'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.keyValueStore')) { + api_keyValueStore = globals.config.get('Butler.restServerEndpointsEnable.keyValueStore'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.mqttPublishMessage')) { + api_mqttPublishMessage = globals.config.get('Butler.restServerEndpointsEnable.mqttPublishMessage'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.newRelic.postNewRelicMetric')) { + api_newRelic_postNewRelicMetric = globals.config.get('Butler.restServerEndpointsEnable.newRelic.postNewRelicMetric'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.newRelic.postNewRelicEvent')) { + api_newRelic_postNewRelicEvent = globals.config.get('Butler.restServerEndpointsEnable.newRelic.postNewRelicEvent'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.createNewSchedule')) { + api_scheduler_createNewSchedule = globals.config.get('Butler.restServerEndpointsEnable.scheduler.createNewSchedule'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.getSchedule')) { + api_scheduler_getSchedule = globals.config.get('Butler.restServerEndpointsEnable.scheduler.getSchedule'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.getScheduleStatusAll')) { + api_scheduler_getScheduleStatusAll = globals.config.get('Butler.restServerEndpointsEnable.scheduler.getScheduleStatusAll'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.updateSchedule')) { + api_scheduler_updateSchedule = globals.config.get('Butler.restServerEndpointsEnable.scheduler.updateSchedule'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.deleteSchedule')) { + api_scheduler_deleteSchedule = globals.config.get('Butler.restServerEndpointsEnable.scheduler.deleteSchedule'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.startSchedule')) { + api_scheduler_startSchedule = globals.config.get('Butler.restServerEndpointsEnable.scheduler.startSchedule'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.scheduler.stopSchedule')) { + api_scheduler_stopSchedule = globals.config.get('Butler.restServerEndpointsEnable.scheduler.stopSchedule'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.senseAppReload')) { + api_senseAppReload = globals.config.get('Butler.restServerEndpointsEnable.senseAppReload'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.senseAppDump')) { + api_senseAppDump = globals.config.get('Butler.restServerEndpointsEnable.senseAppDump'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.senseListApps')) { + api_senseListApps = globals.config.get('Butler.restServerEndpointsEnable.senseListApps'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.senseStartTask')) { + api_senseStartTask = globals.config.get('Butler.restServerEndpointsEnable.senseStartTask'); + } + + if (globals.config.has('Butler.restServerEndpointsEnable.slackPostMessage')) { + api_slackPostMessage = globals.config.get('Butler.restServerEndpointsEnable.slackPostMessage'); + } + + if (globals.config.has('Butler.teamsNotification.reloadTaskFailure.enable')) { + teamsNotification_reloadTaskFailure = globals.config.get('Butler.teamsNotification.reloadTaskFailure.enable'); + } + + if (globals.config.has('Butler.teamsNotification.reloadTaskAborted.enable')) { + teamsNotification_reloadTaskAborted = globals.config.get('Butler.teamsNotification.reloadTaskAborted.enable'); + } + + if (globals.config.has('Butler.slackNotification.reloadTaskFailure.enable')) { + slackNotification_reloadTaskFailure = globals.config.get('Butler.slackNotification.reloadTaskFailure.enable'); + } + + if (globals.config.has('Butler.slackNotification.reloadTaskAborted.enable')) { + slackNotification_reloadTaskAborted = globals.config.get('Butler.slackNotification.reloadTaskAborted.enable'); + } + + if (globals.config.has('Butler.emailNotification.reloadTaskFailure.enable')) { + emailNotification_reloadTaskFailure = globals.config.get('Butler.emailNotification.reloadTaskFailure.enable'); + } + + if (globals.config.has('Butler.emailNotification.reloadTaskAborted.enable')) { + emailNotification_reloadTaskAborted = globals.config.get('Butler.emailNotification.reloadTaskAborted.enable'); + } + + if (globals.config.has('Butler.webhookNotification.enable') && globals.config.get('Butler.webhookNotification.enable') === true) { + webhookNotification_reloadTaskFailure = globals.config.get('Butler.webhookNotification.reloadTaskFailure.webhooks').length > 0; + } else { + webhookNotification_reloadTaskFailure = false; + } + + if (globals.config.has('Butler.webhookNotification.enable') && globals.config.get('Butler.webhookNotification.enable') === true) { + webhookNotification_reloadTaskAborted = globals.config.get('Butler.webhookNotification.reloadTaskAborted.webhooks').length > 0; + } else { + webhookNotification_reloadTaskAborted = false; + } + + if (globals.config.has('Butler.incidentTool.signl4.reloadTaskFailure.enable')) { + signl4Notification_reloadTaskFailure = globals.config.get('Butler.incidentTool.signl4.reloadTaskFailure.enable'); + } + + if (globals.config.has('Butler.incidentTool.signl4.reloadTaskAborted.enable')) { + signl4Notification_reloadTaskAborted = globals.config.get('Butler.incidentTool.signl4.reloadTaskAborted.enable'); + } + + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.enable') || + globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.enable') + ) { + if ( + globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.event.enable') || + globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.destination.log.enable') + ) { + newRelicNotification_reloadTaskFailure = true; + } else { + newRelicNotification_reloadTaskFailure = false; + } + } + + if ( + globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.enable') || + globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.enable') + ) { + if ( + globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.event.enable') || + globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.destination.log.enable') + ) { + newRelicNotification_reloadTaskAborted = true; + } else { + newRelicNotification_reloadTaskAborted = false; + } + } + + if (globals.config.has('Butler.scheduler.enable')) { + scheduler = globals.config.get('Butler.scheduler.enable'); + } + + if (globals.config.has('Butler.mqttConfig.enable')) { + mqtt = globals.config.get('Butler.mqttConfig.enable'); + } + + if (globals.config.has('Butler.serviceMonitor.enable')) { + serviceMonitor = globals.config.get('Butler.serviceMonitor.enable'); + } + + if (globals.config.has('Butler.keyValueStore.enable')) { + keyValueStore = globals.config.get('Butler.keyValueStore.enable'); + } + + if (globals.config.has('Butler.udpServerConfig.enable')) { + udpServer = globals.config.get('Butler.udpServerConfig.enable'); + } + + if (globals.config.has('Butler.restServerConfig.enable')) { + restServer = globals.config.get('Butler.restServerConfig.enable'); + } + + // Build body that can be sent to PostHog const body = { - service: 'butler', - serviceVersion: globals.appVersion, - system: { - id: globals.hostInfo.id, - arch: globals.hostInfo.si.os.arch, - platform: globals.hostInfo.si.os.platform, - release: globals.hostInfo.si.os.release, - distro: globals.hostInfo.si.os.distro, - codename: globals.hostInfo.si.os.codename, - virtual: globals.hostInfo.si.system.virtual, - hypervisor: globals.hostInfo.si.os.hypervizor, - nodeVersion: globals.hostInfo.node.nodeVersion, - }, - enabledFeatures: { - api: globals.config.has('Butler.restServerEndpointsEnable') ? globals.config.get('Butler.restServerEndpointsEnable') : {}, - feature: { - heartbeat: globals.config.has('Butler.heartbeat.enable') ? globals.config.get('Butler.heartbeat.enable') : false, - dockerHealthCheck: globals.config.has('Butler.dockerHealthCheck.enable') - ? globals.config.get('Butler.dockerHealthCheck.enable') - : false, - uptimeMonitor: globals.config.has('Butler.uptimeMonitor.enable') - ? globals.config.get('Butler.uptimeMonitor.enable') - : false, - uptimeMonitor_storeInInfluxdb: globals.config.has('Butler.uptimeMonitor.storeInInfluxdb.enable') - ? globals.config.get('Butler.uptimeMonitor.storeInInfluxdb.enable') - : false, - uptimeMonitor_storeInNewRelic: globals.config.has('Butler.uptimeMonitor.storeNewRelic.enable') - ? globals.config.get('Butler.uptimeMonitor.storeNewRelic.enable') - : false, - teamsNotification: globals.config.has('Butler.teamsNotification.enable') - ? globals.config.get('Butler.teamsNotification.enable') - : false, - teamsNotification_reloadTaskFailure: globals.config.has('Butler.teamsNotification.reloadTaskFailure.enable') - ? globals.config.get('Butler.teamsNotification.reloadTaskFailure.enable') - : false, - teamsNotification_reloadTaskAborted: globals.config.has('Butler.teamsNotification.reloadTaskAborted.enable') - ? globals.config.get('Butler.teamsNotification.reloadTaskAborted.enable') - : false, - slackNotification: globals.config.has('Butler.slackNotification.enable') - ? globals.config.get('Butler.slackNotification.enable') - : false, - slackNotification_reloadTaskFailure: globals.config.has('Butler.slackNotification.reloadTaskFailure.enable') - ? globals.config.get('Butler.slackNotification.reloadTaskFailure.enable') - : false, - slackNotification_reloadTaskAborted: globals.config.has('Butler.slackNotification.reloadTaskAborted.enable') - ? globals.config.get('Butler.slackNotification.reloadTaskAborted.enable') - : false, - emailNotification: globals.config.has('Butler.emailNotification.enable') - ? globals.config.get('Butler.emailNotification.enable') - : false, - emailNotification_reloadTaskFailure: globals.config.has('Butler.emailNotification.reloadTaskFailure.enable') - ? globals.config.get('Butler.emailNotification.reloadTaskFailure.enable') - : false, - emailNotification_reloadTaskAborted: globals.config.has('Butler.emailNotification.reloadTaskAborted.enable') - ? globals.config.get('Butler.emailNotification.reloadTaskAborted.enable') - : false, - webhookNotification: globals.config.has('Butler.webhookNotification.enable') - ? globals.config.get('Butler.webhookNotification.enable') - : false, - webhookNotification_reloadTaskFailure: globals.config.has('Butler.webhookNotification.reloadTaskFailure.enable') - ? globals.config.get('Butler.webhookNotification.reloadTaskFailure.enable') - : false, - webhookNotification_reloadTaskAborted: globals.config.has('Butler.webhookNotification.reloadTaskAborted.enable') - ? globals.config.get('Butler.webhookNotification.reloadTaskAborted.enable') - : false, - signl4Notification_reloadTaskFailure: globals.config.has('Butler.incidentTool.signl4.reloadTaskFailure.enable') - ? globals.config.get('Butler.incidentTool.signl4.reloadTaskFailure.enable') - : false, - signl4Notification_reloadTaskAborted: globals.config.has('Butler.incidentTool.signl4.reloadTaskAborted.enable') - ? globals.config.get('Butler.incidentTool.signl4.reloadTaskAborted.enable') - : false, - newRelicNotification_reloadTaskFailure: globals.config.has('Butler.incidentTool.newRelic.reloadTaskFailure.enable') - ? globals.config.get('Butler.incidentTool.newRelic.reloadTaskFailure.enable') - : false, - newRelicNotification_reloadTaskAborted: globals.config.has('Butler.incidentTool.newRelic.reloadTaskAborted.enable') - ? globals.config.get('Butler.incidentTool.newRelic.reloadTaskAborted.enable') - : false, - scheduler: globals.config.has('Butler.scheduler.enable') ? globals.config.get('Butler.scheduler.enable') : false, - mqtt: globals.config.has('Butler.mqttConfig.enable') ? globals.config.get('Butler.mqttConfig.enable') : false, - userActivityLogging: globals.config.has('Butler.userActivityLogging.enable') - ? globals.config.get('Butler.userActivityLogging.enable') - : false, + distinctId: globals.hostInfo.id, + event: 'telemetry sent', + + properties: { + service: 'butler', + serviceVersion: globals.appVersion, + + system_id: globals.hostInfo.id, + system_arch: globals.hostInfo.si.os.arch, + system_platform: globals.hostInfo.si.os.platform, + system_release: globals.hostInfo.si.os.release, + system_distro: globals.hostInfo.si.os.distro, + system_codename: globals.hostInfo.si.os.codename, + system_virtual: globals.hostInfo.si.system.virtual, + system_hypervisor: globals.hostInfo.si.os.hypervizor, + system_nodeVersion: globals.hostInfo.node.nodeVersion, + + feature_heartbeat: heartbeat, + feature_dockerHealthCheck: dockerHealthCheck, + feature_uptimeMonitor: uptimeMonitor, + feature_uptimeMonitoStoreInInfluxdb: uptimeMonitorStoreInInfluxdb, + feature_uptimeMonitoStoreInNewRelic: uptimeMonitorStoreInNewRelic, + + feature_apiListEnbledEndpoints: api_apiListEnbledEndpoints, + feature_apiBase62ToBase16: api_base62ToBase16, + feature_apiBase16ToBase62: api_base16ToBase62, + feature_apiButlerPing: api_butlerPing, + feature_apiCreateDir: api_createDir, + feature_apiCreateDirQvd: api_createDirQvd, + feature_apiFileDelete: api_fileDelete, + feature_apiFileMove: api_fileMove, + feature_apiFileCopy: api_fileCopy, + feature_apiKeyValueStore: api_keyValueStore, + feature_apiMqttPublishMessage: api_mqttPublishMessage, + feature_apiNewRelicPostMetric: api_newRelic_postNewRelicMetric, + feature_apiNewRelicPostEvent: api_newRelic_postNewRelicEvent, + feature_apiSchedulerCreateNew: api_scheduler_createNewSchedule, + feature_apiSchedulerGet: api_scheduler_getSchedule, + feature_apiSchedulerGetStatusAll: api_scheduler_getScheduleStatusAll, + feature_apiSchedulerUpdate: api_scheduler_updateSchedule, + feature_apiSchedulerDelete: api_scheduler_deleteSchedule, + feature_apiSchedulerStart: api_scheduler_startSchedule, + feature_apiSchedulerStop: api_scheduler_stopSchedule, + feature_apiSenseAppReload: api_senseAppReload, + feature_apiSenseAppDump: api_senseAppDump, + feature_apiSenseListApps: api_senseListApps, + feature_apiSenseStartTask: api_senseStartTask, + feature_apiSlackPostMessage: api_slackPostMessage, + + feature_teamsNotificationReloadTaskFailure: teamsNotification_reloadTaskFailure, + feature_teamsNotificationReloadTaskAborted: teamsNotification_reloadTaskAborted, + + feature_slackNotificationReloadTaskFailure: slackNotification_reloadTaskFailure, + feature_slackNotificationReloadTaskAborted: slackNotification_reloadTaskAborted, + + feature_signl4NotificationReloadTaskFailure: signl4Notification_reloadTaskFailure, + feature_signl4NotificationReloadTaskAborted: signl4Notification_reloadTaskAborted, + + feature_newRelicNotificationReloadTaskFailure: newRelicNotification_reloadTaskFailure, + feature_newRelicNotificationReloadTaskAborted: newRelicNotification_reloadTaskAborted, + + feature_emailNotificationReloadTaskFailure: emailNotification_reloadTaskFailure, + feature_emailNotificationReloadTaskAborted: emailNotification_reloadTaskAborted, + + feature_webhookNotificationReloadTaskFailure: webhookNotification_reloadTaskFailure, + feature_webhookNotificationReloadTaskAborted: webhookNotification_reloadTaskAborted, + + feature_mqtt: mqtt, + feature_scheduler: scheduler, + feature_serviceMonitor: serviceMonitor, + feature_keyValueStore: keyValueStore, + feature_udpServer: udpServer, + feature_restServer: restServer, + + telemetry_json: { + system: { + id: globals.hostInfo.id, + arch: globals.hostInfo.si.os.arch, + platform: globals.hostInfo.si.os.platform, + release: globals.hostInfo.si.os.release, + distro: globals.hostInfo.si.os.distro, + codename: globals.hostInfo.si.os.codename, + virtual: globals.hostInfo.si.system.virtual, + hypervisor: globals.hostInfo.si.os.hypervizor, + nodeVersion: globals.hostInfo.node.nodeVersion, + }, + enabledFeatures: { + feature: { + heartbeat, + dockerHealthCheck, + uptimeMonitor, + uptimeMonitor_storeInInfluxdb: uptimeMonitorStoreInInfluxdb, + uptimeMonitor_storeInNewRelic: uptimeMonitorStoreInNewRelic, + + apiEnbledEndpoints: globals.config.has('Butler.restServerEndpointsEnable') + ? globals.config.get('Butler.restServerEndpointsEnable') + : {}, + + teamsNotificationReloadTaskFailure: teamsNotification_reloadTaskFailure, + teamsNotificationReloadTaskAborted: teamsNotification_reloadTaskAborted, + + slackNotificationReloadTaskFailure: slackNotification_reloadTaskFailure, + slackNotificationReloadTaskAborted: slackNotification_reloadTaskAborted, + + signl4NotificationReloadTaskFailure: signl4Notification_reloadTaskFailure, + signl4NotificationReloadTaskAborted: signl4Notification_reloadTaskAborted, + + newRelicNotificationReloadTaskFailure: newRelicNotification_reloadTaskFailure, + newRelicNotificationReloadTaskAborted: newRelicNotification_reloadTaskAborted, + + emailNotificationReloadTaskFailure: emailNotification_reloadTaskFailure, + emailNotificationReloadTaskAborted: emailNotification_reloadTaskAborted, + + webhookNotificationReloadTaskFailure: webhookNotification_reloadTaskFailure, + webhookNotificationReloadTaskAborted: webhookNotification_reloadTaskAborted, + + mqtt, + scheduler, + serviceMonitor, + keyValueStore, + udpServer, + restServer, + }, + }, }, }, }; - const axiosConfig = { - url: telemetryUrl, - method: 'post', - baseURL: telemetryBaseUrl, - data: body, - timeout: 15000, - responseType: 'text', - }; + // Send the telemetry to PostHog + posthogClient.capture(body); - await axios.request(axiosConfig); globals.logger.debug('TELEMETRY: Sent anonymous telemetry. Thanks for contributing to making Butler better!'); } catch (err) { globals.logger.error('TELEMETRY: Could not send anonymous telemetry.'); globals.logger.error(' While not mandatory the telemetry data greatly helps the Butler developers.'); - globals.logger.error(' It provides insights into which features are used most and what hardware/OSs are most used out there.'); + globals.logger.error(' It provides insights into which features are used most and what hardware/OSs are used out there.'); globals.logger.error( ' This information makes it possible to focus development efforts where they will make most impact and be most valuable.' ); @@ -119,15 +443,27 @@ const callRemoteURL = async () => { } else { globals.logger.error(` Error: ${err}`); } - globals.logger.error('❤️ Thank you for your supporting Butler by allowing telemetry! ❤️'); + globals.logger.error('❤️ Thank you for supporting Butler by allowing telemetry! ❤️'); } }; function setupAnonUsageReportTimer(logger, hostInfo) { try { - setInterval(() => { - callRemoteURL(logger, hostInfo); - }, 1000 * 60 * 60 * 12); // Report anon telemetry every 12 hours + // Setup PostHog client + posthogClient = new PostHog('phc_5cmKiX9OubQjsSfOZuaolWaxo2z7WXqd295eB0uOtTb', { + host: 'https://eu.posthog.com', + flushAt: 1, // Flush events to PostHog as soon as they are captured + flushInterval: 60 * 1000, // Flush every 60 seconds + requestTimeout: 30 * 1000, // 30 secpnds timeout + disableGeoip: false, // Enable geoip lookups + }); + + setInterval( + () => { + callRemoteURL(logger, hostInfo); + }, + 1000 * 60 * 60 * 12 + ); // Report anon telemetry every 12 hours // Do an initial report to the remote URL callRemoteURL(logger, hostInfo);