From a1968f2c1c2124890484bf3d6f7216f1c35da8fc Mon Sep 17 00:00:00 2001 From: pavel bairov Date: Fri, 14 Jun 2024 12:08:18 +0300 Subject: [PATCH] InfluxDB 2.x - Send annotations (#4175) * InfluxDB 2.x - send annotations * InfluxDB 2.x - send annotations. Add organisation query param --- .github/workflows/linux.yml | 4 +- lib/plugins/influxdb/index.js | 40 ++++++--- lib/plugins/influxdb/send-annotation.js | 2 +- lib/plugins/influxdb/send-annotationV2.js | 101 ++++++++++++++++++++++ 4 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 lib/plugins/influxdb/send-annotationV2.js diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 3bb645666..098160d63 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -71,9 +71,9 @@ jobs: - name: Run test without a CLI run: xvfb-run node test/runWithoutCli.js - name: Run test with Influx 1.8 - run: bin/sitespeed.js http://127.0.0.1:3001/simple/ -n 1 --influxdb.host 127.0.0.1 --xvfb --logToFile + run: bin/sitespeed.js http://127.0.0.1:3001/simple/ -n 1 --influxdb.host 127.0.0.1 --xvfb --logToFile --resultBaseUrl https://result.sitespeed.io --influxdb.annotationScreenshot=true - name: Run test with Influx 2.6.1 - run: bin/sitespeed.js http://127.0.0.1:3001/simple/ -n 1 --influxdb.host 127.0.0.1 --influxdb.port 8087 --influxdb.version 2 --influxdb.organisation sitespeed --influxdb.token sitespeed --xvfb + run: bin/sitespeed.js http://127.0.0.1:3001/simple/ -n 1 --influxdb.host 127.0.0.1 --influxdb.port 8087 --influxdb.version 2 --influxdb.organisation sitespeed --influxdb.token sitespeed --xvfb --resultBaseUrl https://result.sitespeed.io --influxdb.annotationScreenshot=true - name: Run Chrome test with config run: node bin/sitespeed.js --config test/exampleConfig.json http://127.0.0.1:3001/simple/ --xvfb - name: Run Chrome test using compare plugin diff --git a/lib/plugins/influxdb/index.js b/lib/plugins/influxdb/index.js index eea1e4de7..45a940981 100644 --- a/lib/plugins/influxdb/index.js +++ b/lib/plugins/influxdb/index.js @@ -5,7 +5,8 @@ import dayjs from 'dayjs'; import { SitespeedioPlugin } from '@sitespeed.io/plugin'; import { InfluxDBSender as Sender } from './sender.js'; import { InfluxDB2Sender as SenderV2 } from './senderV2.js'; -import { send } from './send-annotation.js'; +import { sendV1 } from './send-annotation.js'; +import { sendV2 } from './send-annotationV2.js'; import { InfluxDBDataGenerator as DataGenerator } from './data-generator.js'; import { throwIfMissing } from '../../support/util.js'; @@ -137,18 +138,31 @@ export default class InfluxDBPlugin extends SitespeedioPlugin { ); this.receivedTypesThatFireAnnotations[message.url] = 0; - return send( - message.url, - message.group, - absolutePagePath, - this.useScreenshots, - this.screenshotType, - // Browsertime pass on when the first run was done for that URL - message.runTime, - this.alias, - this.usingBrowsertime, - this.options - ); + return this.options.influxdb.version == 2 + ? sendV2( + message.url, + message.group, + absolutePagePath, + this.useScreenshots, + this.screenshotType, + // Browsertime pass on when the first run was done for that URL + message.runTime, + this.alias, + this.usingBrowsertime, + this.options + ) + : sendV1( + message.url, + message.group, + absolutePagePath, + this.useScreenshots, + this.screenshotType, + // Browsertime pass on when the first run was done for that URL + message.runTime, + this.alias, + this.usingBrowsertime, + this.options + ); } }); } else { diff --git a/lib/plugins/influxdb/send-annotation.js b/lib/plugins/influxdb/send-annotation.js index 6c9c1f6bf..72dd112f3 100644 --- a/lib/plugins/influxdb/send-annotation.js +++ b/lib/plugins/influxdb/send-annotation.js @@ -13,7 +13,7 @@ import { const log = intel.getLogger('sitespeedio.plugin.influxdb'); -export function send( +export function sendV1( url, group, absolutePagePath, diff --git a/lib/plugins/influxdb/send-annotationV2.js b/lib/plugins/influxdb/send-annotationV2.js new file mode 100644 index 000000000..f6c1bc163 --- /dev/null +++ b/lib/plugins/influxdb/send-annotationV2.js @@ -0,0 +1,101 @@ +import http from 'node:http'; +import https from 'node:https'; + +import intel from 'intel'; +import dayjs from 'dayjs'; + +import { getConnectivity, getURLAndGroup } from '../../support/tsdbUtil.js'; +import { + getAnnotationMessage, + getTagsAsString +} from '../../support/annotationsHelper.js'; + +const log = intel.getLogger('sitespeedio.plugin.influxdb'); + +export function sendV2( + url, + group, + absolutePagePath, + screenShotsEnabledInBrowsertime, + screenshotType, + runTime, + alias, + usingBrowsertime, + options +) { + // The tags make it possible for the dashboard to use the + // templates to choose which annotations that will be showed. + // That's why we need to send tags that matches the template + // variables in Grafana. + const connectivity = getConnectivity(options); + const browser = options.browser; + const urlAndGroup = getURLAndGroup( + options, + group, + url, + options.influxdb.includeQueryParams, + alias + ).split('.'); + let tags = [connectivity, browser, urlAndGroup[0], urlAndGroup[1]]; + + if (options.slug) { + tags.push(options.slug); + } + + const message = getAnnotationMessage( + absolutePagePath, + screenShotsEnabledInBrowsertime, + screenshotType, + undefined, + usingBrowsertime, + options + ); + const timestamp = runTime + ? Math.round(dayjs(runTime) / 1000) + : Math.round(dayjs() / 1000); + // if we have a category, let us send that category too + if (options.influxdb.tags) { + for (let row of options.influxdb.tags.split(',')) { + const keyAndValue = row.split('='); + tags.push(keyAndValue[1]); + } + } + const influxDBTags = getTagsAsString(tags); + const postData = `events title="Sitespeed.io",text="${message}",tags=${influxDBTags} ${timestamp}`; + const postOptions = { + hostname: options.influxdb.host, + port: options.influxdb.port, + path: `/api/v2/write?org=${options.influxdb.organisation}&bucket=${options.influxdb.database}&precision=s`, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(postData), + Authorization: `Token ${options.influxdb.token}` + } + }; + + return new Promise((resolve, reject) => { + log.debug('Send annotation to Influx: %j', postData); + // not perfect but maybe work for us + const library = options.influxdb.protocol === 'https' ? https : http; + const request = library.request(postOptions, res => { + if (res.statusCode === 204) { + res.setEncoding('utf8'); + log.debug('Sent annotation to InfluxDB'); + resolve(); + } else { + const e = new Error( + `Got ${res.statusCode} from InfluxDB when sending annotation ${res.statusMessage}` + ); + log.warn(e.message); + reject(e); + } + }); + request.on('error', error => { + log.error('Got error from InfluxDB when sending annotation', error); + reject(error); + }); + request.write(postData); + request.end(); + }); +}