docs: amend constitution to v1.1.0 (Observability for tracing migration)

Principle V now reflects the merged tracing migration (#148):
- tracing + tracing-opentelemetry spans in every build, with OTLP export
  gated on OTLP_OTLS_ENDPOINT;
- no manual Context threading;
- every spawn / fan-out carries its parent span;
- RUST_LOG gates span export (run at info/debug).
Layer and Tech Stack wording matches.

Also corrects stale "release builds only" telemetry notes in CLAUDE.md and
.env.example, updates the CLAUDE.md dependency list, and fixes the README's
RUST_LOG default. It also documents OTLP_OTLS_ENDPOINT in the README, as
Principle IV requires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-09-29 18:03:44 -04:00
1 parent e0c6c696f2
commit fbe3d06ae5
4 files changed
+55 -21

No files matched your search

+3 -1
View File
@@ -28,7 +28,9 @@ HLS_CONCURRENCY=2
HLS_TIMEOUT_SECONDS=900
PLAYLIST_CLEANUP_INTERVAL_SECONDS=86400
# ── Telemetry (release builds only) ─────────────────────────────────────
# ── Telemetry ────────────────────────────────────────────────────────────
# Span export over OTLP in any build when set (unset = spans stay local).
# RUST_LOG also gates span export: keep it at info or debug.
# OTLP_OTLS_ENDPOINT=http://localhost:4317
# ── AI Insights — Ollama (local LLM) ────────────────────────────────────
+48 -17
View File
@@ -1,20 +1,31 @@
<!--
Sync Impact Report
==================
Version change: (new) -> 1.0.0
Modified principles: N/A (initial ratification)
Added sections:
- Core Principles (5 principles)
- Technology Stack & Constraints
- Development Workflow
- Governance
Version change: 1.0.0 -> 1.1.0
Bump rationale: MINOR. Principle V is materially expanded: the tracing
mechanism changed (tracing + tracing-opentelemetry in every build), and
it adds two new MUST rules: no manual Context threading, and carrying
the parent span across spawns. No principle is removed or redefined in
intent.
Modified principles:
- V. Observability: mechanism + rules updated for the tracing migration
(map #135, PR #148)
Also updated:
- I. Layered Architecture: Database Layer "traced" wording
- Technology Stack & Constraints: Tracing line
Added sections: N/A
Removed sections: N/A
Templates requiring updates:
- .specify/templates/plan-template.md — ✅ no changes needed (Constitution Check section is generic)
- .specify/templates/plan-template.md — ✅ no changes needed (generic Constitution Check)
- .specify/templates/spec-template.md — ✅ no changes needed
- .specify/templates/tasks-template.md — ✅ no changes needed
- .specify/templates/checklist-template.md — ✅ no changes needed
- .specify/templates/agent-file-template.md — ✅ no changes needed
Runtime guidance:
- CLAUDE.md "Tracing" — ✅ already consistent (conventions landed with #148);
OTLP env line + dependency list updated alongside this amendment
- README.md — ✅ RUST_LOG default/gating corrected; OTLP_OTLS_ENDPOINT added
- .env.example — ✅ telemetry header corrected
Follow-up TODOs: None
-->
@@ -34,7 +45,8 @@ All features MUST follow the established layered architecture:
contracts. Every DAO MUST be defined as a trait to enable mock
implementations for testing.
- **Database Layer** (Diesel ORM, `schema.rs`): Concrete `Sqlite*Dao`
implementations. All queries traced with OpenTelemetry.
implementations. Every query runs inside a `tracing` span via
`otel::trace_db_call`.
New features MUST NOT bypass layers (e.g., HTTP handlers MUST NOT
execute raw SQL). Actix actors are permitted for long-running async
@@ -84,17 +96,35 @@ prohibited.
### V. Observability
All database operations and HTTP handlers MUST be instrumented
with OpenTelemetry spans via the `trace_db_call` helper or
equivalent tracing macros.
All database operations and HTTP handlers MUST be instrumented with
`tracing` spans, exported through `tracing-opentelemetry`: DAO bodies via
`otel::trace_db_call`, and handlers / feature functions via
`#[tracing::instrument]`. The per-request root span comes from the
`tracing-actix-web` middleware, which also honors an incoming W3C
`traceparent`.
- Release builds export traces to the configured OTLP endpoint.
- Debug builds use the basic logger.
- Spans are produced in debug and release builds alike. OTLP export is
enabled by `OTLP_OTLS_ENDPOINT`, not by build profile.
- Code MUST NOT thread an OpenTelemetry `Context` through call chains.
Spans parent on the ambient span.
- Every `tokio::spawn` or cross-thread fan-out (rayon, per-pass runtimes)
MUST carry its parent span: `.instrument(span)` or
`info_span!(parent: &span, ...)`. Tracing context is thread-local, and
an uncarried spawn orphans its spans onto a fresh trace.
- `RUST_LOG` gates span export as well as console output (one `EnvFilter`).
Deployments MUST run at `info` or `debug`.
- Logs are a separate pipeline: `env_logger` in debug, OTel log export in
release.
- Prometheus metrics (`imageserver_image_total`,
`imageserver_video_total`) MUST be maintained for key counters.
- Errors MUST be logged at `error!` level with sufficient context
for debugging without reproducing the issue.
**Rationale:** span parenting that relies on hand-threaded contexts drifted
into orphaned traces (the pre-migration baseline, #137). Ambient
parenting, plus an explicit carry at each spawn boundary, keeps a request or
job in one trace by construction.
## Technology Stack & Constraints
- **Language**: Rust (stable toolchain, Cargo build system)
@@ -105,8 +135,9 @@ equivalent tracing macros.
- **Video Processing**: ffmpeg/ffprobe (CLI, must be on PATH)
- **Image Processing**: `image` crate for thumbnails, `kamadak-exif`
for EXIF extraction
- **Tracing**: OpenTelemetry with OTLP export (release),
basic logger (debug)
- **Tracing**: `tracing` + `tracing-opentelemetry` (every build), OTLP
export when `OTLP_OTLS_ENDPOINT` is set; logs via `env_logger` (debug) /
OTel log export (release)
- **Testing**: `cargo test`, `actix_web::test`, in-memory SQLite
External dependencies (ffmpeg, Ollama) are optional runtime
@@ -146,4 +177,4 @@ MUST comply with these principles.
these principles. The CLAUDE.md file provides runtime development
guidance and MUST remain consistent with this constitution.
**Version**: 1.0.0 | **Ratified**: 2026-02-26 | **Last Amended**: 2026-02-26
**Version**: 1.1.0 | **Ratified**: 2026-02-26 | **Last Amended**: 2026-09-29
+2 -2
View File
@@ -684,7 +684,7 @@ Optional:
WATCH_QUICK_INTERVAL_SECONDS=60 # Quick scan interval
WATCH_FULL_INTERVAL_SECONDS=3600 # Full scan interval
DATE_BACKFILL_MAX_PER_TICK=500 # Cap on canonical-date drain per watcher tick
OTLP_OTLS_ENDPOINT=http://... # OpenTelemetry collector (release builds)
OTLP_OTLS_ENDPOINT=http://... # OTLP collector for span export (any build; unset = no export)
# AI Insights Configuration
OLLAMA_PRIMARY_URL=http://desktop:11434 # Primary Ollama server (e.g., desktop)
@@ -944,7 +944,7 @@ side if exposing beyond a trusted network.
- **image**: Thumbnail generation
- **walkdir**: Directory traversal
- **rayon**: Parallel processing
- **opentelemetry**: Distributed tracing
- **tracing** + **tracing-opentelemetry** + **tracing-actix-web**: spans (exported via `opentelemetry-otlp`)
- **bcrypt**: Password hashing
- **infer**: Magic number file type detection
+2 -1
View File
@@ -72,7 +72,8 @@ They should be defined where the binary is located or above it in an `.env` file
- `GIFS_DIRECTORY` is a path where generated video GIF thumbnails should be stored
- `BIND_URL` is the url and port to bind to (typically your own IP address)
- `SECRET_KEY` is the *hopefully* random string to sign Tokens with
- `RUST_LOG` is one of `off, error, warn, info, debug, trace`, from least to most noisy [error is default]
- `RUST_LOG` is one of `off, error, warn, info, debug, trace`, from least to most noisy [default: `info` for spans, `error` for dev console logs]. It also gates tracing-span export, so keep it at `info` or `debug`
- `OTLP_OTLS_ENDPOINT` (optional) is an OTLP/gRPC collector URL (e.g. SigNoz, Jaeger) for span export, in any build [default: unset, no export]
- `EXCLUDED_DIRS` is a comma separated list of directories to exclude from the Memories API
- `PREVIEW_CLIPS_DIRECTORY` (optional) is a path where generated video preview clips should be stored [default: `preview_clips`]
- `WATCH_QUICK_INTERVAL_SECONDS` (optional) is the interval in seconds for quick file scans [default: 60]