diff --git a/docs/scheduler/observability.md b/docs/scheduler/observability.md index 272d1558..5f836a88 100644 --- a/docs/scheduler/observability.md +++ b/docs/scheduler/observability.md @@ -377,6 +377,8 @@ this change removed them in favour of the log line. The hive tier's own collector runs a `journald` receiver scoped to the units in `services.hyperhive.otel.journalUnits`: `hive-c0re.service`, plus `squid.service` and `squid-selfcheck.service` (see [Egress proxy](../networking/network.md#egress-proxy-squid)). +A host that runs the cache without the swarm collector adds `swarm-bao-attic-secret.service` +and `swarm-bao-attic-tokens.service`. No bind mount is needed. Unlike an agent's journal, this collector already shares a filesystem with the units it reads, because it's a host systemd service rather than a container. It forwards the crash log line alongside the diff --git a/docs/swarm/services.md b/docs/swarm/services.md index 7f248268..7cb0f4ee 100644 --- a/docs/swarm/services.md +++ b/docs/swarm/services.md @@ -453,8 +453,11 @@ file to copy. The builder pushes green builds to it. How it works, and the external alternative, are in [`builder.md`](builder.md#binary-cache). The container forwards atticd's journal to the swarm collector like the other -service containers (see [Telemetry collector](#telemetry-collector-otel)). The two host units' lines -stay in the host's journal. +service containers (see [Telemetry collector](#telemetry-collector-otel)). The two host +units' lines reach the log store too: through the hive collector's journal +allow-list on a hive host, or through the swarm collector's whole-journal +receiver where the host runs that. A host with neither keeps them in its own +journal. ### CI metrics diff --git a/nix/host-modules/swarm-attic.nix b/nix/host-modules/swarm-attic.nix index 6e992f0c..d931fb5f 100644 --- a/nix/host-modules/swarm-attic.nix +++ b/nix/host-modules/swarm-attic.nix @@ -233,6 +233,14 @@ in services.hyperhive.gateway.localNames = [ atticCfg.domain ]; + # The init units' journal reaches the log store through the hive collector. + # A host that also runs the swarm collector ships its whole journal already + # (./swarm-otel.nix), so naming them there would send each line twice. + services.hyperhive.otel.journalUnits = lib.optionals (!hyperhiveCfg.deploy.swarm-otel.enable) [ + "swarm-bao-attic-secret.service" + "swarm-bao-attic-tokens.service" + ]; + # This host serves the vhost, and the host's own resolver finds the name. services.hyperhive.gateway.enable = lib.mkDefault true; services.hyperhive.gateway.dns.enable = lib.mkDefault true; diff --git a/nix/module-eval/builder.nix b/nix/module-eval/builder.nix index 1f33645e..944499fc 100644 --- a/nix/module-eval/builder.nix +++ b/nix/module-eval/builder.nix @@ -95,7 +95,7 @@ let atticVhost = atticHere.services.hyperhive.gateway.vhosts."attic.t.local"; # The cache switched on while the operator overrides the options. - atticByHand = hive { + atticByHand = hiveWithController { deploy.bao.enable = true; deploy.attic.enable = true; swarm.attic.domain = "cache.example.org"; @@ -388,6 +388,33 @@ let && atticHere.systemd.services ? swarm-bao-attic-secret && atticHere.systemd.services ? swarm-bao-attic-tokens; } + { + # The hive collector's journal allow-list carries the cache's init units + # on a hive host with the cache and no swarm collector (`atticByHand`). + # Where the swarm collector runs too (`atticHere`) it reads the whole + # journal, so the units are not named twice; without the cache + # (`atticExternal`) they are absent. `hive-c0re.service` is the control + # that each list is the one the collector reads. + name = "the hive collector ships the cache's init units only where nothing else reads the host journal"; + ok = + let + units = m: m.services.opentelemetry-collector.settings.receivers.journald.units; + initUnits = [ + "swarm-bao-attic-secret.service" + "swarm-bao-attic-tokens.service" + ]; + has = m: lib.all (u: lib.elem u (units m)) initUnits; + hasNone = m: lib.all (u: !(lib.elem u (units m))) initUnits; + in + has atticByHand + && hasNone atticHere + && hasNone atticExternal + && lib.all (m: lib.elem "hive-c0re.service" (units m)) [ + atticByHand + atticHere + atticExternal + ]; + } { # Both host units log in as the cache's principal, not the hive's, and # the container reaches the key through a read-only directory. The