This page holds the work instructions for each product team to bring its product onto the telemetry contract. It covers two decisions in the decision log:
trace.id as the correlation identifier.<product>-<env>, and the plane attaches that name as a label.The contract states the rule; this page states what each repository has to change. When an item is finished:
If an instruction turns out to be wrong for your codebase, fix this page rather than working around it. The next team will hit the same thing.
| Team | Repository | State (2026-10-12) |
|---|---|---|
| jakemon | ~/source/jakemon | Done. It attaches service and service_instance to product metrics and logs. Live instances: wiki-prod, crafter-prod, roller-prod (logs only), wiki-dev and crafter-dev. |
| Wikantik | ~/source/jspwiki | Not started. Its logs are already ECS JSON. It needs service.name, ECS context keys, trace.id, and an updated conformance script. |
| Roller | ~/source/roller | Not started. It logs plain text and has no /metrics. |
| CrafterCMS | third-party | No work. jakemon labels it; its log format is not ours to change. |
instance, service or service_instance on /metrics, and never put those names in log lines as labels. The plane owns them.repo-* on docker1, and production Roller is roller-* on docker2. If you rename a compose project or a container, tell jakemon before you deploy, or your logs lose their service_instance.apps.alloy.trace.id, transaction.id or any other per-request value a Loki label. See the contract, §2.~/source/jspwiki)Wikantik already uses log4j2's ECS layout. LogQL's | json and Loki's detected_level work on its lines today, so these items close the remaining gaps.
W1. Name the service. In docker/config/log4j2-docker.xml, change the EventTemplateAdditionalField key from application to service.name. Keep the value wikantik.
W2. Rename the request filter's context keys to ECS names. These are in wikantik-observability/src/main/java/com/wikantik/observability/RequestCorrelationFilter.java:
| Current key | ECS key |
|---|---|
requestId | transaction.id |
method | http.request.method |
uri | url.path |
remoteAddr | client.ip |
userAgent | user_agent.original |
RequestCorrelationFilterTest reads requestId; update it as well.
W3. Add trace.id in the same filter.
traceparent header.X-Correlation-Id.Put the identifier in the ThreadContext as trace.id, and clear it when the request ends, as the filter already does for its other keys.
W4. Propagate the identifier. Send traceparent and X-Correlation-Id on every outbound call, including MCP tool calls to other stack members.
W5. Name events and namespace extra fields.
event.action (page_view, bundle_assembled).wikantik.*. W6. Update the conformance script (bin/simple-agility-conformance.sh). The other products depend on this.
@timestamp, log.level, message and service.name.trace.id instead of correlation_id."log.level") or nested ({"log": {"level": …}}).Done when:
traceparent header can be found with {service_instance="wiki-prod"} | json | trace_id="<that trace-id>" in Loki.bin/simple-agility-conformance.sh passes against production.~/source/roller)Coding Agent Execution Blueprint: The complete, code-level execution specification for items R1 through R5 is detailed in RollerTelemetryHandoffSpec. Consult it for exact Maven XML, Log4j2 additivity requirements,
TraceCorrelationFilter.javareference implementation, and port 8090 Actuator configuration.
Roller is Spring Boot 4.1 on log4j2, and it already depends on Actuator.
R1. Log ECS JSON to the console. In app/src/main/resources/log4j2.xml, replace the console appender's PatternLayout with:
<JsonTemplateLayout eventTemplateUri="classpath:EcsLayout.json">
<EventTemplateAdditionalField key="service.name" value="roller"/>
</JsonTemplateLayout>
org.apache.logging.log4j:log4j-layout-template-json dependency. Its version comes from the existing log4j-bom (2.26.1). R2. Add a request filter that puts trace.id and transaction.id into the log4j ThreadContext.
trace.id is resolved in the same order as Wikantik W3.transaction.id is a fresh identifier for each request. R3. Propagate the identifier. Send traceparent and X-Correlation-Id on outbound calls to listmonk, Umami and Keycloak.
R4. Name events and namespace extra fields. Use event.action for events, put Roller-specific fields under roller.*, and add no new top-level keys.
R5. Expose metrics and health.
micrometer-registry-prometheus.prometheus and health endpoints.roller_.roller-prod gains metrics.Done when:
{service_instance="roller-prod", container="roller-app-1"} | json | log_level="ERROR" returns parsed lines.up{service_instance="roller-prod"} is 1.bin/simple-agility-conformance.sh passes. This needs Wikantik's W6 first.trace.id propagation;/metrics with your prefix;<product>-<env>) for metrics and logs.service and service_instance (2026-10-12, jakemon 6d86140).discovery.relabel "products" hook. bin/validate.sh enforces the hook and the <product>-<env> form (2026-10-12, 6d86140).service means only the product on the plane. The per-systemd-unit resource series use unit (2026-10-12, 6d86140).Cluster Hub: Simple Agility Stack Hub (simple-agility)