Add developer API, Prometheus metrics, and community links
This commit is contained in:
236
shared/grafana-dashboard.ts
Normal file
236
shared/grafana-dashboard.ts
Normal file
@@ -0,0 +1,236 @@
|
||||
// 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" },
|
||||
},
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user