vercel-labs / vercel-labs/native
native dev: default events trace floods stdout with the 500ms markup-watch timer
Nobody has claimed this yet.
- Dominant language
- Zig
- Stars
- 7.7k
- Forks
- 314
- Avg merge
- 5h
- Merged PRs (30d)
- 13
Description
Symptom
native dev prints this pair of lines about twice a second for as long as the app is running:
ts=1788398844994007000 level=info kind=event name="runtime.event" event="timer"
ts=1788398845494030000 level=info kind=event name="runtime.event" event="timer"
The terminal is unusable as a log: real start/stop, pointer, and error lines are buried under a heartbeat. Reproduced on @native-sdk/cli 0.10.1 with a stock TypeScript + Native markup app (src/core.ts, src/app.native, app.json). The app has no Sub.timer and no Cmd.delay.
Why
native dev builds Debug with the default trace mode events (build/app.zig: -Dtrace defaults to .events). That mode prints every record named runtime.event. Every platform event is logged in src/runtime/flow.zig (dispatchEvent → log(..., "runtime.event", ...)), including .timer.
Debug also arms markup hot reload. UiApp.startMarkupWatch starts a repeating runtime timer at 500ms (markup_watch_timer_id / markup_watch_interval_ns in src/runtime/ui_app.zig). Each poll is a .timer event, so the default events trace prints two lines per second for the whole session.
The timer itself is the right behavior: it is how .native files reload without restarting. Only the log is the problem.
Workaround today: native dev -Dtrace=off. That compiles tracing out. It is a rebuild flag, not a runtime switch, and it is easy to miss because native --help only shows -D... zig build flags.
Proposed fix
Keep the 500ms markup-watch timer. Stop printing it on the default native dev path.
A small change that matches the existing filter: under -Dtrace=events, skip .timer events whose id is a reserved framework timer (markup_watch_timer_id, and any other id at or above platform.reserved_timer_id_base). App-owned timers and pointer/frame events would still show. -Dtrace=all would keep the full firehose.
Defaulting native dev to -Dtrace=off would also silence this, but it would hide the rest of the events log too. Filtering the watch poll from events keeps a useful default.
Checking it
native inita TypeScript + Native markup app.- Run
native devwith no extra flags. - After the window is up, stdout should stay quiet aside from the usual build/start lines — no repeating
event="timer"lines. - Saving
src/app.nativeshould still hot-reload the window. native dev -Dtrace=allshould still print the watch-timer events if someone wants them.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the default trace setting in build/app.zig, then follow dispatchEvent and log in src/runtime/flow.zig. Read the markup-watch timer setup in src/runtime/ui_app.zig, including markup_watch_timer_id and markup_watch_interval_ns. Verify that native dev no longer repeats timer lines, hot reload still works, and -Dtrace=all still shows them.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- zig
- Domain
- desktop, observability
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100