VictoriaMetrics als zusätzliche Datenbank-Option für Messwerte ergänzt (STORE/DBASE=victoria)

Dritte, zu mongo/influx exklusive Auswahl für die laufenden Messwerte. Schreibpfad
nutzt das bestehende Influx-Line-Protocol unverändert (common/victoria_post.js);
Lesepfad (sensorapi/databases/victoria.js + victoria2json.js) holt Rohdaten per
VictoriaMetrics' /api/v1/export und bucketet/aggregiert stundenweise clientseitig,
nach Mongo-Konvention (Stunden-Start als Label, kein Zeit-Shift nötig wie bei Influx).
Scope bewusst auf die schon heute per DBASE umschaltbaren Funktionen begrenzt
(getActData/getNoiseAVGData) - getAvgData/getLongAvg/getGeigerData bleiben wie bisher.

Docker-Compose um victoriametrics-Service ergänzt (Retention explizit auf 100y
gesetzt, da VictoriaMetrics sonst nach 1 Monat Daten löscht).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 21:31:06 +02:00
parent b1b8f39ff4
commit 23fe7d2ed2
12 changed files with 302 additions and 14 deletions
+55
View File
@@ -0,0 +1,55 @@
/* Zugriff auf VictoriaMetrics per HTTP (InfluxDB-Line-Protocol-kompatibler Write-Endpunkt)
Gemeinsam genutzt von readin (Live-API) und readarchive (CSV-Archiv).
*/
import axios from 'axios'
import { logit, logerror } from './logit.js'
import { statistics } from './statistics.js'
import { DateTime } from 'luxon'
let VICTORIAHOST = process.env.VICTORIAHOST || "localhost"
let VICTORIAPORT = process.env.VICTORIAPORT || 8428
const VICTORIAURL_WRITE = `http://${VICTORIAHOST}:${VICTORIAPORT}/write?precision=ms`
// `${e}` liefert bei einem AggregateError nur "AggregateError" - die einzelnen
// Verbindungsfehler (je einer pro aufgeloester IP) stecken in e.errors bzw. e.cause.errors
function describeError(e) {
const sub = e.errors || e.cause?.errors
if (sub?.length) {
return `${e.message || e.name}: ` + sub.map(s => `${s.code} ${s.address}:${s.port}`).join(', ')
}
if (e.response) {
return `HTTP ${e.response.status} ${JSON.stringify(e.response.data)}`
}
return `${e.code ? e.code + ' ' : ''}${e.message || e}`
}
// liefert true, wenn VictoriaMetrics die Daten uebernommen hat, sonst false
export const victoriaWrite = async (data) => {
let start = DateTime.now()
let ok = false
try {
const ret = await axios({
method: 'post',
url: VICTORIAURL_WRITE,
data: data,
headers: {
Accept: 'application/json',
'Content-Type': 'text/plain; charset=utf-8'
},
timeout: 10000,
})
if (ret.status != 204) {
logerror(`doWrite2API Status: ${ret.status}`)
} else {
ok = true
}
} catch (e) {
logerror(`doWrite2API ${VICTORIAURL_WRITE} ${describeError(e)}`)
}
statistics['writeVictoriaData[sensor_data]Time'] = DateTime.now().diff(start, ['seconds']).toObject().seconds
logit(`Victoria-Write-Time: ${start.diffNow('seconds').toObject().seconds * -1} sec`)
return ok
}