This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
logwhisper is a small Go CLI that reads production log lines and explains them in plain English: what happened, the likely cause, and the next thing to check.
logwhisper examples/production.log
cat app.log | logwhisper -model llama3.2:3b
The AI part runs entirely on my own machine through Ollama and an open-weight model (Llama 3.2). No API key, no cloud call, no log line ever leaving the box.
Who gets to be a little lazier because of it? The on-call version of me. The tool was born from a familiar 2 a.m. scene: an incident, a wall of log lines, and the slow work of reading them one by one until a pattern shows up. logwhisper does the first pass — the reading — so the human can start at the diagnosis.
Demo
A sample incident log ships in the repo (examples/production.log): a Go service whose Postgres runs out of connection slots at 02:15 and starts failing requests. Here is logwhisper on it, running the small llama3.2:1b model locally:
$ ./logwhisper -model llama3.2:1b examples/production.log
5. "Slow query" - A query to retrieve orders was slow, taking 1,823 milliseconds to complete.
6. "Query failed" - A query to insert order items failed due to a connection error.
7. "Request failed" - A POST request to create order items failed due to a connection error.
10. "Connection pool waiting" - The connection pool is waiting for 37 requests to be fulfilled.
11. "Query failed" - A query to retrieve the balance of a specific user failed due to a password authentication error.
12. "Read replica disabled" - The read replica database is disabled, and the server is falling back to the primary database.
16. "Postgres connections still high" - There are still high levels of connections to Postgres.
Honest note: the 1B model mostly narrates line by line. It reads the log back to you in plain words, which is already useful at 2 a.m., but the real cause-and-effect synthesis gets noticeably better with llama3.2:3b. The tool doesn't care which one you run — that's the point of building on a local, swappable model.
Code
logwhisper is one Go module with zero dependencies — standard library only:
-
cmd/logwhisper— flags and env config (-model,-host,OLLAMA_HOST,OLLAMA_MODEL), stdin or file input -
internal/chunk— splits long logs into pieces a small model's context window can actually hold (40 lines / 6000 bytes by default, never splits a line in half) -
internal/prompt— a fixed What happened / Likely cause / Next check template, worded to stop a small model from inventing a root cause it can't see -
internal/ollama— a thin client for Ollama's/api/generate, with an honest error when Ollama isn't running that tells you exactly how to start it
Unit tests cover the chunking, the prompt builder, and the client (including an unreachable-server case and a stub Ollama server). go build ./... and go test ./... are green.
How I Built It
The design constraint came first: whatever I built, the model had to be open and local. Ollama made that part boring in the best way — pull a model, get an HTTP API on localhost:11434, done.
The interesting problems were the unglamorous ones:
- Context windows are small. A real incident log doesn't fit in a 1B model's context. So logwhisper chunks by lines and bytes and explains piece by piece, labeling each part.
- Small models bluff. Ask a small model "what's the root cause?" and it will happily invent one. The prompt template separates observation ("what happened") from hypothesis ("likely cause") and tells the model to say when the log doesn't contain the answer.
-
Failure should teach. If Ollama is down, the tool exits with the exact commands to fix it (
ollama serve,ollama pull llama3.2:3b) instead of a naked dial error.
Why Does Open Innovation Matter?
Production logs are some of the most sensitive text a company produces: user IDs, IPs, query parameters, the exact shape of every failure. Pasting them into a hosted AI API means sending that text to someone else's computer, under someone else's retention policy — at 2 a.m., under incident pressure, when nobody is thinking about data policy.
A local open-weight model removes the question entirely. The log stays on the box that produced it. It also costs nothing per call, works with the network cable unplugged, and the model can be swapped the day a better open one drops — I ran the same binary against the 1B and 3B Llama 3.2 builds without changing a line of code.
Slow and steady is also how incidents actually get solved: read carefully, form a hypothesis, check one thing. logwhisper just takes the first, slowest step off my plate.
The Lazy Payoff
Reading a 200-line incident log cold takes me roughly ten minutes before I even start forming a hypothesis. logwhisper's pass takes seconds, and I start from a plain-English summary instead of raw text. It doesn't fix the incident — it gets me to the fixing part faster, with the log never leaving the machine.
Top comments (2)
On-call me would have loved this at 2am — that Postgres connection-pool example is exactly the kind of log where you stare at 200 lines and miss the one that matters. I liked the honesty about the 1B model mostly narrating line by line; that's the trap with small local models, they sound fluent while adding nothing. The fixed What happened / Likely cause / Next check template feels like the right guardrail there. Did you find chunking at 40 lines ever splits a story across two chunks, where the cause is in one and the symptom in the next? That's the bit I'd worry about on a real incident log.
it can. you found the weakest part of the design, honestly. the v1 split is dumb on purpose: 40 lines or 6000 bytes, never cuts a line in half, but it has no idea where a story starts or ends, and nothing carries over into the next chunk.
two things keep it honest at the seam. each part gets labeled with its line range, so you can see exactly where the cut happened. and the prompt tells the model that if the lines aren't enough to name a cause, it should say so instead of inventing one. a symptom-only chunk should come back with "not enough here to tell" rather than a confident guess. should, anyway. small models don't always listen.
the fix I want is an overlap: carry the last few lines of each chunk into the next, so a cause sitting on the boundary shows up on both sides. costs some repeated text, buys continuity. haven't built it yet. I want to test it on real incident logs first and see whether the overlap actually changes the output or just makes it longer.