ai newsDi., 20. Okt.
EilmeldungDeepSeek gave away its engine. The $38-an-hour parts stayed home

Finally Pinpointed Intermittent Staging Failures with AI Log Analysis

Man, I've been tearing my hair out for the past few weeks. You know the drill – your staging environment, the place where everything should mostly work like production, but it occasionally just… dies. Not consistently, mind you. Just often enough to block deploys, frustrate the team, and send me do

dev.toDienstag 16:00 · 20.10.4 Min. Lesezeit
Bild: dev.to

Man, I've been tearing my hair out for the past few weeks. You know the drill – your staging environment, the place where everything should mostly work like production, but it occasionally just… dies. Not consistently, mind you. Just often enough to block deploys, frustrate the team, and send me down rabbit holes that felt more like quicksand.

Our staging environment is a pretty standard microservice setup. Dozens of services, a few databases, Kafka, Redis, the works. It generally hums along fine, but every other day, often during peak development hours, one or two crucial services would just start throwing Connection refused by upstream or Service Unavailable errors. They'd last for 5-10 minutes, then mysteriously clear up. No specific deployment triggered it. No obvious load spike. Just a ghost in the machine.

Debugging this stuff is a nightmare. I couldn't reproduce it locally. Running a stress test on staging didn't always trigger it either. It was like a shy bug, only appearing when it felt like it. We'd check service logs, restart pods, scratch our heads, and eventually, it'd just fix itself. The classic indie dev nightmare.

My first instinct, naturally, was to dive into the logs. I spent nearly two weeks just manually sifting through gigabytes of structured JSON logs, feeling like a digital detective without a map. I'd kubectl logs my-problem-pod -f | jq '.', then grep for specific error messages, trying to correlate timestamps across different services. I even wrote a few awk scripts to count error frequencies, but the sheer volume and the intermittent nature meant I was mostly just staring at a firehose of text, hoping for an epiphany.

We already had decent monitoring with Prometheus and Grafana. The dashboards showed CPU, memory, network I/O. Nothing screamed "problem!" right before the incidents. CPU might tick up a bit, but nothing alarming. I thought maybe it was a resource leak, so we tried scaling up the affected services, bumping memory limits, giving them more dedicated CPU. Nope, the ghost still showed up. Multiple eyes (my teammates) went through the code of the main services, looking for obvious race conditions or weird concurrency issues. Still nothing. It was frustrating.

I was reaching my breaking point. I started thinking, what if a machine could connect the dots that my human brain, bogged down by confirmation bias and sheer log volume, couldn't? I didn't have time to set up a full-blown ELK stack for advanced log analysis, nor did I want to throw money at a commercial log management solution just yet. I decided to build something quick and dirty myself.

My "AI" was actually just a rather specific Python script, log_correlator.py, running on Python 3.9. Here's the gist of it:

Log Collection: Every hour, a cron job on our Kubernetes cluster would dump all service logs from the past hour into an S3 bucket. We used fluentd to push logs to S3, ensuring they were in a consistent JSON format.

Processing: My Python script would download these logs from S3 (using boto3), parse them with json.loads, and then structure them into pandas DataFrames. Crucially, I extracted timestamp, service_name, level (INFO, WARN, ERROR), and message.

Pattern Matching & Correlation: This was the "AI" part. Instead of deep learning, I focused on looking for statistically significant co-occurrences. I built a sliding window (30 seconds, 60 seconds, 120 seconds) and essentially asked: "What WARN or INFO messages from any service frequently precede an ERROR message on a specific problematic service (like our order-processor)?"

The script would group logs by time window, count distinct message strings, and then, for every ERROR on order-processor, it would look back in the window to see which other messages from other services appeared with high frequency. I used collections.Counter and some custom logic for this, essentially a simple form of association rule mining.

And then, it hit me. After letting it run for a couple of days and sifting through its output, a pattern emerged that I had completely missed. Almost every single Connection refused by upstream error on order-processor was preceded, within about 45 seconds, by a WARN message from our notification-service:

log {"timestamp": "2026-10-18T14:32:01.123Z", "service_name": "notification-service", "level": "WARN", "message": "KafkaProducerException: TimeoutException: Failed to send; it took 60000ms. Message buffer full."}

This wasn't an ERROR for notification-service, just a WARN. It meant the notification-service was struggling to send messages to Kafka, causing its internal message buffer to fill up. When that happened, notification-service would become temporarily unresponsive, cascading to order-processor which depended on it. My human brain dismissed WARN messages from other services, focusing only on the ERROR logs of the failing service. The script didn't. It just saw a strong statistical link.

The root cause wasn't order-processor at all, but a bottleneck in notification-service's Kafka producer! We did two things:

It took me maybe 3 full days of coding and iterating on the log processing script to get it right. Our staging environment stability went from about 60% uptime during peak dev hours to over 98%. It's been rock solid for a week now. Sometimes, the most complex problems are solved not by throwing more powerful tools at them, but by cleverly automating the search for patterns you can't see yourself. And jq 1.6 was still a daily companion for spot checks!

Quelle: dev.to (dev.to). Original öffnen