Skip to main content
Filetrace does not inspect packet payloads. It attributes bytes sent on a socket to a file by watching what the kernel does on behalf of the sending thread, and it labels every attribution with a confidence level that states what the association rests on. This page explains the two attribution methods, the thresholds that decide when an association is reported, and how to read the confidence of a record.

Confidence levels

A level is never raised by a filter or an output format, and every record lists the evidence behind it. In tables, a * after the level marks a transfer during which events were lost, so its byte counts may be incomplete.

Exact attribution with sendfile

When a program calls sendfile(2), the kernel copies data from a file to a socket inside one operation (do_splice_direct). The probe sees the file and the socket in the same call, so the association is certain. Web servers such as nginx serve static files this way.

Inferred attribution with read and send

Most programs read a file into a buffer and then write the buffer to a socket. The kernel never sees the two operations as one, so Filetrace correlates them per thread:
  1. The vfs_read probe records which regular file each thread read last, and how much.
  2. When the same thread sends on a socket within the correlation window (2 seconds by default) after that read, with no receive in between, the send is associated with the file.
  3. The association covers at most as many bytes as the thread read.
  4. It is reported once it covers at least 1 KB and 5% of what was read from the file.
The receive rule keeps request and response traffic apart: a thread that reads a file, then hears from its peer, then sends something else has not sent the file. For example, a certificate bundle read before a TLS handshake is not attributed to the connection, because the handshake’s receive ends the association. The settings live in the [correlation] section of the configuration file:

When an inferred association is wrong

An INFERRED record is a strong hint, not proof. It can be wrong when a thread reads one file and then sends unrelated data of a similar size without receiving in between. It can also be missing:
  • A file read by one thread and sent by another, or passed through a pipe, is not associated with the send.
  • Files read with readv, io_uring or through a memory mapping are not seen as read. Bytes sent through io_uring are still counted per socket.
Known limitations lists every case.

Unattributed bytes

Bytes that no file accounts for are not dropped. They appear as UNKNOWN in filetrace transfers, which shows unknown in the FILE column, and in filetrace files --include-unknown. The share of outbound traffic that files account for is a useful signal on its own:

Evidence

Machine-readable output lists the evidence behind each record in transfer.evidence. A sendfile transfer carries, for example:

What a byte count means

Byte counts are what the local socket accepted. They are not the number of bytes on the wire and not what the remote end acknowledged. For a read-write transfer, three numbers describe the file: file.size (its size when it was first seen), transfer.bytes_read (what the thread read from it) and transfer.bytes_sent (what the socket accepted). See Records and identifiers.

Filter by confidence

filetrace files, transfers and watch accept --confidence: