critical
Accounting records can be written to a file, passed to a program through a pipe or sent to an endpoint over HTTP. The third method is the webhook, and it works differently from how it seems.
A webhook is not a stream but batches on top of files. Records accumulate in a file at the path given in the block, the file goes out as a POST request and is deleted only after a successful send. Success is a 2xx response and nothing else; everything else triggers a retry after a short delay.
So an unavailable receiver causes accumulation, not loss. That is good news right up to the moment the lower free disk space threshold trips and the engine starts deleting old accounting files. That is what you need to design against: not loss on failure, but the disk.
The file underneath is common to all three methods, and it is also their common point of failure. On the other hand, all three have the same reliability: the data survives a restart because it sits on disk.
The pipe has a separate danger named by the vendor. If writing to the program fails, the node gives up trying until a configuration reload or a timeout, and the vendor advises keeping a regular file alongside so the data survives a broken pipe.
What we pay for it: the receiver must be available. Ours responds quickly on purpose — it checks the token, puts the body in the cache, queues a job — because the engine waits for a 2xx and holds the connection.
We keep file accounting next to the webhook — as a separate <acct-file /var/log/pmta/acct.csv> block in the same template. That is exactly the insurance the vendor advises: until the receiver is proven, there is something to compare against.
The mechanism has no values of its own: the method is chosen by which lines are written in the block.
| Method | Enabled by | What is underneath |
|---|---|---|
| file | the path in the <acct-file> tag | the file itself |
| endpoint | http-webhook-url | a file at the same path, deleted after sending |
| program | a pipe in the block tag | a file alongside — on the vendor’s advice |
The path extension decides the format: .json is NDJSON, anything else is CSV.
# two methods at once — this is how a migration is done <acct-file /var/log/pmta/acct.csv> records d, b, t </acct-file> <acct-file /var/log/pmta/webhook.json> records d, b, t http-webhook-url https://hub.example.com/api/telemetry/pmta/7</acct-file>
what people get wrong and how it ends3 mistakes▶
§ 12.1.1
§ 12.1.1
§ 12.1.1
3 relations
ls -la /var/log/pmta/ | tail -20
3 articles
◇What the node tells about itself and through which channelsSeven observation surfaces: the web monitor, the console in four formats, the log, accounting, accounting search, metrics and export to external analytics.◇The log and accounting — two files and two different questionsThe engine keeps a separate log and a separate accounting file; the separation is made for the sake of format, performance and the ability to hand over the log without disclosing data.◇The watchdog that restarts the engineKeeps an eye on the engine and brings it back up after a crash by itself, sending a crash report to the postmaster address.