Skip to content

Commit bfbd09f

Browse files
committed
adding back streaming
1 parent 73966b2 commit bfbd09f

1 file changed

Lines changed: 30 additions & 19 deletions

File tree

‎log_parser.py‎

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import sys
44
import time
5+
import json
56
import argparse
67
import requests
78
import re
@@ -63,10 +64,11 @@ def classify_severity(line: str) -> str:
6364
return "UNKNOWN"
6465

6566

66-
def explain_log_line(line: str, model: str, context: str = "") -> str:
67+
def explain_log_line(line: str, model: str, context: str = "") -> None:
68+
"""Stream an explanation of a log line token by token from Ollama."""
6769
line = line.strip()
6870
if not line:
69-
return ""
71+
return
7072

7173
context_clause = f" familiar with {context} applications" if context else ""
7274
system_prompt = SYSTEM_PROMPT_TEMPLATE.format(context_clause=context_clause)
@@ -75,21 +77,33 @@ def explain_log_line(line: str, model: str, context: str = "") -> str:
7577
"model": model,
7678
"messages": [
7779
{"role": "system", "content": system_prompt},
78-
{"role": "user", "content": f"Explain this application log line in plain English, Keep explanations concise — 1-2 sentences maximum. Focus on what it means and whether action is needed.:\n\n{line}"}
80+
{"role": "user", "content": (
81+
"Explain this application log line in plain English. "
82+
"Keep it concise — 1-2 sentences maximum. "
83+
"Focus on what it means and whether action is needed.:\n\n" + line
84+
)},
7985
],
80-
"stream": False,
86+
"stream": True,
8187
}
8288

8389
try:
84-
response = requests.post(OLLAMA_URL, json=payload, timeout=30)
85-
response.raise_for_status()
86-
return response.json().get("message", {}).get("content", "").strip()
90+
print(f" {DIM}↳{RESET} ", end="", flush=True)
91+
with requests.post(OLLAMA_URL, json=payload, timeout=30, stream=True) as response:
92+
response.raise_for_status()
93+
for chunk in response.iter_lines():
94+
if chunk:
95+
data = json.loads(chunk)
96+
token = data.get("message", {}).get("content", "")
97+
print(token, end="", flush=True)
98+
if data.get("done"):
99+
break
100+
print() # newline after stream ends
87101
except requests.exceptions.ConnectionError:
88-
return "[ERROR] Cannot connect to Ollama. Is it running? Try: ollama serve"
102+
print(f"[ERROR] Cannot connect to Ollama. Is it running? Try: ollama serve")
89103
except requests.exceptions.Timeout:
90-
return "[ERROR] Ollama timed out. Model may still be loading."
104+
print(f"[ERROR] Ollama timed out. Model may still be loading.")
91105
except Exception as e:
92-
return f"[ERROR] {str(e)}"
106+
print(f"[ERROR] {str(e)}")
93107

94108

95109
class PatternDetector:
@@ -185,7 +199,7 @@ def tail_file(filepath: str, model: str, context: str, min_severity: str): # pr
185199
detector = PatternDetector(window_seconds=60, threshold=5)
186200
summarizer = IncidentSummarizer(window_seconds=120, spike_threshold=10)
187201

188-
print(f"\n{BOLD}🔍 Log Explainer{RESET} — SRE Incident Response Tool")
202+
print(f"\n{BOLD}Log Explainer{RESET} — SRE Incident Response Tool")
189203
print(f"{DIM}File: {filepath}{RESET}")
190204
print(f"{DIM}Model: {model}{RESET}")
191205
print(f"{DIM}Filter: {min_severity}+{RESET}")
@@ -238,17 +252,14 @@ def tail_file(filepath: str, model: str, context: str, min_severity: str): # pr
238252
if repeat_count:
239253
print(f" {SEVERITY_COLORS['WARN']}⚠ Pattern repeated {repeat_count}x in 60s — possible recurring issue{RESET}")
240254

241-
# Explain the line
242-
explanation = explain_log_line(line, model, context)
243-
if explanation:
244-
print(f" {DIM}↳{RESET} {explanation}")
255+
# Stream explanation token by token
256+
explain_log_line(line, model, context)
245257

246258
# Incident summary on error spikes
247259
if summarizer.should_summarize():
248260
print()
249-
print(f"{SEVERITY_COLORS['CRITICAL']}{BOLD}🚨 INCIDENT SPIKE DETECTED — generating summary...{RESET}")
250-
summary = explain_log_line(summarizer.get_summary_prompt(), model, context)
251-
print(f"{BOLD}{summary}{RESET}")
261+
print(f"{SEVERITY_COLORS['CRITICAL']}{BOLD}INCIDENT SPIKE DETECTED — generating summary...{RESET}")
262+
explain_log_line(summarizer.get_summary_prompt(), model, context)
252263
print_separator()
253264

254265
print()
@@ -287,4 +298,4 @@ def main(): # pragma: no cover
287298

288299

289300
if __name__ == "__main__":
290-
main()
301+
main()

0 commit comments

Comments
 (0)