Skip to content

Commit

Permalink
adding non-fatal stack trace analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
kitrady committed Jul 30, 2024
1 parent 34acd28 commit 1acf11b
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/alogamous/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
line_count_analyzer,
log_line_parser,
loginfo_analyzer,
stack_trace_analyzer,
startup_header_analyzer,
warning_analyzer,
)
Expand Down Expand Up @@ -44,6 +45,7 @@
format_analyzer.FormatAnalyzer(line_parser),
warning_analyzer.WarningAnalyzer(),
loginfo_analyzer.InfoAnalyzer(line_parser),
stack_trace_analyzer.StackTraceAnalyzer(line_parser),
startup_header_analyzer.StartupHeaderAnalyzer(line_parser),
warning_analyzer.WarningAnalyzer(),
],
Expand Down
32 changes: 32 additions & 0 deletions src/alogamous/stack_trace_analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from alogamous import analyzer, log_line_parser


class StackTraceAnalyzer(analyzer.Analyzer):
def __init__(self, line_parser):
self.parser = line_parser
self.stack_trace = False
self.stack_trace_counter = 0
self.stack_trace_lines = []
self.non_fatal_trace = False

def read_log_line(self, line):
line_type = self.parser.parse(line)["type"]
if line_type == log_line_parser.LineType.UNSTRUCTURED_LINE and line.count("Traceback") == 1:
self.stack_trace = True
self.stack_trace_counter += 1
self.stack_trace_lines.append(line)
elif self.stack_trace:
if line_type == log_line_parser.LineType.UNSTRUCTURED_LINE:
self.stack_trace_lines.append(line)
elif line_type == log_line_parser.LineType.HEADER_LINE:
self.stack_trace = False
elif line_type == log_line_parser.LineType.LOG_LINE:
self.stack_trace = False
self.non_fatal_trace = True

def report(self, out_stream):
if self.non_fatal_trace:
out_stream.write(f"{self.stack_trace_counter} non-fatal stack trace(s) found:\n- ")
out_stream.write("\n- ".join(self.stack_trace_lines))
else:
out_stream.write("No non-fatal stack traces were found")
127 changes: 127 additions & 0 deletions tests/stack_trace_analyzer_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
from io import StringIO

from alogamous import log_line_parser, stack_trace_analyzer


def test_stacktrace_where_service_dies():
parser = log_line_parser.LogLineParser(
["datetime", "source", "level", "message"], " - ", "===================================================="
)
stacktrace_checker = stack_trace_analyzer.StackTraceAnalyzer(parser)
in_stream = """2024-07-23 21:13:53,862 - root - INFO - Closing client connection.
2024-07-23 21:13:53,862 - root - INFO - Closing client connection.
Traceback (most recent call last):
File "<frozen runpy>", line 1938, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File ".build/2811/execution/execution_service", line 973, in <module>
app.run(life_cycle_runner.run, life_cycle_runner.stop)
File ".build/2811/app/application.py", line 219, in run
run(self.start(my_date, main, stop))
File ".build/2811/.venv/lib/python3.11/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File ".build/2811/.venv/lib/python3.11/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".build/2811/.venv/lib/python3.11/events.py", line 653, in run_until_done
return future.result()
^^^^^^^^^^^^^^^
File "2811/app/application.py", line 421, in start
await self.task
File "2811/messages/app/runner.py", line 449, in run
await asyncio.gather(*self.running_tasks)
File "2811/messages/processor.py", line 340, in run
await self.dispatch(message)
File ".build/2811/execution/execution_service", line 1315, in market_test
if symbol and obj.region != 'NORTHAMERICA'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'region'"""
out_stream = StringIO()
for line in in_stream.splitlines():
stacktrace_checker.read_log_line(line)
stacktrace_checker.report(out_stream)
assert out_stream.getvalue() == "No non-fatal stack traces were found"


def test_stacktrace_where_service_lives():
parser = log_line_parser.LogLineParser(
["datetime", "source", "level", "message"], " - ", "===================================================="
)
stacktrace_checker = stack_trace_analyzer.StackTraceAnalyzer(parser)
in_stream = """2024-07-23 21:13:53,862 - root - INFO - Closing client connection.
2024-07-23 21:13:53,862 - root - INFO - Closing client connection.
Traceback (most recent call last):
File "<frozen runpy>", line 1938, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File ".build/2811/execution/execution_service", line 973, in <module>
app.run(life_cycle_runner.run, life_cycle_runner.stop)
File ".build/2811/app/application.py", line 219, in run
run(self.start(my_date, main, stop))
File ".build/2811/.venv/lib/python3.11/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File ".build/2811/.venv/lib/python3.11/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File ".build/2811/.venv/lib/python3.11/events.py", line 653, in run_until_done
return future.result()
^^^^^^^^^^^^^^^
File "2811/app/application.py", line 421, in start
await self.task
File "2811/messages/app/runner.py", line 449, in run
await asyncio.gather(*self.running_tasks)
File "2811/messages/processor.py", line 340, in run
await self.dispatch(message)
File ".build/2811/execution/execution_service", line 1315, in market_test
if symbol and obj.region != 'NORTHAMERICA'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'region'
2024-07-23 21:13:54,091 - root - ERROR - Caught exception N/A. Message: Unclosed client session"""
out_stream = StringIO()
for line in in_stream.splitlines():
stacktrace_checker.read_log_line(line)
stacktrace_checker.report(out_stream)
assert (
out_stream.getvalue()
== """1 non-fatal stack trace(s) found:
- Traceback (most recent call last):
- File "<frozen runpy>", line 1938, in _run_module_as_main
- File "<frozen runpy>", line 88, in _run_code
- File ".build/2811/execution/execution_service", line 973, in <module>
- app.run(life_cycle_runner.run, life_cycle_runner.stop)
- File ".build/2811/app/application.py", line 219, in run
- run(self.start(my_date, main, stop))
- File ".build/2811/.venv/lib/python3.11/runners.py", line 190, in run
- return runner.run(main)
- ^^^^^^^^^^^^^^^^
- File ".build/2811/.venv/lib/python3.11/runners.py", line 118, in run
- return self._loop.run_until_complete(task)
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- File ".build/2811/.venv/lib/python3.11/events.py", line 653, in run_until_done
- return future.result()
- ^^^^^^^^^^^^^^^
- File "2811/app/application.py", line 421, in start
- await self.task
- File "2811/messages/app/runner.py", line 449, in run
- await asyncio.gather(*self.running_tasks)
- File "2811/messages/processor.py", line 340, in run
- await self.dispatch(message)
- File ".build/2811/execution/execution_service", line 1315, in market_test
- if symbol and obj.region != 'NORTHAMERICA'
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- AttributeError: 'NoneType' object has no attribute 'region'"""
)


def test_no_stacktrace():
parser = log_line_parser.LogLineParser(
["datetime", "source", "level", "message"], " - ", "===================================================="
)
stacktrace_checker = stack_trace_analyzer.StackTraceAnalyzer(parser)
in_stream = """2024-07-23 21:13:53,862 - root - INFO - Closing client connection.
2024-07-23 21:13:53,862 - root - INFO - Closing client connection."""
out_stream = StringIO()
for line in in_stream.splitlines():
stacktrace_checker.read_log_line(line)
stacktrace_checker.report(out_stream)
assert out_stream.getvalue() == "No non-fatal stack traces were found"

0 comments on commit 1acf11b

Please sign in to comment.