Skip to content

fix(logs): enable millisecond-precision timestamps in heimdall logs#570

Open
lucca30 wants to merge 2 commits intodevelopfrom
lmartins/ms-precision-logs
Open

fix(logs): enable millisecond-precision timestamps in heimdall logs#570
lucca30 wants to merge 2 commits intodevelopfrom
lmartins/ms-precision-logs

Conversation

@lucca30
Copy link
Copy Markdown
Contributor

@lucca30 lucca30 commented Mar 26, 2026

Problem

Heimdall log lines carry only second-precision timestamps, e.g.:

2026-03-25T21:07:40Z INF Milestone stored successfully endBlock=84676411 ...

This makes it impossible to accurately measure sub-second timing between milestone events without relying on the Datadog ingestion timestamp — which carries a variable delay and is not a reliable high-resolution event marker.

Root cause

zerolog.TimeFieldFormat (a zerolog global) defaults to time.RFC3339, which has second-level precision. This global controls how the timestamp is stored in the zerolog event before the ConsoleWriter ever formats it. TimeFormatOption(time.RFC3339Nano) was already set for the ConsoleWriter display layer, but the stored value only carried second granularity — so the displayed timestamp was always truncated to the second regardless of display format.

Fix

Set zerolog.TimeFieldFormat to a fixed 3-decimal-place millisecond format ("2006-01-02T15:04:05.000Z07:00") before logger construction, and apply the same format to TimeFormatOption. This makes all log lines emit millisecond-precision timestamps that are consistent with bor's log format:

2026-03-26T13:54:28.593Z INF Generated a new milestone proposition ...
2026-03-26T13:54:28.793Z INF 2/3rd majority reached on milestone proposition ...
2026-03-26T13:54:28.793Z INF Milestone stored successfully ...

Motivation

The change is driven by block-finality latency analysis. The key heimdall events being timed are:

  • Generated a new milestone proposition — proposal phase (T2)
  • 2/3rd majority reached on milestone proposition — consensus achieved (T3)
  • Milestone stored successfully — finality committed (T4)

With second precision, derived latencies have ±500ms noise per step. With millisecond precision, inter-event timing becomes accurate enough to identify the dominant bottleneck in the finality pipeline (CometBFT consensus round duration, validator nil-vote behavior) without relying on Datadog ingestion timestamps.

Milliseconds (3 decimal places) were chosen over nanoseconds to match bor's existing log timestamp format, keeping both services consistent for cross-service log analysis.

Validation

Tested on a local kurtosis devnet — confirmed all three milestone log events carry millisecond-precision timestamps after the fix.

zerolog.TimeFieldFormat defaults to time.RFC3339 (second-level
precision). This global controls how timestamps are stored in the
zerolog event before the ConsoleWriter ever formats them. Even though
TimeFormatOption(time.RFC3339Nano) was already set for the ConsoleWriter
display layer, the stored value only carried second granularity, so
the displayed timestamp was always truncated to the second.

Setting zerolog.TimeFieldFormat = time.RFC3339Nano before logger
construction makes all log lines emit sub-second timestamps (e.g.
2026-03-25T21:07:40.594Z instead of 2026-03-25T21:07:40Z), which
is necessary for accurate block-finality timing analysis where
Datadog ingestion delays make the Datadog timestamp unreliable as a
high-resolution event marker.
Copy link
Copy Markdown

@claude claude bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Tip: disable this comment in your organization's Code Review settings.

@claude
Copy link
Copy Markdown

claude bot commented Mar 26, 2026

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 26, 2026

Codecov Report

❌ Patch coverage is 0% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.6%. Comparing base (ee0f51f) to head (6f8cda1).
⚠️ Report is 4 commits behind head on develop.

Files with missing lines Patch % Lines
cmd/heimdalld/cmd/root.go 0.0% 2 Missing ⚠️
helper/config.go 0.0% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (0.0%) is below the target coverage (90.0%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop    #570     +/-   ##
=========================================
- Coverage     41.7%   41.6%   -0.1%     
=========================================
  Files          172     172             
  Lines        17434   17500     +66     
=========================================
+ Hits          7280    7291     +11     
- Misses        9074    9128     +54     
- Partials      1080    1081      +1     
Files with missing lines Coverage Δ
helper/config.go 19.6% <0.0%> (ø)
cmd/heimdalld/cmd/root.go 0.0% <0.0%> (ø)

... and 8 files with indirect coverage changes

Files with missing lines Coverage Δ
helper/config.go 19.6% <0.0%> (ø)
cmd/heimdalld/cmd/root.go 0.0% <0.0%> (ø)

... and 8 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Switch from time.RFC3339Nano (nanoseconds) to a fixed 3-decimal-place
format ("2006-01-02T15:04:05.000Z07:00") so heimdall timestamps are
consistent with bor's millisecond-precision log format.
@sonarqubecloud
Copy link
Copy Markdown

Copy link
Copy Markdown
Collaborator

@marcello33 marcello33 left a comment

Choose a reason for hiding this comment

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

Small nit, LGTM else

logOpts = append(logOpts,
log.LevelOption(logLevel),
log.TimeFormatOption(time.RFC3339Nano),
log.TimeFormatOption("2006-01-02T15:04:05.000Z07:00"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

maybe we can use a constant here, since it's duplicated from line 144

logOpts = append(logOpts,
logger.LevelOption(logLevel),
logger.TimeFormatOption(time.RFC3339Nano),
logger.TimeFormatOption("2006-01-02T15:04:05.000Z07:00"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here

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.

2 participants