An agent on every host — at-least-once log shipping and offset checkpoints
A shipping agent on each host owns three pieces of state — a byte offset on disk (positions.yaml / registry), an in-RAM batch, and a retry slot — and ships batches at-least-once, which means duplicates on retry are normal and a checkpoint that advances before the ship can silently lose lines.
Centralising means putting a network between the app and its log file — and that something on each host that has to keep the pipe full has a name. It is the shipping agent: Filebeat, Promtail, Fluent Bit, or Vector. They look different on the outside; under the skin they are the same three compartments.
Scene 02
An agent on every host
- Watch
- Try it
- Predict
- Capture
The app writes lines into /var/log/app.log. The agent reads each new line into its in-memory batch. When the batch hits 4 lines, it POSTs the batch over HTTP. Only AFTER the backend acks does positions.yaml advance — that on-disk offset is what the agent re-reads from on restart.
Highlighted lines are the ones running in the diagram right now.
def tail_loop():f = open('/var/log/app.log')f.seek(self.offset) # offset from positions.yamlwhile running:line = f.readline()if not line:sleep(poll_interval); continuebatch.append(line)if len(batch) >= batch_capacity:send_queue.put(batch)batch = []
def send_loop():while running:batch = retry_slot or send_queue.get()resp = http.post(backend_url, batch)if 200 <= resp.status < 300:self.offset += sum(len(l) for l in batch)persist(positions_yaml, self.offset)retry_slot = Noneelse: # network drop, 5xx, or no ackretry_slot = batch # resend after backoffsleep(backoff_with_jitter())
def on_restart():# batch and retry_slot lived in RAM — both goneself.offset = read(positions_yaml) or 0# Promtail gotcha: if positions advanced when the line# was READ rather than when the backend ACKED, every# in-flight line between offset and EOF is silently lost.spawn(tail_loop) # re-opens app.log, seeks to offsetspawn(send_loop) # starts with empty queue + slot
Where this sits in Build a distributed logging stack (ELK / Loki)
Scene 02 of 12. A shipping agent tails each log file from a saved offset, batches lines, and POSTs them at-least-once — duplicates on retry are normal, not a bug.
Up next. The agent ships at-least-once over a pipe — but ships them WHERE? The backend at the far end can stall, and when it does the agent has exactly three options for what to do with the lines piling up — only one of which keeps the application alive.
All 12 scenes in Build a distributed logging stack (ELK / Loki) · Every curriculum