Severity: Info
File: src/Servy.Manager/Utils/LogTailer.cs lines 121 and 134
Description:
The tailer detects log rotation by comparing FileInfo.CreationTimeUtc and by checking whether the file has shrunk below the last-read position:
if (info.CreationTimeUtc != lastCreationTime || info.Length < lastPosition)
{
lastPosition = 0;
lastCreationTime = info.CreationTimeUtc;
}
The class's XML doc block acknowledges the filesystem caveat but does not mitigate it. Two rotation patterns are silently missed:
- FAT32 / network share "file tunneling": when a file is deleted and re-created with the same name within ~15 seconds, NTFS-the-client-sees preserves the creation timestamp of the deleted file.
CreationTimeUtc is therefore equal to the previous value despite a genuine rotation.
- Same-size rotation with immediate write: if the new file's first write brings its length above the old
lastPosition before the tailer samples, the info.Length < lastPosition check also misses the rotation. The tailer then reads garbage from the old offset of the new file.
Under either pattern, the user sees either duplicate lines (re-reading a range from the new file) or missing lines (skipping the head of the new file).
Suggested fix:
Use a stable file-identity signal in addition to metadata:
- On NTFS,
GetFileInformationByHandle gives you a dwVolumeSerialNumber + nFileIndexHigh/Low pair that uniquely identifies the inode. Detect rotation by comparing the inode id across polls.
- For network shares / FAT where that is unreliable, sample a small hash of the first N bytes of the file at each poll and detect rotation when the hash changes.
- Fall back to the current heuristic only when no stable identity is available, and log at Debug level when you suspect rotation was missed.
Severity: Info
File:
src/Servy.Manager/Utils/LogTailer.cslines 121 and 134Description:
The tailer detects log rotation by comparing
FileInfo.CreationTimeUtcand by checking whether the file has shrunk below the last-read position:The class's XML doc block acknowledges the filesystem caveat but does not mitigate it. Two rotation patterns are silently missed:
CreationTimeUtcis therefore equal to the previous value despite a genuine rotation.lastPositionbefore the tailer samples, theinfo.Length < lastPositioncheck also misses the rotation. The tailer then reads garbage from the old offset of the new file.Under either pattern, the user sees either duplicate lines (re-reading a range from the new file) or missing lines (skipping the head of the new file).
Suggested fix:
Use a stable file-identity signal in addition to metadata:
GetFileInformationByHandlegives you adwVolumeSerialNumber+nFileIndexHigh/Lowpair that uniquely identifies the inode. Detect rotation by comparing the inode id across polls.