From 17288589ef1c459479d60081c7c69c33ee2561b5 Mon Sep 17 00:00:00 2001 From: atlas Date: Mon, 24 Aug 2026 18:27:44 +0200 Subject: [PATCH] feat(swarm-grafana): provision the log store as a datasource, with logs drilldown Grafana could reach the swarm's metrics and not its logs, so the store that landed with the collector pipeline had no reader. Adds the VictoriaLogs datasource plugin and the Logs Drilldown app, and provisions the datasource beside the metrics one. The drilldown matters as much as the connection: an unfamiliar log stream is explorable without writing a LogsQL query first, which is the difference between a store you can query and one you can use. --- nix/host-modules/swarm-grafana.nix | 56 ++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/nix/host-modules/swarm-grafana.nix b/nix/host-modules/swarm-grafana.nix index c85b8f9c..4b5258a9 100644 --- a/nix/host-modules/swarm-grafana.nix +++ b/nix/host-modules/swarm-grafana.nix @@ -22,6 +22,7 @@ let tlsCfg = hyperhiveCfg.tls; autheliaCfg = hyperhiveCfg.swarm.authelia; vmCfg = hyperhiveCfg.swarm.victoriametrics; + vlCfg = hyperhiveCfg.swarm.victorialogs; swarmDomain = hyperhiveCfg.swarm.domain; caTrust = import ./lib/hive-ca-trust.nix { inherit lib tlsCfg gatewayCfg; }; @@ -32,6 +33,11 @@ let # than an error. datasourceUid = "swarm-victoriametrics"; + # The logs store's own uid. Separate from the metrics one and spelled once for + # the same reason: a dashboard panel names it, and a second literal would be + # free to drift into a panel that renders empty rather than erroring. + logsDatasourceUid = "swarm-victorialogs"; + # The shipped dashboards carry `@datasourceUid@` where a real deployment needs # the uid above. They are substituted here rather than committed with the # literal so the single binding stays single. @@ -174,6 +180,21 @@ in ''; }; + logsDatasourceUrl = lib.mkOption { + type = lib.types.str; + default = "http://127.0.0.1:${toString vlCfg.port}"; + defaultText = lib.literalExpression ''"http://127.0.0.1:''${toString services.hyperhive.swarm.victorialogs.port}"''; + description = '' + Where the provisioned logs datasource points. Same reasoning as + {option}`services.hyperhive.swarm.grafana.datasourceUrl`: the store + binds loopback, so a Grafana elsewhere could not reach it anyway. + + Provisioned unconditionally, like the metrics datasource — the store + being off is a deployment choice rather than a reason to withhold the + connection, and an operator whose logs live elsewhere sets this. + ''; + }; + oidc = { clientId = lib.mkOption { type = lib.types.str; @@ -211,8 +232,24 @@ in plugins = lib.mkOption { type = lib.types.listOf lib.types.package; - default = [ pkgs.grafanaPlugins.grafana-metricsdrilldown-app ]; - defaultText = lib.literalExpression "[ pkgs.grafanaPlugins.grafana-metricsdrilldown-app ]"; + default = [ + pkgs.grafanaPlugins.grafana-metricsdrilldown-app + # Reading the swarm's logs needs both halves: the datasource that can + # speak LogsQL, and the browser that makes an unfamiliar log stream + # explorable without writing a query first. + # + # ⚠️ The app's plugin id is `grafana-lokiexplore-app` and its name is + # "Grafana Logs Drilldown" — Grafana renamed the product and kept the + # id. Searching nixpkgs for "logsdrilldown" finds nothing. + pkgs.grafanaPlugins.victoriametrics-logs-datasource + pkgs.grafanaPlugins.grafana-lokiexplore-app + ]; + defaultText = lib.literalExpression '' + [ + pkgs.grafanaPlugins.grafana-metricsdrilldown-app + pkgs.grafanaPlugins.victoriametrics-logs-datasource + pkgs.grafanaPlugins.grafana-lokiexplore-app + ]''; example = lib.literalExpression "[ pkgs.grafanaPlugins.grafana-piechart-panel ]"; description = '' Grafana plugins to install, as packages. Declarative rather than @@ -608,6 +645,21 @@ in access = "proxy"; isDefault = true; } + { + name = "VictoriaLogs"; + # The plugin's own id, read from its `plugin.json` rather + # than guessed. A `type` Grafana does not recognise is + # provisioned without complaint and every query against it + # fails at use, far from anything naming this file. + type = "victoriametrics-logs-datasource"; + uid = logsDatasourceUid; + url = cfg.logsDatasourceUrl; + access = "proxy"; + # Exactly one datasource may claim this, and metrics has it: + # two defaults is a coin toss over which one an untyped panel + # gets. + isDefault = false; + } ]; };