diff --git a/monitoring/monitorlib/errors.py b/monitoring/monitorlib/errors.py index dd5880f465..85121aaff0 100644 --- a/monitoring/monitorlib/errors.py +++ b/monitoring/monitorlib/errors.py @@ -4,3 +4,11 @@ def stacktrace_string(e: Exception) -> str: """Return a multi-line string containing a stacktrace for the specified exception.""" return "".join(traceback.format_exception(e)) + + +def current_stack_string(exclude_levels: int = 1) -> str: + """Return a multi-line string containing a trace of the current execution state.""" + stack = traceback.extract_stack() + if exclude_levels > 0: + stack = stack[0:-exclude_levels] + return "".join(traceback.format_list(stack)) diff --git a/monitoring/uss_qualifier/scenarios/scenario.py b/monitoring/uss_qualifier/scenarios/scenario.py index ccdec94961..964ead7fdb 100644 --- a/monitoring/uss_qualifier/scenarios/scenario.py +++ b/monitoring/uss_qualifier/scenarios/scenario.py @@ -9,6 +9,7 @@ from monitoring import uss_qualifier as uss_qualifier_module from monitoring.monitorlib import fetch, inspection +from monitoring.monitorlib.errors import current_stack_string from monitoring.monitorlib.inspection import fullname from monitoring.uss_qualifier import scenarios as scenarios_module from monitoring.uss_qualifier.common_data_definitions import Severity @@ -363,6 +364,12 @@ def record_query(self, query: fetch.Query) -> None: self._expect_phase({ScenarioPhase.RunningTestStep, ScenarioPhase.CleaningUp}) if "queries" not in self._step_report: self._step_report.queries = [] + for existing_query in self._step_report.queries: + if query.request.timestamp == existing_query.request.timestamp: + logger.error( + f"The same query ({query.query_type} to {query.participant_id} at {query.request.timestamp}) was recorded multiple times. This is likely a bug in uss_qualifier at:\n{current_stack_string(2)}" + ) + return self._step_report.queries.append(query) participant = ( "UNKNOWN"