Skip to content

Add topology-driven log generation#145

Merged
andrewh merged 3 commits into
mainfrom
claude/serene-thompson-kjbkhr
Jun 11, 2026
Merged

Add topology-driven log generation#145
andrewh merged 3 commits into
mainfrom
claude/serene-thompson-kjbkhr

Conversation

@andrewh

@andrewh andrewh commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Closes issue 112 (topology-driven log and event generation).

Adds a logs: section to service and operation definitions, following the same design as topology-driven metrics: service-level entries are evaluated for every span in the service, operation-level entries only for that operation.

DSL

services:
  gateway:
    logs:
      - severity: INFO
        body: "handled {operation.name} method={http.request.method}"
    operations:
      handle:
        duration: 15ms
        logs:
          - severity: ERROR
            body: "upstream timeout for {operation.name}"
            condition: error
            at: end
            attributes:
              error.type:
                value: TimeoutError

Features

  • Severity: TRACE, DEBUG, INFO, WARN, ERROR, FATAL (case-insensitive), mapped to OTel log data model severity numbers with matching severity text
  • Body templates: {key} placeholders resolve against the record's own attributes, then span attributes, then service.name/operation.name built-ins; unresolved placeholders stay literal
  • Conditions: error, success, slow (slow uses --slow-threshold and never fires when the flag is unset); omitted = every span
  • Volume control: per-entry probability (0-1)
  • Timing: at: start|end anchor plus delay offset, applied to the record timestamp so it works with synthetic/offset time
  • Attributes: reuses the existing attribute generators (static, weighted, sequence, range, distribution), emitted as typed log attributes
  • Trace correlation: SpanInfo now carries the producing span's SpanContext, and records are emitted with it on the context, so every log record (including the derived ones) carries trace/span IDs

Answers to the issue's design questions

  • Existing hard-coded ERROR/WARN logs: kept as the default. A service that defines any logs: (at either level) replaces the derived logs for that service; other services keep them. The README documents how to recreate the derived behaviour explicitly.
  • Volume control: one evaluation per matching span, gated by probability.
  • Span attribute references: supported in body templates (log attributes take precedence).
  • Scenario overrides for logs: out of scope here — a natural follow-up alongside scenario metric overrides.

Span events (issue 86) remain a separate concept; this only covers standalone log records.

Validation and docs

  • ValidateConfig checks severity, body, condition, probability range, timing anchor, delay, and attribute generators with the usual contextual error messages
  • DSL reference section in cmd/motel/README.md and a runnable example at docs/examples/topology-driven-logs.yaml

Verified end-to-end with motel run --stdout --signals traces,logs --slow-threshold 100ms on the new example: topology logs interpolate span attributes, conditions and probability behave as configured, the no-logs service still emits derived WARN/ERROR records, and all records carry trace/span IDs.

https://claude.ai/code/session_01AoVS3SJVCebSzegzL5aGuX


Generated by Claude Code

claude and others added 2 commits June 10, 2026 22:30
Add a logs: section to service and operation definitions, replacing the
need for hardcoded ERROR/WARN derivations as the only log output:

- Severity levels TRACE through FATAL per the OTel log data model
- Body templates with {key} interpolation from log attributes, span
  attributes, and service/operation built-ins
- Conditional emission (error, success, slow) and per-span probability
- Timing anchors (span start or end) with an optional delay offset
- Structured attributes using the existing attribute generators
- Trace correlation: records carry the producing span's trace/span IDs

Services that define no logs keep the derived error/slow behaviour;
defining any logs on a service replaces the derived logs for it.

Closes #112

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds topology-driven log generation to the synth engine, allowing services/operations to define log templates in the YAML DSL (severity, body templates, conditions, probability sampling, timing anchors/delay, and generated attributes), while preserving existing derived error/slow logs for services that don’t define any logs:. Also adds trace/span correlation to emitted log records via SpanContext.

Changes:

  • Extend the topology DSL and resolved topology model to support logs: at service and operation scope, plus validation and example documentation.
  • Implement a new LogObserver that emits topology-defined log records (with interpolation/conditions/probability/timing) and falls back to derived logs when no templates exist for a service.
  • Propagate span SpanContext through SpanInfo so emitted logs include trace/span IDs.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/synth/topology.go Adds resolved LogDefinition and resolves YAML LogConfig into templates on services/operations.
pkg/synth/topology_test.go Tests that topology log configs resolve correctly and invalid delay is rejected.
pkg/synth/observer.go Extends SpanInfo to carry trace.SpanContext for correlation.
pkg/synth/logs.go Replaces derived-only observer with topology-template emission + derived fallback; adds interpolation, conditions, sampling, and correlation.
pkg/synth/logs_test.go Adds extensive tests for topology log behavior and trace correlation; updates existing derived-log tests for new constructor.
pkg/synth/engine.go Passes span.SpanContext() into SpanInfo for observers.
pkg/synth/engine_test.go Updates to new NewLogObserver signature (now returns (*LogObserver, error)).
pkg/synth/emit.go Passes SpanContext into SpanInfo for observer notifications in emit paths.
pkg/synth/config.go Adds DSL types/constants + validation for logs: at service/operation scope.
pkg/synth/config_test.go Adds log load/validation tests, but also removes a large set of existing metric override/interval tests.
docs/examples/topology-driven-logs.yaml Adds runnable example demonstrating topology-driven logs.
cmd/motel/README.md Documents the new logs DSL, interpolation rules, conditions, defaults, and correlation.
cmd/motel/main.go Wires topology and RNG into NewLogObserver creation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/synth/config.go
Comment thread pkg/synth/config_test.go
Restore the opRef assignment in the ValidateConfig operation loop and
the metric override, walk/bounds, and interval tests that the merge
resolution dropped.
@andrewh
andrewh merged commit 13909bf into main Jun 11, 2026
2 checks passed
@andrewh
andrewh deleted the claude/serene-thompson-kjbkhr branch June 11, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants