Analyzing logs with AI: from thousands of lines to a clear cause of failure

Do not send gigabytes of logs to a model. Filter, group by templates, ask for hypotheses tied to lines and verify them. Code and price estimate inside.

4 min · · автоматизация · development

AI for log analysis finds patterns in noise well, but it has two weaknesses: huge volumes and a tendency to produce a plausible story instead of a verified one. The fix is the same for both: put a filter and compression before the model, and a hypothesis check after it. Below is a working scheme: how to reduce a million lines to a few thousand tokens, what to ask the model, how to check the answer and what it costs. The same approach fits other large texts: exports, correspondence, reports.

Why you cannot just send the whole file

Logs are heavy. As a rough guide take a 100-character line as 30 tokens (the number differs for different logs and languages; the exact value comes from token counting). Then a million lines is 30M tokens: more than the context of any model in the catalog (most have 1M, Grok 256K, GLM 128K). And even if it fit, you would pay for input on all the repeating lines. Besides, with very long contexts models may notice details in the middle less well: test this on your data.

So we work in four steps.

Step 1. Narrow by time and level

An incident almost always has a window: from the first alert to recovery. Take it with a margin and drop the DEBUG and INFO levels unless you suspect the cause is in them.

bash
awk '$1 >= "2026-10-18T09:40" && $1 <= "2026-10-18T10:20"' app.log \
  | grep -E 'WARN|ERROR|FATAL' > window.log
wc -l window.log

The command takes lines within the incident window, WARN level and above. The time format in awk depends on your log, so adjust it.

Step 2. Fold by templates

Thousands of identical errors differ only in numbers, identifiers and addresses. We replace the variable parts with markers and count how many times each template occurs.

bash
import re
from collections import Counter

PATTERNS = [
    (re.compile(r"\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b"), "<UUID>"),
    (re.compile(r"\b\d{1,3}(?:\.\d{1,3}){3}\b"), "<IP>"),
    (re.compile(r"\b0x[0-9a-fA-F]+\b"), "<HEX>"),
    (re.compile(r"\b\d+\b"), "<N>"),
]

def template(line: str) -> str:
    for rx, mark in PATTERNS:
        line = rx.sub(mark, line)
    return line

The output is a list of a few dozen templates with repeat counts and the number of the first line. This is the main part of the future request. Chronology matters as much as frequency, so we keep the first line number: the template that appeared first is often the cause, and the flood of later ones is the effect.

Step 3. Add context around the first error

Templates lose detail. Add a small raw fragment around the earliest error, for example 30 lines before and 10 after, plus the stack trace if there is one. Scrub secrets (tokens, passwords, customer addresses) before sending.

Step 4. The request: hypotheses with evidence

Do not ask "find the cause"; ask for a structured answer where each hypothesis is tied to lines.

bash
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_your_key")

templates = open("templates.txt", encoding="utf-8").read()
raw = open("first_error_context.txt", encoding="utf-8").read()

prompt = f"""Below is a summary of the logs for the incident window and a raw fragment at the first error.
Summary: line template, repeat count, number of the first line.

SUMMARY:
{templates}

FRAGMENT:

The requirement "which command to run to verify" turns the answer from a story into a verification plan. Client documentation: Python SDK.

Verifying hypotheses

The model's answer is a set of hypotheses, not a diagnosis. For each one, run the check from the answer: look at metrics and deploys in the same window, find in the original logs the lines the model refers to, reproduce the error on a stand. If the model names a line number or a function name, find them yourself: invented details happen. Only after that change the system. For hard cases you can continue the dialogue, showing the results of the checks, and ask it to update the hypotheses.

What it costs

Suppose the window has 200,000 lines, and after folding and context 15,000 input tokens remain; the model's answer is 1,500 tokens. Formula without cache: input × input price + output × output price. Prices as of October 18, 2026, $ per 1M tokens:

  • claude-sonnet-5-5 (0.4 / 2): 0.015 × 0.4 + 0.0015 × 2 = 0.006 + 0.003 = $0.009.
  • claude-opus-5-5 (0.8 / 4): 0.015 × 0.8 + 0.0015 × 4 = 0.012 + 0.006 = $0.018.
  • deepseek-v4.1-flash (0.013 / 0.038): 0.015 × 0.013 + 0.0015 × 0.038 = 0.000195 + 0.000057 = $0.000252.

For comparison, 200,000 lines without folding (at an assumed 30 tokens per line that is 6M tokens) would not fit in the context of any model in the catalog, and at the Sonnet 5.5 input price would cost 6 × 0.4 = $2.4 per request, without the output. Folding makes the analysis both possible and cheap. Current prices: GET https://api.zukko.pro/v1/models; you can check the request size in advance via POST /v1/messages/count_tokens.

If there are very many logs, you can use a two-stage scheme: a cheap model labels blocks, a strong one analyses the selected ones. The topic is covered in detail in the article on summarizing long documents.

Connecting

The scripts above work with any OpenAI-compatible client: create a key in the dashboard and set the base URL https://api.zukko.pro/v1. You can top up the balance via SBP, a MasterCard card or cryptocurrency. If you do not use Python, see the Chat Completions page.

FAQ

Can I send production logs to a model?

Only after scrubbing secrets and personal data and in line with your company's policy. Scrub tokens, e-mails and phone numbers automatically, and review the final request by hand.

Will AI for analyzing large texts understand any log format?

For typical formats (text lines, JSON lines), yes. For an exotic format, give one or two sample lines in the request with an explanation of what each field means.

Why did the model name a cause that turned out to be wrong?

A model gives the most plausible explanation from the data you showed it. If the data is thin, the story can be wrong. That is why you ask for hypotheses with verification and a statement of missing data.

Which model should I take?

A cheap one is enough for folding and first-pass labelling; for analysing a hard failure try a stronger one. Compare on a past incident whose cause you already know.

zukko

Pay 25×
less

for Claude Code & ChatGPT

One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.

Get API keyDocumentation

api.zukko.pro · fetch_*

AI for log analysis: compression, hypotheses, cost · Zukko