Skip to content

Rewatch: add OpenTelemetry tracing support#8370

Merged
cknitt merged 12 commits intorescript-lang:masterfrom
jfrolich:telemetry-cherry-pick
Apr 28, 2026
Merged

Rewatch: add OpenTelemetry tracing support#8370
cknitt merged 12 commits intorescript-lang:masterfrom
jfrolich:telemetry-cherry-pick

Conversation

@jfrolich
Copy link
Copy Markdown
Collaborator

Summary

Cherry-picked telemetry-only subset of #8241. Adds optional OTLP tracing export to rewatch, controlled by the OTEL_EXPORTER_OTLP_ENDPOINT environment variable. When unset, tracing is a no-op.

  • New telemetry module wiring up tracing + opentelemetry-otlp with a batch HTTP exporter and a TelemetryGuard that flushes on drop.
  • #[instrument] / info_span! coverage across initialize_build, incremental_build, compile, parse, clean, packages, format, and the watcher full-compile trigger.
  • Parent-span plumbing through rayon so build.parse_file and build.compile_file spans nest correctly under their parents (these are otherwise orphaned because tracing spans are thread-local).
  • ctrlc "termination" feature enabled so SIGTERM/SIGHUP also trigger the guard's Drop — required to flush buffered spans when stopped by a container/systemd/kill.
  • Jaeger setup instructions in AGENTS.md.

The original PR also included a Vitest test harness, CI/Makefile/scripts changes, and two unrelated UX tweaks. Those are excluded here — the UX tweaks will follow in separate PRs.

Test plan

  • cargo build --release --manifest-path rewatch/Cargo.toml
  • cargo test --manifest-path rewatch/Cargo.toml (68/68 pass)
  • cargo clippy --manifest-path rewatch/Cargo.toml --all-targets --all-features (clean)
  • Manual: OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 ./rewatch build with Jaeger running

🤖 Generated with Claude Code

@jfrolich jfrolich force-pushed the telemetry-cherry-pick branch from a79a52c to ece9e1b Compare April 19, 2026 12:30
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 19, 2026

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8370

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8370

@rescript/darwin-x64

npm i https://pkg.pr.new/@rescript/darwin-x64@8370

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8370

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8370

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8370

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8370

commit: 14da4de

@cknitt
Copy link
Copy Markdown
Member

cknitt commented Apr 22, 2026

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0429522fe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread rewatch/src/telemetry.rs Outdated
Comment on lines +153 to +156
unsafe {
std::env::remove_var("OTEL_EXPORTER_OTLP_ENDPOINT");
std::env::remove_var("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT");
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Serialize env var mutation in telemetry tests

init_telemetry_without_env_is_noop mutates process-global environment variables using unsafe std::env::remove_var without any synchronization, but Rust tests run in parallel by default, so another test reading/writing env vars concurrently can trigger undefined behavior or flaky failures. Please guard this section with a shared Mutex (or otherwise force serial execution) before mutating OTEL env vars.

Useful? React with 👍 / 👎.

Add optional OTLP tracing export to rewatch, controlled by the
OTEL_EXPORTER_OTLP_ENDPOINT environment variable. When set, rewatch
exports spans via HTTP OTLP; when unset, tracing is a no-op.

Instrument key build system functions (initialize_build, incremental_build,
compile, parse, clean, format, packages) with tracing spans and attributes
such as module counts and package names.

Restructure main.rs to support telemetry lifecycle (init/flush/shutdown)
and fix show_progress to use >= LevelFilter::Info so -v/-vv don't
suppress progress messages. Also print 'Finished compilation' in
plain_output mode during watch full rebuilds.

Cherry-picked from rescript-lang#8241.
Propagate parent span through rayon in build.parse so build.parse_file
spans are properly nested under build.parse instead of appearing as
orphaned root spans.

Enrich build.compile_file span with package, suffix, module_system,
and namespace attributes for better observability.

Cherry-picked from rescript-lang#8241.
Tracing spans are thread-local, so compile_file spans created inside
Rayon's par_iter had no parent connection to the compile_wave span on
the main thread. Pass the wave span explicitly via `parent: &wave_span`
to establish the correct parent-child relationship.

Cherry-picked from rescript-lang#8241.
Replace the ad-hoc split-by-/-or-backslash + take-last-two-parts logic
with Path::file_name, which handles platform separators correctly and
is simpler to reason about. The attribute is informational only, so
reducing to the file name (e.g. `ppx.exe`) is strictly more readable
than the previous two-segment join.
The dirty_modules attribute on build.parse required a full iteration
over build_state.modules every parse phase, even when no subscriber
was listening. Gate behind tracing::enabled!(INFO) so incremental
rebuilds don't eat that O(N) scan when telemetry is off.
Add a table to the OpenTelemetry section listing the env vars rewatch
responds to and what each does. All config is via standard OTEL vars —
no rewatch-specific knobs — so this is the full surface area.
Lets callers pass folder arguments to functions taking &Path without
the cryptic `as &str` deref-coercion cast:

  Path::new(&build_args.folder as &str)  ->  build_args.folder.as_ref()

FolderArg already had a Deref<Target = str> impl, so this is the
analogous addition for the &Path direction.
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
@jfrolich jfrolich force-pushed the telemetry-cherry-pick branch from be38941 to f43dcc6 Compare April 28, 2026 09:33
jfrolich and others added 3 commits April 28, 2026 13:30
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
Signed-off-by: Jaap Frolich <jfrolich@gmail.com>
@cknitt cknitt enabled auto-merge (squash) April 28, 2026 14:10
@cknitt cknitt merged commit 09df838 into rescript-lang:master Apr 28, 2026
26 checks passed
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