Feature Specification: Resource otel
Created: 2026-10-07
Status: Implemented
Input: Reconstructed from the code at 093e68b6f (core/resources/otel/default.nix, core/resources/otel/test.nix, core/setups/hosts-common.nix, core/components/hosting-provider/windmill/default.nix, core/components/hosting-provider/windmill-otel.nix, core/components/hosting-provider/netbox/default.nix), pull requests #1184, #1205 and #1206.
User Scenarios & Testing (mandatory)
The otel resource lets an application send OpenTelemetry signals to the
collector of its deployment. The policy holds the OTLP endpoint. For each
enabled request, apply sets fediversity.otel.endpoints.<consumerName> on
the node. The OTel module of each application renders its settings from that
entry. The shared
resource rules are in the resource family spec.
User Story 1 - Send telemetry from an application (Priority: P1)
An operator of the hosting provider wants traces and metrics from windmill
and netbox. Each component requests "otel".otel with enable = true and its
consumerName, and imports its OTel module (windmill-otel.nix, netbox/otel.nix). The module sets
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL,
OTEL_SERVICE_NAME and OTEL_RESOURCE_ATTRIBUTES on the services. For
netbox, it also wraps gunicorn and netbox rqworker in
opentelemetry-instrument.
Why this priority: telemetry from the platform services is the purpose of the resource.
Independent Test: nix-unit-resources-otel, tests
test-endpoint-flows-to-windmill and test-endpoint-flows-to-netbox, and
test-otel-wiring.
Acceptance Scenarios:
- Given the policy
endpoint = "http://otel.example:4318", When thewindmillnode evaluates, Thensystemd.services.windmill-server.environment.OTEL_EXPORTER_OTLP_ENDPOINTis that endpoint. - Given the same policy, When the
netboxnode evaluates, Thensystemd.services.netbox.environment.OTEL_EXPORTER_OTLP_ENDPOINTis that endpoint.
User Story 2 - Find the collector of the deployment (Priority: P1)
A node of the deployment provides otel. core/setups/hosts-common.nix
sets the policy endpoint with mkDefault to
http://<host of the otel provider>:4318. The traffic uses plain HTTP on the
internal network. An environment can replace the endpoint.
Why this priority: without an endpoint, no application sends telemetry.
Independent Test: nix-unit-resources-otel, test
test-endpoint-defaults-to-group-collector.
Acceptance Scenarios:
- Given a deployment with a node that provides
oteland no override, When thewindmillnode evaluates, Then the endpoint ishttp://<fqdn of that node>:4318.
User Story 3 - Keep telemetry off (Priority: P2)
A deployment has no collector, or an environment sets endpoint = null.
apply returns an empty list. fediversity.otel.endpoints has no entry, and
no service gets OTel settings.
Why this priority: an application must not send signals to an address that does not exist.
Independent Test: nix-unit-resources-otel, test
test-endpoint-absent-with-null-override.
Acceptance Scenarios:
- Given
endpoint = null, When thewindmillnode evaluates, Thenwindmill-serverhas noOTEL_EXPORTER_OTLP_ENDPOINT.
Edge Cases
- When no request on a node is enabled,
applyadds no module, also when an endpoint is set. - The result applies to one consumer. An application on the same node that imports an OTel module but does not request the resource gets no OTel settings.
Requirements (mandatory)
Functional Requirements
- FR-001: The request MUST accept
enable(defaultfalse) andconsumerName. The request MUST contain only data, so that it can be written to JSON. - FR-002: The policy MUST accept
endpoint, a string ornull(defaultnull). - FR-003:
applyMUST return[ ]whenendpointisnull. - FR-004:
applyMUST otherwise return, for each request withenable = true, a module that importscore/resources/otel/option.nixand setsfediversity.otel.endpoints.<consumerName>toendpoint. - FR-005:
core/setups/hosts-common.nixMUST defaultendpointtohttp://<host of the otel provider>:4318when a node of the deployment providesotel, and tonullotherwise. - FR-006:
core/setups/hosts-common.nixMUST add theprocessoutput to theimportsof each node.
Key Entities
endpoint: the OTLP HTTP endpoint of the collector, for examplehttp://otel-collector.vpn:4318.fediversity.otel.endpoints.<consumerName>: the endpoint on the application node, declared incore/resources/otel/option.nix. It is absent when the request is not enabled or the policy has no endpoint. The OTel module of each application imports the option file and reads the entry.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001:
nix-unit-resources-otel(4 tests) andnix-unit-resources-plain-requestspass.
Assumptions
- The collector listens for OTLP over HTTP on port
4318. The comment incore/setups/hosts-common.nixsays that the port must match thehttpPortdefault of the collector. - The internal network is trusted, so the signals travel without TLS.
Known Deviations
None.