**Approach (brief)** Stream each file (including gzip) line-by-line to avoid loading large logs. Detect the first line that matches the exception type, then capture a minimal stack trace (consecutive indented frames) plus N lines of context before and after. Support rotated/compressed logs by globbing filename patterns and processing in time order.**Python implementation**python
#!/usr/bin/env python3
import gzip, io, glob, re, os, sys
from collections import deque
EXC = re.compile(r'\bValueError\b|\bMyException\b') # change to target
FRAME = re.compile(r'^\s+File .*?, line \d+')
CONTEXT = 3
def open_stream(path):
if path.endswith('.gz'):
return io.TextIOWrapper(gzip.open(path, 'rb'), encoding='utf-8', errors='replace')
return open(path, 'r', encoding='utf-8', errors='replace')
def find_first_exception(paths):
before = deque(maxlen=CONTEXT)
for p in paths:
with open_stream(p) as f:
while True:
line = f.readline()
if not line:
break
before.append(line.rstrip('\n'))
if EXC.search(line):
snippet = list(before)
# capture stack trace lines immediately following
while True:
nxt = f.readline()
if not nxt: break
snippet.append(nxt.rstrip('\n'))
if not (FRAME.match(nxt) or nxt.strip()=='' or nxt.startswith('Traceback')):
# stop when frames end and non-exc text follows
# allow a few tail lines
if len(snippet) - CONTEXT > 50: break
# continue capturing frames
return p, snippet
return None, None
def ordered_paths(base_pattern):
files = sorted(glob.glob(base_pattern))
# if rotated like app.log, app.log.1.gz, ensure newest last or adjust as needed
return files
if __name__=='__main__':
pattern = sys.argv[1] if len(sys.argv)>1 else 'logs/app*.log*'
path = ordered_paths(pattern)
p, snip = find_first_exception(path)
if p:
out = f'File: {p}\n\n' + '\n'.join(snip)
print(out)
else:
print('No exception found')
**Why this works**- Streams lines to keep memory low.- Handles gzip rotated logs.- Uses context buffer to include prior lines for reproducibility.- Easy to adapt regex for other exception patterns, include timestamps, or write directly to a bug tracker API.**Edge cases & improvements**- Multi-line exceptions (custom parser), different stack formats, log encoding variations — normalize encodings and extend FRAME regex. Add limits to prevent capturing entire file.