129 lines
3.0 KiB
JavaScript
129 lines
3.0 KiB
JavaScript
/**
|
|
* Canonical data-model helpers + JSDoc typedefs for metrics, anomalies, health.
|
|
*
|
|
* Wire shapes are JSON over protomux-rpc compact-encoding and REST /api/v*.
|
|
*/
|
|
|
|
/**
|
|
* @typedef {{
|
|
* nodeId: string,
|
|
* hostname: string,
|
|
* publicKeyHex: string,
|
|
* platform: string,
|
|
* arch: string,
|
|
* release: string,
|
|
* cpus: number,
|
|
* totalMemMiB: number,
|
|
* agentVersion: string,
|
|
* protocolVersion: number,
|
|
* startedAt: number,
|
|
* labels?: Record<string, string>,
|
|
* }} NodeInfo
|
|
*
|
|
* @typedef {{
|
|
* chart: string,
|
|
* context: string,
|
|
* ts: number,
|
|
* values: Record<string, number|null>,
|
|
* }} MetricSample
|
|
*
|
|
* @typedef {{
|
|
* chart: string,
|
|
* context: string,
|
|
* labels: string[],
|
|
* data: Array<[number, ...(number|null)[]]>,
|
|
* view_update_every?: number,
|
|
* }} QueryResult
|
|
*
|
|
* @typedef {{
|
|
* id: string,
|
|
* chart: string,
|
|
* context: string,
|
|
* dimension: string,
|
|
* severity: 'warning'|'critical',
|
|
* score: number,
|
|
* value: number,
|
|
* threshold: number,
|
|
* comparator: string,
|
|
* message: string,
|
|
* ts: number,
|
|
* cleared?: boolean,
|
|
* }} AnomalyEvent
|
|
*
|
|
* @typedef {{
|
|
* id: string,
|
|
* name: string,
|
|
* chart: string,
|
|
* dimension: string,
|
|
* status: 'CLEAR'|'WARNING'|'CRITICAL'|'UNDEFINED',
|
|
* value: number|null,
|
|
* units: string,
|
|
* info: string,
|
|
* lastStatusChange: number,
|
|
* config: AlertConfig,
|
|
* }} AlertState
|
|
*
|
|
* @typedef {{
|
|
* id: string,
|
|
* chart: string,
|
|
* dimension: string,
|
|
* warn?: number|null,
|
|
* crit?: number|null,
|
|
* comparator?: '>'|'<'|'>='|'<=',
|
|
* lookbackSec?: number,
|
|
* enabled?: boolean,
|
|
* info?: string,
|
|
* }} AlertConfig
|
|
*
|
|
* @typedef {{
|
|
* status: 'ok'|'degraded'|'critical',
|
|
* score: number,
|
|
* checks: Array<{ id: string, ok: boolean, detail: string }>,
|
|
* ts: number,
|
|
* }} HealthSnapshot
|
|
*
|
|
* @typedef {{
|
|
* id: string,
|
|
* name: string,
|
|
* status: 'queued'|'running'|'done'|'failed'|'cancelled',
|
|
* startedAt: number|null,
|
|
* finishedAt: number|null,
|
|
* result?: any,
|
|
* error?: string,
|
|
* }} JobRecord
|
|
*/
|
|
|
|
/**
|
|
* @param {Partial<MetricSample>} sample
|
|
* @returns {MetricSample}
|
|
*/
|
|
export function normalizeSample(sample) {
|
|
return {
|
|
chart: String(sample.chart || ''),
|
|
context: String(sample.context || sample.chart || ''),
|
|
ts: Number(sample.ts) || Date.now(),
|
|
values: sample.values && typeof sample.values === 'object' ? sample.values : {},
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {Partial<AnomalyEvent>} ev
|
|
* @returns {AnomalyEvent}
|
|
*/
|
|
export function normalizeAnomaly(ev) {
|
|
return {
|
|
id: String(ev.id || `${ev.chart}:${ev.dimension}:${ev.ts}`),
|
|
chart: String(ev.chart || ''),
|
|
context: String(ev.context || ev.chart || ''),
|
|
dimension: String(ev.dimension || ''),
|
|
severity: ev.severity === 'critical' ? 'critical' : 'warning',
|
|
score: Number(ev.score) || 0,
|
|
value: Number(ev.value),
|
|
threshold: Number(ev.threshold),
|
|
comparator: String(ev.comparator || '>'),
|
|
message: String(ev.message || ''),
|
|
ts: Number(ev.ts) || Date.now(),
|
|
cleared: Boolean(ev.cleared),
|
|
}
|
|
}
|