33 BuildMap ,
44 HarnessWeights ,
55)
6- from buttercup .common .datastructures .msg_pb2 import BuildOutput , BuildType , WeightedHarness
6+ from buttercup .common .datastructures .msg_pb2 import BuildOutput , BuildType , WeightedHarness , SubmissionEntry
77from buttercup .common .queues import QueueFactory , QueueNames , ReliableQueue
88from uuid import uuid4
99from redis import Redis
1818logger = logging .getLogger (__name__ )
1919
2020
21+ def truncate_stacktraces (submission : SubmissionEntry , max_length : int = 80 ) -> SubmissionEntry :
22+ """Create a copy of the submission with truncated stacktraces for display purposes."""
23+ # Create a new submission and copy the fields manually to ensure proper truncation
24+ from google .protobuf import text_format
25+
26+ # Serialize to text and then parse back to create a proper copy
27+ submission_text = text_format .MessageToString (submission )
28+ truncated_submission = SubmissionEntry ()
29+ text_format .Parse (submission_text , truncated_submission )
30+
31+ # Now truncate the stacktraces and crash token
32+ for crash in truncated_submission .crashes :
33+ if crash .crash .stacktrace and len (crash .crash .stacktrace ) > max_length :
34+ crash .crash .stacktrace = crash .crash .stacktrace [:max_length ] + "... (truncated)"
35+
36+ if crash .tracer_stacktrace and len (crash .tracer_stacktrace ) > max_length :
37+ crash .tracer_stacktrace = crash .tracer_stacktrace [:max_length ] + "... (truncated)"
38+
39+ if crash .crash .crash_token and len (crash .crash .crash_token ) > max_length :
40+ crash .crash .crash_token = crash .crash .crash_token [:max_length ] + "... (truncated)"
41+
42+ return truncated_submission
43+
44+
2145def get_queue_names ():
2246 return [f"'{ queue_name .value } '" for queue_name in QueueNames ]
2347
@@ -49,6 +73,10 @@ class ReadBuildsSettings(BaseModel):
4973 build_type : CliPositionalArg [str ] = Field (description = "Build type (one of " + ", " .join (get_build_types ()) + ")" )
5074
5175
76+ class ReadSubmissionsSettings (BaseModel ):
77+ verbose : bool = Field (False , description = "Show full stacktraces instead of truncated versions" )
78+
79+
5280class AddHarnessWeightSettings (BaseModel ):
5381 msg_path : CliPositionalArg [Path ] = Field (description = "Path to WeightedHarness file in Protobuf text format" )
5482
@@ -73,6 +101,7 @@ class Settings(BaseSettings):
73101 add_build : CliSubCommand [AddBuildSettings ]
74102 read_harnesses : CliSubCommand [ReadHarnessWeightSettings ]
75103 read_builds : CliSubCommand [ReadBuildsSettings ]
104+ read_submissions : CliSubCommand [ReadSubmissionsSettings ]
76105
77106 class Config :
78107 env_prefix = "BUTTERCUP_MSG_PUBLISHER_"
@@ -146,6 +175,31 @@ def main():
146175 for build in BuildMap (redis ).get_builds (command .task_id , build_type ):
147176 print (build )
148177 logger .info ("Done" )
178+ elif isinstance (command , ReadSubmissionsSettings ):
179+ # Read submissions from Redis using the same key as the Submissions class
180+ SUBMISSIONS_KEY = "submissions"
181+ raw_submissions = redis .lrange (SUBMISSIONS_KEY , 0 , - 1 )
182+
183+ if not raw_submissions :
184+ logger .info ("No submissions found" )
185+ return
186+
187+ logger .info (f"Found { len (raw_submissions )} submissions:" )
188+ for i , raw in enumerate (raw_submissions ):
189+ try :
190+ submission = SubmissionEntry .FromString (raw )
191+
192+ # Apply stacktrace truncation unless verbose mode is enabled
193+ if not command .verbose :
194+ submission = truncate_stacktraces (submission )
195+
196+ print (f"--- Submission { i } ---" )
197+ print (submission )
198+ print ()
199+ except Exception as e :
200+ logger .error (f"Failed to parse submission { i } : { e } " )
201+
202+ logger .info ("Done" )
149203 elif isinstance (command , ListSettings ):
150204 print ("Available queues:" )
151205 print ("\n " .join ([f"- { name } " for name in get_queue_names ()]))
0 commit comments