From a0d7e42a1136b18a58b650ba78f16537083e9535 Mon Sep 17 00:00:00 2001 From: HDegroote <75906619+HDegroote@users.noreply.github.com> Date: Sun, 28 Jul 2024 19:16:29 +0200 Subject: [PATCH] Add hostname and service labels (#12) * Add hostname and service labels * Update prometheus example config * No logs --- index.js | 14 ++++++++++---- lib/prom-targets.js | 8 +++++--- package.json | 4 ++-- prometheus/prometheus.yml | 14 +++++++++++--- test/integration.js | 17 +++++++++++++---- test/test.js | 3 ++- 6 files changed, 43 insertions(+), 17 deletions(-) diff --git a/index.js b/index.js index d59e1c8..71be5a2 100644 --- a/index.js +++ b/index.js @@ -93,7 +93,7 @@ class PrometheusDhtBridge extends ReadyResource { if (this.opened) await this._writeAliases() } - putAlias (alias, targetPubKey, { write = true } = {}) { + putAlias (alias, targetPubKey, hostname, service, { write = true } = {}) { if (!this.opened && write) throw new Error('Cannot put aliases before ready') targetPubKey = idEnc.decode(idEnc.normalize(targetPubKey)) @@ -111,10 +111,13 @@ class PrometheusDhtBridge extends ReadyResource { const entry = new AliasesEntry( new ScraperClient(this.swarm, targetPubKey), + hostname, + service, Date.now() + this.entryExpiryMs ) this.aliases.set(alias, entry) + // TODO: just emit entry? this.emit('set-alias', { alias, publicKey: targetPubKey, scrapeClient: entry.scrapeClient }) const updated = true @@ -192,11 +195,12 @@ class PrometheusDhtBridge extends ReadyResource { async _loadAliases () { // should never throw try { const aliases = await readPromTargets(this.promTargetsLoc) - for (const [alias, pubKey] of aliases) { + + for (const [alias, { z32PubKey, hostname, service }] of aliases) { // Write false since we load an existing state // (otherwise we overwrite them 1 by 1, and can lose // entries if we restart/crash during setup) - this.putAlias(alias, pubKey, { write: false }) + this.putAlias(alias, z32PubKey, hostname, service, { write: false }) } } catch (e) { this.emit('load-aliases-error', e) @@ -205,10 +209,12 @@ class PrometheusDhtBridge extends ReadyResource { } class AliasesEntry extends ReadyResource { - constructor (scrapeClient, expiry) { + constructor (scrapeClient, hostname, service, expiry) { super() this.scrapeClient = scrapeClient + this.hostname = hostname + this.service = service this.expiry = expiry } diff --git a/lib/prom-targets.js b/lib/prom-targets.js index 201da15..93e7352 100644 --- a/lib/prom-targets.js +++ b/lib/prom-targets.js @@ -9,7 +9,9 @@ async function writePromTargets (location, aliases) { // than to extract the pubkey in the caller for (const [target, entry] of aliases) { const pubKey = idEnc.normalize(entry.targetKey) - targets.push(`${target}:${pubKey}`) + const hostname = entry.hostname.replaceAll(':', '-') + const service = entry.service.replaceAll(':', '-') + targets.push(`${target}:${pubKey}:${hostname}:${service}`) } const content = [ @@ -38,8 +40,8 @@ async function readPromTargets (location) { const aliases = new Map() for (const target of fullJson[0].targets) { - const [alias, z32PubKey] = target.split(':') - aliases.set(alias, z32PubKey) + const [alias, z32PubKey, hostname, service] = target.split(':') + aliases.set(alias, { z32PubKey, hostname, service }) } return aliases diff --git a/package.json b/package.json index 709a598..164e6dc 100644 --- a/package.json +++ b/package.json @@ -41,8 +41,8 @@ "dependencies": { "b4a": "^1.6.6", "debounceify": "^1.1.0", - "dht-prom-alias-rpc": "^0.0.1-alpha.0", - "dht-prom-client": "^0.0.1-alpha.9", + "dht-prom-alias-rpc": "^0.0.1-alpha.1", + "dht-prom-client": "^0.0.1-alpha.10", "fastify": "^4.28.0", "graceful-goodbye": "^1.3.0", "hypercore-id-encoding": "^1.3.0", diff --git a/prometheus/prometheus.yml b/prometheus/prometheus.yml index c9292bf..b1b9ac8 100644 --- a/prometheus/prometheus.yml +++ b/prometheus/prometheus.yml @@ -1,8 +1,8 @@ # This is an example config. global: - scrape_interval: 5s - evaluation_interval: 5s + scrape_interval: 1s + evaluation_interval: 1s # Source for relabeling approach: https://stackoverflow.com/questions/59866342/prometheus-dynamic-metrics-path scrape_configs: @@ -12,9 +12,17 @@ scrape_configs: - 'targets.json' relabel_configs: - source_labels: [__address__] - regex: "(.+):.{52}" # Targets are structured as :, and at prometheus level we only need the target name + regex: "(.+):.{52}:.+" # Targets are structured as :, and at prometheus level we only need the target name replacement: "/scrape/$1/metrics" # Captured part + /metrics appendix target_label: __metrics_path__ # => instead of default /metrics - source_labels: [__address__] replacement: "localhost:30000" # Replace with the port where the dht-prometheus http server runs target_label: __address__ + - source_labels: [__address__] + regex: ".+:.{52}:([^:]+):.+:" # Targets are structured as :, and at prometheus level we only need the target name + replacement: "$1" # Captured part + /metrics appendix + target_label: hostname + - source_labels: [__address__] + regex: ".+:.{52}:[^:]+:(.+):" # Targets are structured as :, and at prometheus level we only need the target name + replacement: "$1" # Captured part + /metrics appendix + target_label: service diff --git a/test/integration.js b/test/integration.js index 797b2ad..b8965dc 100644 --- a/test/integration.js +++ b/test/integration.js @@ -323,7 +323,8 @@ function getClient (t, bootstrap, scraperPubKey, sharedSecret, { name = 'dummy' idEnc.decode(scraperPubKey), name, sharedSecret, - { bootstrap } + 'my-service', + { bootstrap, hostname: 'my-hostname' } ) t.teardown(async () => { @@ -349,12 +350,20 @@ scrape_configs: - '${promTargetsLoc}' relabel_configs: - source_labels: [__address__] - regex: "(.+):.{52}" # Targets are structured as :, and at prometheus level we only need the key + regex: "(.+):.{52}:.+" # Targets are structured as :, and at prometheus level we only need the target name replacement: "/scrape/$1/metrics" # Captured part + /metrics appendix target_label: __metrics_path__ # => instead of default /metrics - source_labels: [__address__] - replacement: "${bridgeHttpAddress}" - target_label: __address__ # => That's the actual address + replacement: "${bridgeHttpAddress}" # Replace with the port where the dht-prometheus http server runs + target_label: __address__ + - source_labels: [__address__] + regex: ".+:.{52}:([^:]+):.+:" # Targets are structured as :, and at prometheus level we only need the target name + replacement: "$1" # Captured part + /metrics appendix + target_label: hostname + - source_labels: [__address__] + regex: ".+:.{52}:[^:]+:(.+):" # Targets are structured as :, and at prometheus level we only need the target name + replacement: "$1" # Captured part + /metrics appendix + target_label: service ` await fs.promises.writeFile(loc, content) diff --git a/test/test.js b/test/test.js index 4304e5b..26a0843 100644 --- a/test/test.js +++ b/test/test.js @@ -256,7 +256,8 @@ async function setup (t, bridgeOpts = {}) { scraperPubKey, 'dummy', sharedSecret, - { bootstrap } + 'my-service', + { bootstrap, hostname: 'my-hostname' } ) t.teardown(async () => {