Skip to content

Commit c34f74e

Browse files
committed
improvement(sct/service): Locate coredumps in new events system
This commit splits the coredump finding logic into the legacy text event function and a coredump link creator, which is now also used inside the new event system, checking each event if it's a coredump and then trying to create a link for it. Fixes ARGUS-102
1 parent cad6009 commit c34f74e

1 file changed

Lines changed: 58 additions & 31 deletions

File tree

argus/backend/plugins/sct/service.py

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
import math
66
import re
77
from time import time
8+
from typing import TypedDict
89
from uuid import UUID
910
from xml.etree import ElementTree
1011
from flask import current_app, g
12+
from cassandra.util import uuid_from_time
1113
from argus.backend.db import ScyllaCluster
1214
from argus.backend.models.github_issue import GithubIssue, IssueLink
1315
from argus.backend.models.web import ArgusEventTypes, ErrorEventEmbeddings, CriticalEventEmbeddings
@@ -78,6 +80,10 @@ class EventSubmitRequest:
7880
nemesis_status: str | None = None
7981

8082

83+
class CoredumpLink(TypedDict):
84+
log_name: str
85+
log_link: str
86+
8187

8288
class SCTService:
8389

@@ -413,8 +419,8 @@ def finalize_nemesis(run_id: str, nemesis_details: dict) -> str:
413419
return "updated"
414420

415421

416-
@staticmethod
417-
def submit_event(run_id: str, raw_event: RawEventPayload):
422+
@classmethod
423+
def submit_event(cls, run_id: str, raw_event: RawEventPayload):
418424
req = EventSubmitRequest(**raw_event)
419425

420426
event = SCTEvent()
@@ -438,7 +444,13 @@ def submit_event(run_id: str, raw_event: RawEventPayload):
438444
event.known_issue = req.known_issue
439445

440446
event.save()
441-
447+
try:
448+
if event.event_type.lower() == "coredumpevent" and (link := cls.create_coredump_link(event.message, event.ts)):
449+
run: SCTTestRun = SCTTestRun.get(id=event.run_id)
450+
run.submit_logs([link])
451+
run.save()
452+
except Exception:
453+
LOGGER.warning("Unable to parse event for coredump links.", exc_info=True)
442454
# Add to unprocessed events queue for ERROR and CRITICAL events
443455
if event.severity in (SCTEventSeverity.ERROR.value, SCTEventSeverity.CRITICAL.value):
444456
try:
@@ -490,41 +502,56 @@ def submit_events(run_id: str, events: list[dict]) -> str:
490502

491503
return "added"
492504

493-
@staticmethod
494-
def locate_coredumps(run: SCTTestRun, events: list[EventsBySeverity]) -> list[dict]:
505+
@classmethod
506+
def locate_coredumps(cls, run: SCTTestRun, events: list[EventsBySeverity]) -> list[CoredumpLink]:
495507
flat_messages: list[str] = []
496508
links = []
497509
for es in events:
498510
flat_messages.extend(es.last_events)
499511
coredump_events = filter(lambda v: "coredumpevent" in v.lower(), flat_messages)
500-
for idx, event in enumerate(coredump_events):
501-
core_pattern = r"corefile_url=(?P<url>.+)$"
502-
ts_pattern = r"^(?P<ts>\d{4}-\d{2}-\d{2} ([\d:]*)\.\d{3})"
503-
node_name_pattern = r"node=(?P<name>.+)$"
504-
core_url_match = re.search(core_pattern, event, re.MULTILINE)
505-
node_name_match = re.search(node_name_pattern, event, re.MULTILINE)
506-
ts_match = re.search(ts_pattern, event)
507-
if core_url_match:
508-
node_name = node_name_match.group("name") if node_name_match else f"unknown-node-{idx}"
509-
split_name = node_name.split(" ")
510-
node_name = split_name[1] if len(split_name) >= 2 else node_name
511-
url = core_url_match.group("url")
512-
ext = url.rsplit(".", maxsplit=1)[-1]
513-
ext = ext if len(ext) <= 5 else "zst" # Default to .zst if URL doesn't conform
514-
timestamp_component = ""
515-
if ts_match:
516-
try:
517-
timestamp = datetime.fromisoformat(ts_match.group("ts"))
518-
timestamp_component = timestamp.strftime("-%Y-%m-%d_%H-%M-%S")
519-
except ValueError:
520-
pass
521-
log_link = {
522-
"log_name": f"core.scylla-{node_name}{timestamp_component}.{ext}",
523-
"log_link": url
524-
}
525-
links.append(log_link)
512+
for event in coredump_events:
513+
if link := cls.create_coredump_link(event):
514+
links.append(link)
526515
return links
527516

517+
@staticmethod
518+
def create_coredump_link(event_message: str, event_ts: datetime | None = None) -> CoredumpLink | None:
519+
core_pattern = r"corefile_url=(?P<url>.+)$"
520+
ts_pattern = r"^(?P<ts>\d{4}-\d{2}-\d{2} ([\d:]*)\.\d{3})"
521+
node_name_pattern = r"node=(?P<name>.+)$"
522+
core_url_match = re.search(core_pattern, event_message, re.MULTILINE)
523+
node_name_match = re.search(node_name_pattern, event_message, re.MULTILINE)
524+
ts_match = re.search(ts_pattern, event_message)
525+
timestamp = datetime.now(UTC)
526+
if core_url_match:
527+
url = core_url_match.group("url")
528+
ext = url.rsplit(".", maxsplit=1)[-1]
529+
ext = ext if len(ext) <= 5 else "zst" # Default to .zst if URL doesn't conform
530+
timestamp_component = ""
531+
if event_ts:
532+
timestamp_component = event_ts.strftime("-%Y-%m-%d_%H-%M-%S")
533+
elif ts_match:
534+
try:
535+
timestamp = datetime.fromisoformat(ts_match.group("ts"))
536+
timestamp_component = timestamp.strftime("-%Y-%m-%d_%H-%M-%S")
537+
except ValueError:
538+
pass
539+
else:
540+
timestamp_component = timestamp.strftime("-%Y-%m-%d_%H-%M-%S")
541+
node_name = (
542+
node_name_match.group("name")
543+
if node_name_match
544+
else f"unknown-node-{uuid_from_time(event_ts or timestamp, node=1000, clock_seq=128)}"
545+
)
546+
split_name = node_name.split(" ")
547+
node_name = split_name[1] if len(split_name) >= 2 else node_name
548+
log_link = {
549+
"log_name": f"core.scylla-{node_name}{timestamp_component}.{ext}",
550+
"log_link": url
551+
}
552+
return log_link
553+
return None
554+
528555
@staticmethod
529556
def get_similar_events(run_id: str) -> list[dict]:
530557
"""Get similar events for each event in a test run

0 commit comments

Comments
 (0)