From the team behind aidrop.it — one workspace to build, host, and keep changing your code.

Something failed at 3am. Nobody was watching. The only thing left is whatever the system wrote down, and that is now the entire evidence base for deciding what happened.

This is the moment logging is for, and it is the moment most logging turns out to be useless — not because there is too little of it, but because it recorded the wrong half. Thousands of lines saying a request arrived, and nothing saying why the one that mattered stopped.

The test for a log line is simple and unforgiving: would this let somebody who was not there reconstruct the decision? Almost everything that fails the test is noise, and almost everything people wish they had passes it.

Record the decision, not the traffic

An access log tells you a request happened. It does not tell you what the code chose to do about it, and the choice is the thing you need.

So write down the branch, not the arrival. Not "processing order" but "order 4821 rejected: card declined, retry 2 of 3". Not "sync started" but "sync skipped: repository unchanged since 2f9ab1". Each of those answers a question a person will actually ask, and answers it without the code in front of them.

The same applies to failure. "Error" is not a record. What was being attempted, on what, and what came back — those three make an entry worth keeping and are usually available at the moment you are tempted to write except: log("error").

A stop needs a reason and a stage

The most valuable thing a long pipeline can record is where it stopped and why, as two separate facts.

"Build failed" sends somebody to read the whole log. "Build failed at push: registry returned 401 unauthorized" sends them to the credential. The difference in cost is an hour, and it recurs every time.

That shape generalises. Anything with steps — a deploy, an import, a scheduled job — should be able to answer "which stage" and "what did it say" without interpretation. And a stage that says it finished is a claim to verify, not a result: a migration that logged success still has to be read back out of the database. If the record makes somebody infer the stage from the last line that appeared, it has left the hardest part undone.

What to write down before you need it

  • The identifier that ties lines together. A request id, a job id, anything that turns scattered lines into one story.
  • What was decided and on what evidence. The branch taken and the value that decided it.
  • The external answer, verbatim and truncated. Not "the API failed" — the status and the first part of the body. Somebody else's error message is data.
  • A timestamp with a zone, because the person reading is somewhere else.
  • Never a credential. The error path is where secrets escape most often, and a log is not private — the same reasoning as keeping them out of the artefact.

What to leave out is just as important. A line printed on every iteration of a loop buries the one printed once, and the buried line is always the one you wanted — the same effect that makes a bigger context window unhelpful.

Agents raise the stakes on this

An agent debugging a failure has exactly what the log says and no memory of the incident. It cannot notice that the timestamps look wrong, or that this is the third time this week. It will confidently build an explanation from whatever is there.

Which means a thin log does not merely slow it down — it produces a plausible wrong answer faster than a person would have produced a right one. Recording the decision rather than the traffic is what keeps that from happening.

FAQ

How much should I log? Enough to reconstruct a decision, little enough that one important line is not buried. If a line appears more than once per request, question it.

Structured or plain text? Structured if anything will query it; plain if a person is the only reader. Consistency matters more than the choice.

What log level should errors be? Reserve error for things somebody should act on. A handled, expected condition logged as an error trains everybody to ignore errors.

How long should logs be kept? Long enough to cover the gap between a failure and somebody noticing — usually longer than teams assume, because the failures that matter are the quiet ones.

What does aidrop.it record? A deployment carries an explicit stage and, if it stops, a stop reason attached to that stage, so a failed run says where and why rather than leaving it to be inferred from a log.


Cover: https://unsplash.com/photos/AGQZprOABgQ by iSawRed on Unsplash. Alt text: A close-up of an industrial control panel covered in grey switches and indicator buttons.

Before the next deploy

Get it running from the session you are already in

Connect your coding agent over MCP and ask it to deploy. aidrop builds the repository and runs it on a public address; when a build or the app fails, the log says why, and your agent fixes it and builds again.