237 lines
6.4 KiB
TypeScript
237 lines
6.4 KiB
TypeScript
// Grafana's classic import model prompts for the user's Prometheus data source.
|
|
// This template contains query definitions only, never credentials or player data.
|
|
const datasource = { type: "prometheus", uid: "${DS_PROMETHEUS}" };
|
|
const filter = 'job="minegeo",instance=~"$instance"';
|
|
const panels = [
|
|
[
|
|
"Scrape health",
|
|
"stat",
|
|
`min(up{${filter}})`,
|
|
"short",
|
|
"Shows whether Prometheus can scrape MineGeo. 1 = healthy, 0 = failed.",
|
|
],
|
|
[
|
|
"Registered accounts",
|
|
"stat",
|
|
`sum(minegeo_accounts{${filter}})`,
|
|
"short",
|
|
"Currently retained profiles.",
|
|
],
|
|
[
|
|
"Published maps",
|
|
"stat",
|
|
`sum(minegeo_maps{${filter},state="published"})`,
|
|
"short",
|
|
"Maps available in the public catalog.",
|
|
],
|
|
[
|
|
"Published panoramas",
|
|
"stat",
|
|
`sum(minegeo_published_panoramas{${filter}})`,
|
|
"short",
|
|
"Playable panorama locations in published maps.",
|
|
],
|
|
[
|
|
"Solo games started · last 24h",
|
|
"stat",
|
|
`sum(minegeo_games_started_24h{${filter}})`,
|
|
"short",
|
|
"Rolling 24-hour window, not a counter or page-view total.",
|
|
],
|
|
[
|
|
"Parties created · last 24h",
|
|
"stat",
|
|
`sum(minegeo_rooms_created_24h{${filter}})`,
|
|
"short",
|
|
"Rolling 24-hour count of created multiplayer rooms.",
|
|
],
|
|
[
|
|
"Map catalog over time",
|
|
"timeseries",
|
|
`sum by (state) (minegeo_maps{${filter}})`,
|
|
"short",
|
|
"Current retained map inventory. Counts can decrease after deletion.",
|
|
],
|
|
[
|
|
"Solo games by difficulty and completion",
|
|
"timeseries",
|
|
`sum by (difficulty,status) (minegeo_games{${filter}})`,
|
|
"short",
|
|
"Incomplete includes abandoned games. Complete means all five rounds ended.",
|
|
],
|
|
[
|
|
"Multiplayer room lifecycle",
|
|
"timeseries",
|
|
`sum by (state) (minegeo_rooms{${filter}})`,
|
|
"short",
|
|
"Stored room lifecycle states. These are not a count of online users.",
|
|
],
|
|
[
|
|
"Upload processing",
|
|
"timeseries",
|
|
`sum by (state) (minegeo_upload_jobs{${filter}})`,
|
|
"short",
|
|
"Queued, running, completed, failed and cancelled jobs.",
|
|
],
|
|
[
|
|
"Player bug reports",
|
|
"timeseries",
|
|
`sum by (state) (minegeo_bug_reports{${filter}})`,
|
|
"short",
|
|
"Retained reports. Closed reports are deleted after three days, so counts may fall.",
|
|
],
|
|
[
|
|
"Content moderation reports",
|
|
"timeseries",
|
|
`sum by (state) (minegeo_content_reports{${filter}})`,
|
|
"short",
|
|
"Open and resolved map-content reports.",
|
|
],
|
|
[
|
|
"Discord delivery",
|
|
"timeseries",
|
|
`sum by (state) (minegeo_discord_announcements{${filter}})`,
|
|
"short",
|
|
"Retained announcement delivery states.",
|
|
],
|
|
[
|
|
"Exporter read time",
|
|
"timeseries",
|
|
`max(minegeo_exporter_read_duration_seconds{${filter}})`,
|
|
"s",
|
|
"Time spent reading and validating a database snapshot; not site request latency.",
|
|
],
|
|
[
|
|
"Snapshot age",
|
|
"timeseries",
|
|
`time() - min(minegeo_snapshot_timestamp_seconds{${filter}})`,
|
|
"s",
|
|
"Snapshot age grows when scraping stops. The database caches aggregates for 30 seconds.",
|
|
],
|
|
] as const;
|
|
|
|
export function grafanaDashboard() {
|
|
return {
|
|
__inputs: [
|
|
{
|
|
name: "DS_PROMETHEUS",
|
|
label: "Prometheus",
|
|
description: "Choose the Prometheus data source that scrapes MineGeo.",
|
|
type: "datasource",
|
|
pluginId: "prometheus",
|
|
pluginName: "Prometheus",
|
|
},
|
|
],
|
|
id: null,
|
|
uid: "minegeo-community",
|
|
title: "MineGeo · Community analytics",
|
|
version: 1,
|
|
schemaVersion: 39,
|
|
tags: ["minegeo", "prometheus"],
|
|
timezone: "browser",
|
|
editable: true,
|
|
graphTooltip: 1,
|
|
refresh: "1m",
|
|
time: { from: "now-24h", to: "now" },
|
|
description:
|
|
"Aggregate MineGeo product metrics. All MineGeo series are gauges; no personal data or per-process counters. History starts when Prometheus begins scraping.",
|
|
templating: {
|
|
list: [
|
|
{
|
|
name: "instance",
|
|
label: "MineGeo instance",
|
|
type: "query",
|
|
datasource,
|
|
query: {
|
|
query: 'label_values(minegeo_accounts{job="minegeo"}, instance)',
|
|
refId: "instance",
|
|
},
|
|
refresh: 1,
|
|
multi: false,
|
|
includeAll: false,
|
|
sort: 1,
|
|
},
|
|
],
|
|
},
|
|
panels: panels.map(([title, type, expr, unit, description], index) => {
|
|
const stat = index < 6;
|
|
return {
|
|
id: index + 1,
|
|
title,
|
|
type,
|
|
description,
|
|
datasource,
|
|
gridPos: stat
|
|
? { x: (index % 3) * 8, y: Math.floor(index / 3) * 4, w: 8, h: 4 }
|
|
: {
|
|
x: ((index - 6) % 2) * 12,
|
|
y: 8 + Math.floor((index - 6) / 2) * 8,
|
|
w: 12,
|
|
h: 8,
|
|
},
|
|
targets: [
|
|
{
|
|
refId: "A",
|
|
expr,
|
|
datasource,
|
|
legendFormat: "{{state}} {{difficulty}} {{status}}",
|
|
range: !stat,
|
|
instant: stat,
|
|
},
|
|
],
|
|
fieldConfig: {
|
|
defaults: {
|
|
unit,
|
|
min: 0,
|
|
decimals: unit === "short" ? 0 : 2,
|
|
color: { mode: stat ? "thresholds" : "palette-classic" },
|
|
thresholds: {
|
|
mode: "absolute",
|
|
steps:
|
|
index === 0
|
|
? [
|
|
{ color: "red", value: null },
|
|
{ color: "green", value: 1 },
|
|
]
|
|
: [{ color: "green", value: null }],
|
|
},
|
|
...(stat
|
|
? {}
|
|
: {
|
|
custom: {
|
|
drawStyle: "line",
|
|
lineInterpolation: "smooth",
|
|
lineWidth: 2,
|
|
fillOpacity: 12,
|
|
showPoints: "never",
|
|
spanNulls: false,
|
|
},
|
|
}),
|
|
},
|
|
overrides: [],
|
|
},
|
|
options: stat
|
|
? {
|
|
colorMode: "value",
|
|
graphMode: "area",
|
|
justifyMode: "auto",
|
|
textMode: "auto",
|
|
reduceOptions: {
|
|
calcs: ["lastNotNull"],
|
|
fields: "",
|
|
values: false,
|
|
},
|
|
}
|
|
: {
|
|
legend: {
|
|
displayMode: "list",
|
|
placement: "bottom",
|
|
showLegend: true,
|
|
},
|
|
tooltip: { mode: "multi", sort: "desc" },
|
|
},
|
|
};
|
|
}),
|
|
};
|
|
}
|