Fluentd’s tail input plugin is your go-to for ingesting logs from files, but when those files rotate, things can get messy. The pos_file is the key to picking up where you left off, but if it’s not managed correctly, you’ll either miss logs or re-process them.

Here’s how to ensure your tail input correctly handles log file rotation:

Common Causes of Log Rotation Issues

  1. pos_file Not Updated or Corrupted: If the pos_file that tracks the last read position within a log file becomes corrupted or is not updated by Fluentd, it can lead to missed logs. This can happen if Fluentd crashes or is shut down abruptly.

    • Diagnosis: Check the pos_file itself. It’s usually a plain text file containing inode-number:offset. If the file is empty, zero bytes, or contains nonsensical data, it’s likely corrupted.
    • Fix: Manually reset the pos_file. Delete the file. Fluentd will then start reading the target log file from the beginning.
      rm /var/log/myapp.log.pos
      
    • Why it works: Deleting the pos_file forces Fluentd to re-evaluate the current state of the log file, effectively resetting its reading pointer to the start of the file.
  2. Incorrect pos_file Path: The pos_file path might be misconfigured in your Fluentd configuration, pointing to a location where Fluentd doesn’t have write permissions or to a non-existent directory.

    • Diagnosis: Verify the pos_file directive in your Fluentd configuration. Check the directory specified for write permissions for the user running Fluentd.
    • Fix: Ensure the pos_file path is correct and the Fluentd process has write permissions to the directory.
      <source>
        @type tail
        path /var/log/myapp.log
        pos_file /var/log/td-agent/myapp.log.pos # Ensure this path is writable
        tag myapp.log
      </source>
      
    • Why it works: A valid and writable pos_file path allows Fluentd to store and retrieve its read position reliably.
  3. Log Rotation Utility Not Using Standard rename: Some log rotation utilities don’t use the standard rename system call, which is crucial for tail to detect file rotation. If the log is truncated or overwritten instead of being renamed, Fluentd might not realize a new file has started.

    • Diagnosis: Examine your log rotation configuration (e.g., /etc/logrotate.d/myapp). Look for directives like copytruncate. If copytruncate is used, it’s a likely culprit.
    • Fix: Configure logrotate to use rename or create with rotate and delaycompress. The default behavior of logrotate is usually sufficient if copytruncate is avoided.
      # Example logrotate config snippet to AVOID copytruncate
      /var/log/myapp.log {
        rotate 5
        daily
        missingok
        notifempty
        compress
        delaycompress
        # DO NOT use copytruncate here if possible
      }
      
    • Why it works: The rename system call ensures that the original file inode is preserved, allowing Fluentd to continue tracking it while a new file is created. copytruncate truncates the original file after copying it, meaning Fluentd might miss logs written between the copy and the truncate.
  4. inode Changes During Rotation: When a log file rotates, the new file typically gets a new inode. If Fluentd is configured to only rely on the offset within the pos_file and not the inode, it might incorrectly resume reading from the old, now-rotated file.

    • Diagnosis: Fluentd’s tail input plugin by default tracks both inode and offset. If you’ve explicitly disabled inode tracking (which is rare and not recommended), this could be an issue.
    • Fix: Ensure inode tracking is enabled (it is by default). The pos_file format inode:offset is designed for this. No configuration change is usually needed.
      <source>
        @type tail
        path /var/log/myapp.log
        pos_file /var/log/td-agent/myapp.log.pos
        tag myapp.log
        # inode_sensitivity true # This is the default and recommended
      </source>
      
    • Why it works: By tracking the inode, Fluentd can detect when the file it was reading has been replaced by a new file with a different inode, even if the filename is the same. It then knows to look for new data in the new file.
  5. Frequent Log Rotation: If logs are rotated very frequently (e.g., every minute), Fluentd might not have enough time to write its pos_file update before the rotation occurs, especially under heavy load or if the disk is slow.

    • Diagnosis: Monitor Fluentd’s pos_file update frequency and the log rotation schedule. Check Fluentd’s logs for any errors related to writing to the pos_file.
    • Fix: Increase the flush_interval in your Fluentd configuration for the tail input. This gives Fluentd more time between writing its internal state to disk.
      <source>
        @type tail
        path /var/log/myapp.log
        pos_file /var/log/td-agent/myapp.log.pos
        tag myapp.log
        flush_interval 5s # Increase from default 1s if needed
      </source>
      
    • Why it works: A larger flush_interval means Fluentd waits longer before flushing its internal state (including the pos_file updates) to disk. This reduces the chance of a rotation happening between a log read and its corresponding pos_file update.
  6. Multiple Fluentd Instances or Processes: If multiple Fluentd processes are trying to tail the same log file using the same pos_file, it can lead to race conditions and corrupted pos_file entries.

    • Diagnosis: Ensure only one Fluentd process is configured to tail a specific log file with a specific pos_file. Check your Fluentd deployment and configuration.
    • Fix: Dedicate each log file (and its pos_file) to a single Fluentd input configuration or process.
    • Why it works: This prevents concurrent writes and reads to the pos_file from different processes, eliminating the possibility of conflicting updates and ensuring data integrity.

The Next Hurdle

Once you’ve nailed log rotation, you’ll likely encounter issues with timestamp parsing if your application logs don’t follow a consistent, easily recognizable format.

Want structured learning?

Take the full Fluentd course →