dimensionlab-website/src/lib/model/fixtures/dimensionlab.ts
2026-06-18 19:09:42 +02:00

595 lines
18 KiB
TypeScript

import {
DASHBOARD_SCHEMA_VERSION,
type DashboardDocument,
type DatasourceReference,
type MetricValue,
type ServiceEntry,
type ServiceGroup,
type Severity,
type TelemetryCard,
} from "../schema";
type NumericValueKind = "percent" | "bytes" | "temperature" | "latency" | "number";
interface MetricSeed {
id: string;
label: string;
icon: string;
kind: NumericValueKind;
value: number;
detail: string;
severity: Severity;
datasource: DatasourceReference;
thresholds?: TelemetryCard["thresholds"];
sparkline?: number[];
precision?: number;
}
interface ServiceSeed {
id: string;
label: string;
description: string;
icon: string;
datasource: DatasourceReference;
href?: string;
severity?: Severity;
detail?: string;
}
export const dimensionLabDashboardFixture: DashboardDocument = {
schemaVersion: DASHBOARD_SCHEMA_VERSION,
metadata: {
title: "System Overview",
subtitle: "Dimension Lab home infra, GPU, and automation surface",
description:
"Initial Dimension Lab dashboard seed data. Runtime values are fallback values until datasource adapters are enabled.",
timezone: "Europe/Amsterdam",
refreshIntervalSeconds: 15,
},
layout: {
density: "dense",
telemetry: [
"infra-ram",
"gpu-host-ram",
"network-ram",
"user-disk-peak",
"system-disk-peak",
"peak-cpu-busy",
"top-cpu-container",
"top-ram-container",
"gpu-3060-load",
"gpu-3060-vram",
"gpu-3060-temp",
"gpu-3060-fan",
"gpu-3090-load",
"gpu-3090-vram",
"gpu-3090-temp",
"gpu-3090-fan",
],
serviceGroups: ["essentials", "monitoring", "ai-automation", "systems", "runtime-health"],
statusStrips: ["footer-status"],
modules: ["weather-amsterdam", "runtime-health-summary"],
},
telemetry: [
metric({
id: "infra-ram",
label: "Infra RAM",
icon: "mdi:memory",
kind: "percent",
value: 19,
detail: "fallback - linux-infra memory used",
severity: "ok",
thresholds: percentThresholds(),
datasource: prometheus(
'100 * (1 - node_memory_MemAvailable_bytes{instance="linux-infra"} / node_memory_MemTotal_bytes{instance="linux-infra"})',
),
sparkline: [18, 18, 19, 19, 18, 19],
}),
metric({
id: "gpu-host-ram",
label: "GPU Host RAM",
icon: "mdi:memory",
kind: "percent",
value: 17,
detail: "fallback - GPU host memory used",
severity: "ok",
thresholds: percentThresholds(),
datasource: prometheus(
'100 * (1 - node_memory_MemAvailable_bytes{instance="linux-gpu"} / node_memory_MemTotal_bytes{instance="linux-gpu"})',
),
sparkline: [16, 16, 17, 17, 17, 17],
}),
metric({
id: "network-ram",
label: "Network RAM",
icon: "mdi:router-network",
kind: "percent",
value: 5,
detail: "fallback - network core memory used",
severity: "ok",
thresholds: percentThresholds(),
datasource: prometheus(
'100 * (1 - node_memory_MemAvailable_bytes{instance="network-core"} / node_memory_MemTotal_bytes{instance="network-core"})',
),
sparkline: [5, 5, 5, 6, 5, 5],
}),
metric({
id: "user-disk-peak",
label: "User Disk Peak",
icon: "mdi:harddisk",
kind: "percent",
value: 29,
detail: "fallback - /home peak usage",
severity: "ok",
thresholds: percentThresholds(80, 92),
datasource: prometheus(
'100 * (1 - node_filesystem_avail_bytes{mountpoint="/home"} / node_filesystem_size_bytes{mountpoint="/home"})',
),
sparkline: [27, 27, 28, 29, 29, 29],
}),
metric({
id: "system-disk-peak",
label: "System Disk Peak",
icon: "mdi:harddisk",
kind: "percent",
value: 49,
detail: "fallback - /boot peak usage",
severity: "ok",
thresholds: percentThresholds(80, 92),
datasource: prometheus(
'100 * (1 - node_filesystem_avail_bytes{mountpoint="/boot"} / node_filesystem_size_bytes{mountpoint="/boot"})',
),
sparkline: [48, 48, 49, 49, 49, 49],
}),
metric({
id: "peak-cpu-busy",
label: "Peak CPU Busy",
icon: "mdi:cpu-64-bit",
kind: "percent",
value: 3,
detail: "fallback - linux-infra 5m CPU busy",
severity: "ok",
thresholds: percentThresholds(75, 90),
datasource: prometheus(
'100 - (avg by(instance) (rate(node_cpu_seconds_total{instance="linux-infra",mode="idle"}[5m])) * 100)',
),
sparkline: [2, 3, 3, 4, 3, 3],
}),
metric({
id: "top-cpu-container",
label: "Top CPU Container",
icon: "mdi:docker",
kind: "percent",
value: 7.9,
precision: 1,
detail: "fallback - top container CPU pending label mapping",
severity: "ok",
thresholds: percentThresholds(70, 90),
datasource: placeholder(
"fallback top-container CPU query pending container label normalization",
),
sparkline: [6.1, 6.4, 7.0, 7.5, 7.2, 7.9],
}),
metric({
id: "top-ram-container",
label: "Top RAM Container",
icon: "mdi:docker",
kind: "bytes",
value: Math.round(5.2 * 1024 ** 3),
precision: 1,
detail: "fallback - top container RAM pending label mapping",
severity: "danger",
thresholds: { warning: 3 * 1024 ** 3, danger: 5 * 1024 ** 3 },
datasource: placeholder(
"fallback top-container memory query pending container label normalization",
),
sparkline: [
3.1 * 1024 ** 3,
3.5 * 1024 ** 3,
4.1 * 1024 ** 3,
4.8 * 1024 ** 3,
5.0 * 1024 ** 3,
5.2 * 1024 ** 3,
],
}),
metric({
id: "gpu-3060-load",
label: "3060 GPU Load",
icon: "mdi:expansion-card",
kind: "percent",
value: 0,
detail: "fallback - RTX 3060 GPU utilization",
severity: "ok",
thresholds: percentThresholds(85, 95),
datasource: prometheus('DCGM_FI_DEV_GPU_UTIL{gpu="rtx-3060"}'),
sparkline: [0, 0, 0, 0, 0, 0],
}),
metric({
id: "gpu-3060-vram",
label: "3060 VRAM",
icon: "mdi:memory",
kind: "percent",
value: 0,
detail: "fallback - RTX 3060 VRAM used",
severity: "ok",
thresholds: percentThresholds(80, 92),
datasource: prometheus(
'100 * DCGM_FI_DEV_FB_USED{gpu="rtx-3060"} / (DCGM_FI_DEV_FB_USED{gpu="rtx-3060"} + DCGM_FI_DEV_FB_FREE{gpu="rtx-3060"})',
),
sparkline: [0, 0, 0, 0, 0, 0],
}),
metric({
id: "gpu-3060-temp",
label: "3060 Temp",
icon: "mdi:thermometer",
kind: "temperature",
value: 54,
detail: "fallback - RTX 3060 temperature",
severity: "ok",
thresholds: { warning: 75, danger: 85 },
datasource: prometheus('DCGM_FI_DEV_GPU_TEMP{gpu="rtx-3060"}'),
sparkline: [52, 53, 54, 54, 53, 54],
}),
metric({
id: "gpu-3060-fan",
label: "3060 Fan Spin",
icon: "mdi:fan",
kind: "percent",
value: 0,
detail: "fallback - RTX 3060 fan duty",
severity: "ok",
thresholds: percentThresholds(80, 95),
datasource: prometheus('DCGM_FI_DEV_FAN_SPEED{gpu="rtx-3060"}'),
sparkline: [0, 0, 0, 0, 0, 0],
}),
metric({
id: "gpu-3090-load",
label: "3090 GPU Load",
icon: "mdi:expansion-card",
kind: "percent",
value: 0,
detail: "fallback - RTX 3090 GPU utilization",
severity: "ok",
thresholds: percentThresholds(85, 95),
datasource: prometheus('DCGM_FI_DEV_GPU_UTIL{gpu="rtx-3090"}'),
sparkline: [0, 0, 0, 0, 0, 0],
}),
metric({
id: "gpu-3090-vram",
label: "3090 VRAM",
icon: "mdi:memory",
kind: "percent",
value: 74,
detail: "fallback - RTX 3090 VRAM used",
severity: "warning",
thresholds: percentThresholds(70, 90),
datasource: prometheus(
'100 * DCGM_FI_DEV_FB_USED{gpu="rtx-3090"} / (DCGM_FI_DEV_FB_USED{gpu="rtx-3090"} + DCGM_FI_DEV_FB_FREE{gpu="rtx-3090"})',
),
sparkline: [68, 70, 72, 74, 73, 74],
}),
metric({
id: "gpu-3090-temp",
label: "3090 Temp",
icon: "mdi:thermometer",
kind: "temperature",
value: 50,
detail: "fallback - RTX 3090 temperature",
severity: "ok",
thresholds: { warning: 75, danger: 85 },
datasource: prometheus('DCGM_FI_DEV_GPU_TEMP{gpu="rtx-3090"}'),
sparkline: [49, 50, 50, 51, 50, 50],
}),
metric({
id: "gpu-3090-fan",
label: "3090 Fan Spin",
icon: "mdi:fan",
kind: "percent",
value: 0,
detail: "fallback - RTX 3090 fan duty",
severity: "ok",
thresholds: percentThresholds(80, 95),
datasource: prometheus('DCGM_FI_DEV_FAN_SPEED{gpu="rtx-3090"}'),
sparkline: [0, 0, 0, 0, 0, 0],
}),
],
serviceGroups: [
group("essentials", "Essentials", [
service({
id: "vaultwarden",
label: "Vaultwarden",
description: "Password manager",
icon: "simple-icons:vaultwarden",
href: "https://vault.dimensionlab.net",
datasource: httpStatus("https://vault.dimensionlab.net/alive"),
}),
service({
id: "forgejo",
label: "Forgejo",
description: "Git repositories",
icon: "simple-icons:forgejo",
href: "https://git.dimensionlab.net",
datasource: httpStatus("https://git.dimensionlab.net/api/healthz"),
}),
service({
id: "wiki",
label: "Wiki",
description: "Internal documentation",
icon: "simple-icons:wikidotjs",
href: "https://wiki.dimensionlab.net",
datasource: httpStatus("https://wiki.dimensionlab.net"),
}),
service({
id: "aws-start",
label: "AWS Start",
description: "AWS access portal",
icon: "simple-icons:amazonaws",
href: "https://dimensionlab.awsapps.com/start",
datasource: httpStatus("https://dimensionlab.awsapps.com/start"),
}),
]),
group("monitoring", "Monitoring", [
service({
id: "grafana",
label: "Grafana",
description: "Capacity and noise dashboard",
icon: "simple-icons:grafana",
href: "https://grafana.dimensionlab.net",
datasource: httpStatus("https://grafana.dimensionlab.net/api/health"),
}),
service({
id: "uptime-kuma",
label: "Uptime Kuma",
description: "Service uptime checks",
icon: "simple-icons:uptimekuma",
href: "https://uptime.dimensionlab.net",
datasource: httpStatus("https://uptime.dimensionlab.net/status/dimensionlab"),
}),
service({
id: "prometheus",
label: "Prometheus",
description: "Metrics database",
icon: "simple-icons:prometheus",
href: "https://prometheus.dimensionlab.net",
datasource: httpStatus("https://prometheus.dimensionlab.net/-/ready"),
}),
service({
id: "backrest",
label: "Backrest",
description: "Restic backup manager",
icon: "mdi:backup-restore",
href: "https://backups.dimensionlab.net",
datasource: httpStatus("https://backups.dimensionlab.net"),
}),
]),
group("ai-automation", "AI & Automation", [
service({
id: "n8n",
label: "n8n",
description: "Workflow automation",
icon: "simple-icons:n8n",
href: "https://workflows.dimensionlab.net",
datasource: httpStatus("https://workflows.dimensionlab.net/healthz"),
}),
service({
id: "open-webui",
label: "Open WebUI",
description: "Chat and model interface",
icon: "simple-icons:openwebui",
href: "https://webui.dimensionlab.net",
datasource: httpStatus("https://webui.dimensionlab.net/health"),
}),
service({
id: "comfyui",
label: "ComfyUI",
description: "Image generation workflows",
icon: "mdi:image-edit-outline",
href: "https://comfy.dimensionlab.net",
datasource: httpStatus("https://comfy.dimensionlab.net"),
}),
service({
id: "models",
label: "Models",
description: "Local model management",
icon: "mdi:brain",
href: "https://models.dimensionlab.net",
datasource: httpStatus("https://models.dimensionlab.net/api/tags"),
}),
]),
group("systems", "Systems", [
service({
id: "adminer",
label: "Adminer",
description: "PostgreSQL database browser",
icon: "simple-icons:adminer",
href: "https://db.dimensionlab.net",
datasource: httpStatus("https://db.dimensionlab.net"),
}),
service({
id: "assistant",
label: "Assistant",
description: "Personal AI agent gateway",
icon: "mdi:robot-outline",
href: "https://assistant.dimensionlab.net",
datasource: httpStatus("https://assistant.dimensionlab.net/health"),
}),
service({
id: "suna",
label: "Suna",
description: "AI command center",
icon: "mdi:account-hard-hat-outline",
href: "https://suna.dimensionlab.net",
datasource: httpStatus("https://suna.dimensionlab.net"),
}),
service({
id: "cockpit-infra",
label: "Cockpit Infra",
description: "linux-infra server console",
icon: "simple-icons:cockpit",
href: "https://infra-cockpit.dimensionlab.net",
datasource: httpStatus("https://infra-cockpit.dimensionlab.net"),
}),
]),
group("runtime-health", "Runtime Health", [
service({
id: "forgejo-ssh-relay",
label: "Forgejo SSH Relay",
description: "Public Git SSH relay",
icon: "simple-icons:forgejo",
href: "https://uptime.dimensionlab.net/status/dimensionlab",
datasource: custom("tcp:git.dimensionlab.net:22"),
detail: "fallback - uptime monitor pending",
}),
service({
id: "postgresql",
label: "PostgreSQL",
description: "Shared application database",
icon: "simple-icons:postgresql",
datasource: prometheus('pg_up{cluster="dimensionlab"}'),
detail: "fallback - postgres exporter pending",
}),
service({
id: "ollama-api",
label: "Ollama API",
description: "Local model API",
icon: "simple-icons:ollama",
datasource: httpStatus("http://linux-gpu:11434/api/tags"),
detail: "fallback - internal health check pending",
}),
service({
id: "node-exporter",
label: "Node Exporter",
description: "Host metrics exporter",
icon: "simple-icons:prometheus",
datasource: prometheus('up{job="node-exporter"}'),
detail: "fallback - exporter health from Prometheus",
}),
]),
],
statusStrips: [
{
id: "footer-status",
items: [
{ id: "system-status", label: "System Status", value: "Fallback operational", severity: "ok" },
{ id: "last-sync", label: "Last Sync", value: "fallback: 2 minutes ago", severity: "stale" },
{ id: "uptime", label: "Uptime", value: "fallback: 28d 14h 32m", severity: "ok" },
{ id: "load-avg", label: "Load Avg", value: "fallback: 0.47 0.53 0.59", severity: "neutral" },
],
},
],
modules: [
{
id: "weather-amsterdam",
kind: "weather",
title: "Amsterdam",
value: "28.3 C",
detail: "fallback - weather adapter pending",
icon: "mdi:weather-sunny",
severity: "ok",
datasource: {
type: "external",
adapter: "weather",
reference: "open-meteo:latitude=52.3676&longitude=4.9041",
},
},
{
id: "runtime-health-summary",
kind: "summary",
title: "Runtime Health",
value: "fallback",
detail: "fallback - health adapters pending",
icon: "mdi:pulse",
severity: "stale",
datasource: placeholder("summary pending live health aggregation"),
},
],
};
function metric(seed: MetricSeed): TelemetryCard {
return {
id: seed.id,
label: seed.label,
icon: seed.icon,
value: metricValue(seed.kind, seed.value, seed.precision),
detail: seed.detail,
severity: seed.severity,
thresholds: seed.thresholds,
datasource: seed.datasource,
sparkline: seed.sparkline,
};
}
function metricValue(
kind: NumericValueKind,
value: number,
precision?: number,
): MetricValue {
return precision === undefined ? { kind, value } : { kind, value, precision };
}
function service(seed: ServiceSeed): ServiceEntry {
const entry: ServiceEntry = {
id: seed.id,
label: seed.label,
description: seed.description,
icon: seed.icon,
severity: seed.severity || "ok",
detail: seed.detail || "fallback - health check pending",
datasource: seed.datasource,
};
if (!seed.href) return entry;
return {
...entry,
link: {
href: seed.href,
label: `Open ${seed.label}`,
external: true,
},
};
}
function group(id: string, title: string, services: ServiceEntry[]): ServiceGroup {
return {
id,
title,
layout: "list",
services,
};
}
function percentThresholds(warning = 80, danger = 92) {
return { warning, danger };
}
function prometheus(reference: string): DatasourceReference {
return {
type: "external",
adapter: "prometheus",
reference,
};
}
function httpStatus(url: string): DatasourceReference {
return {
type: "external",
adapter: "http-status",
reference: `GET ${url}`,
};
}
function custom(reference: string): DatasourceReference {
return {
type: "external",
adapter: "custom",
reference,
};
}
function placeholder(reason: string): DatasourceReference {
return {
type: "placeholder",
reason,
};
}