Skip to content

fix(file): reuse fingerprinted file handles - #26930

Open
pznamensky wants to merge 4 commits into
vectordotdev:masterfrom
pznamensky:fix/file-fingerprint-race
Open

pznamensky wants to merge 4 commits into
vectordotdev:masterfrom
pznamensky:fix/file-fingerprint-race

Conversation

@pznamensky

Copy link
Copy Markdown

Summary

Kubernetes logs appeared in directories named 0006-... and 0026-... instead of 2026-... (for path template like path: %Y-%m-%d), although application timestamps inside the messages were correct.

A reproducer exposed a rotation race: reopening a path after fingerprinting can read a replacement file under the original fingerprint. Later, the replacement's offset can be applied to the original file, skipping, duplicating, or truncating records, including CRI timestamp prefixes.

Reuse the fingerprinted file handle when creating or updating a watcher.

Vector configuration

Affects the shared reader used by file and kubernetes_logs. No configuration changes or checkpoint migration are required.

How did you test this PR?

137 targeted tests passed on macOS, including existing file and Kubernetes source tests.

Deterministic regression tests cover rotation during watcher creation and replacement. Additional cases verify both fingerprint strategies, checkpoint resume, start-position options, and gzip handling.

Clippy and formatting checks passed.

Does this PR include user facing changes?

  • Yes. Added changelog.d/file_fingerprint_rotation.fix.md.
  • No.

LLM disclosure

Most of the implementation and regression tests were generated by an LLM, which also assisted with tracing and reproducing the rotation race.

@pznamensky
pznamensky requested a review from a team as a code owner October 28, 2026 19:19
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-28T21:00:33.925631Z fb05f2f New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@pznamensky

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@datadoghq-integration datadoghq-integration Bot 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.

Bits Code Review: PASS

More details

The fingerprint-to-watcher handoff preserves the opened file’s identity across path rotation. Targeted execution remains unverified because the required saluki Git dependency was unavailable offline.

Was this helpful? React 👍 or 👎

Open Bits AI session

🤖 Bits Code Review · Commit 65cb452

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 65cb452547

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 492 to +493
path.clone(),
file,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Revalidate the path before removing a reused handle

When remove_after_secs is set (especially to 0), a path can be renamed and replaced after fingerprint_or_emit opens it but before this call, so file still refers to the old inode while path now names the replacement. The watcher then reads the old handle to EOF but stores the replacement path, and the no-bytes branch later calls remove_file(&watcher.path), deleting the unread replacement before the next discovery scan; verify that the path's device/inode still matches the watcher before removing it (or otherwise avoid binding the stale path to this handle).

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb05f2f247

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

/// # Errors
/// Returns an error if opening the path, reading metadata, or removing the file fails.
pub(super) async fn remove_file(&self) -> io::Result<bool> {
let file = File::open(&self.path).await?;

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 Avoid requiring read access before removal

When a producer makes a watched log unreadable after Vector has opened it (for example, via chmod during rotation) while Vector still has permission to unlink entries from the parent directory, this read-only File::open fails even though deletion would succeed. remove_after_secs then emits an error, failed rediscovery eventually drops the watcher, and the file is left behind until its permissions change; before this change the code called remove_file directly and did not require read access. Validate the identity through a metadata-only/no-read handle so configured cleanup still works.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
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.

1 participant