Watch
0
0
Fork
You've already forked hyperhive
0

hive collector runs only on hive hosts; review classifier pushes metrics through its forwarder

This commit is contained in:
atlas 2026-10-26 15:58:44 +01:00
commit 0cbfa806d3
9 changed files with 191 additions and 98 deletions

View file

@ -91,17 +91,16 @@ in
collector.enable = lib.mkOption {
type = lib.types.bool;
readOnly = true;
default =
config.services.hyperhive.deploy.hive-controller.enable
|| config.services.hyperhive.deploy.allSwarmServices;
defaultText = lib.literalExpression "deploy.hive-controller.enable || deploy.allSwarmServices";
default = config.services.hyperhive.deploy.hive-controller.enable;
defaultText = lib.literalExpression "deploy.hive-controller.enable";
description = ''
Whether this host runs the hive tier's collector. Not a switch:
every host that runs a hive
({option}`services.hyperhive.deploy.hive-controller.enable`) runs
one, and so does a host carrying all the swarm's shared services
({option}`services.hyperhive.deploy.allSwarmServices`), whose own
containers export to it.
one, and no other host does. It exists to stamp the `hive` label on
a hive's telemetry outside its agents' control, so a host without a
hive has nothing for it to label: the swarm services there export to
the swarm collector directly, each as its own client.
Agents export to it unauthenticated at
{option}`services.hyperhive.otel.collector.host`, a name this

View file

@ -39,7 +39,6 @@ let
autheliaCfg = hyperhiveCfg.swarm.authelia;
gatewayCfg = hyperhiveCfg.gateway;
networkCfg = hyperhiveCfg.network;
otelCfg = hyperhiveCfg.otel;
tlsCfg = hyperhiveCfg.deploy.hive-controller.tls;
machine = "swarm-review-classifier";
@ -55,6 +54,8 @@ let
# Loopback in the container's own netns, and distinct from the other service
# containers' forwarders all the same.
forwarderTelemetryPort = 8894;
# The standard OTLP/HTTP port, on the container's loopback.
forwarderOtlpPort = 4318;
# The daemon reaches authelia, the store and the queue by name over TLS, and
# in self-signed mode their leaves chain to the hive CA.
@ -89,14 +90,15 @@ let
credential = id: "/run/credentials/${unit}.service/${id}";
forwarderCredential = id: "/run/credentials/${forwarderUnit}.service/${id}";
# What `claude` exports its metrics with, and the daemon its ACP runs' cost,
# where this host runs a hive-tier collector on the bridge. The daemon adds
# the repo and the PR to each `claude` run's resource attributes, and to
# each cost record's attributes.
otelEnv = lib.optionalAttrs otelCfg.collector.enable {
# What `claude` exports its metrics with, and the daemon its ACP runs' cost:
# the container's own forwarder, which pushes them to the swarm collector as
# this service's client, on every host. The daemon adds the repo and the PR
# to each `claude` run's resource attributes, and to each cost record's
# attributes.
otelEnv = {
CLAUDE_CODE_ENABLE_TELEMETRY = "1";
OTEL_METRICS_EXPORTER = "otlp";
OTEL_EXPORTER_OTLP_ENDPOINT = "http://${networkCfg.bridgeIp}:${toString hyperhiveCfg.swarm.hiveOtel.collectorPort}";
OTEL_EXPORTER_OTLP_ENDPOINT = "http://127.0.0.1:${toString forwarderOtlpPort}";
OTEL_EXPORTER_OTLP_PROTOCOL = "http/protobuf";
# Claude Code defaults to delta, which the metrics store drops.
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE = "cumulative";
@ -218,6 +220,7 @@ in
inherit clientId;
tokenUrl = "${autheliaCfg.url}/api/oidc/token";
telemetryPort = forwarderTelemetryPort;
otlpMetricsPort = forwarderOtlpPort;
store = {
package = baoDeploy.package;
addr = "https://${baoCfg.domain}:${toString baoCfg.port}";