From patchwork Tue Feb 21 09:00:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147503 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 96F66C61DA3 for ; Tue, 21 Feb 2023 09:02:24 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWU-0007eU-Ce; Tue, 21 Feb 2023 04:01:18 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWT-0007e8-3T for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:17 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWR-0005Su-2z for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:16 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970071; bh=gyQnCVNzCEHVqVEoI58x5xyPhDVaVkRYebDl9/4EbWs=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=OdXbchtSCBOhe4ClOJ7lAcK+RvXMEFv4Oiwhf/ShKLz6uQi3sDfhAjj5ZtHkom67I AL5wfbmRiP4QSAOnLk0pI5BP4rgafIJF4WaEkUVp5s0y0ZHWZWqKEzkf5Jyw0JKEl1 96o6opRXBdhQBge3LhronaAgfaitB0qTAWzV3wETWpP4+Odd+EThvX/GnhRRtBeo0X E+/RmTV7F3oi6oDbJs9nU2gSQt/AUGTg1teP3wczVchmvIYYKUEa85Skx44FJF1Z0r 8jK9V9aTc6Ymig5bv5hoO72rx2zibMSQnJvWGqyZMYlhzSzTuQ5dWHreHOVUYp/SAv 6eJL3Lk6tMulQ== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 11C209629C2; Tue, 21 Feb 2023 09:01:09 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 1/9] simpletrace: Improve parsing of sys.argv; fix files never closed. Date: Tue, 21 Feb 2023 10:00:56 +0100 Message-Id: <20230221090104.86103-2-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: Vr-dEIAdOUs3DDOmtY6XERk7hsi-dRPg X-Proofpoint-GUID: Vr-dEIAdOUs3DDOmtY6XERk7hsi-dRPg X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=643 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal The arguments extracted from `sys.argv` named and unpacked to make it clear what the arguments are and what they're used for. The two input files were opened, but never explicitly closed. File usage changed to use `with` statement to take care of this. At the same time, ownership of the file-object is moved up to `run` function. Secondary `open` inside `process` removed so there's only one place to handle `open`. Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 1f6d1ae1f3..9211caaec1 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -9,6 +9,7 @@ # # For help see docs/devel/tracing.rst +import sys import struct import inspect from tracetool import read_events, Event @@ -44,7 +45,6 @@ def get_record(edict, idtoname, rechdr, fobj): try: event = edict[name] except KeyError as e: - import sys sys.stderr.write('%s event is logged but is not declared ' \ 'in the trace events file, try using ' \ 'trace-events-all instead.\n' % str(e)) @@ -166,11 +166,6 @@ def end(self): def process(events, log, analyzer, read_header=True): """Invoke an analyzer on each event in a log.""" - if isinstance(events, str): - events = read_events(open(events, 'r'), events) - if isinstance(log, str): - log = open(log, 'rb') - if read_header: read_trace_header(log) @@ -223,19 +218,18 @@ def run(analyzer): This function is useful as a driver for simple analysis scripts. More advanced scripts will want to call process() instead.""" - import sys - - read_header = True - if len(sys.argv) == 4 and sys.argv[1] == '--no-header': - read_header = False - del sys.argv[1] - elif len(sys.argv) != 3: - sys.stderr.write('usage: %s [--no-header] ' \ - '\n' % sys.argv[0]) + + try: + # NOTE: See built-in `argparse` module for a more robust cli interface + *no_header, trace_event_path, trace_file_path = sys.argv[1:] + assert no_header == [] or no_header == ['--no-header'], 'Invalid no-header argument' + except (AssertionError, ValueError): + sys.stderr.write(f'usage: {sys.argv[0]} [--no-header] \n') sys.exit(1) - events = read_events(open(sys.argv[1], 'r'), sys.argv[1]) - process(events, sys.argv[2], analyzer, read_header=read_header) + with open(trace_event_path, 'r') as events_fobj, open(trace_file_path, 'rb') as log_fobj: + events = read_events(events_fobj, trace_event_path) + process(events, log_fobj, analyzer, read_header=not no_header) if __name__ == '__main__': class Formatter(Analyzer): From patchwork Tue Feb 21 09:00:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147501 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 08F0EC6379F for ; Tue, 21 Feb 2023 09:01:30 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWV-0007fa-5f; Tue, 21 Feb 2023 04:01:19 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWT-0007eG-M8 for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:17 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWR-0005TV-Pl for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:17 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970073; bh=bQQvCx31M4vekj2rknUKPAqUmbQz4GRIzBFReFyfIzI=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=C3Nv3AxnpGK/VQYYVWV9QUhvTPMeLYbY1WCrW9RDYG+VZYgw+tZAJcLMkJHUZG/IB LzE3q1nK3Lx4ojOnyY7+mLKgboeTo4qH1DOMjQa39Iyqml4TL40oHjK1JNVdFNYAZ4 aqnzA+ccTSkoXcCF3rHgGeFCFpyPyHRC/69mIrUTt2TA1cjNRE/iFHunq/W0G/cKrh 7jHhQJCEPUanqZ1i7eVonJTVhudf/IspcNUtDDIaQHnJew4fTPveLNnBgASgRzWztd 6tGBS+rQE+MUdC8F1S8JQFmGLTA4nc9/QJ9JZGnldU28EdMJY43pdA/idA02tW78An W2YagmTwhumKQ== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 6D273962D74; Tue, 21 Feb 2023 09:01:12 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 2/9] simpletrace: Annotate magic constants from QEMU code Date: Tue, 21 Feb 2023 10:00:57 +0100 Message-Id: <20230221090104.86103-3-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: YvsUpDWk8GUSHxtJ99gzUCmHliWViw5e X-Proofpoint-GUID: YvsUpDWk8GUSHxtJ99gzUCmHliWViw5e X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=614 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal It wasn't clear where the constants and structs came from, so I added comments to help. Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 9211caaec1..7ba805443d 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -15,15 +15,15 @@ from tracetool import read_events, Event from tracetool.backend.simple import is_string -header_event_id = 0xffffffffffffffff -header_magic = 0xf2b177cb0aa429b4 -dropped_event_id = 0xfffffffffffffffe +header_event_id = 0xffffffffffffffff # trace/simple.c::HEADER_EVENT_ID +header_magic = 0xf2b177cb0aa429b4 # trace/simple.c::HEADER_MAGIC +dropped_event_id = 0xfffffffffffffffe # trace/simple.c::DROPPED_EVENT_ID -record_type_mapping = 0 -record_type_event = 1 +record_type_mapping = 0 # trace/simple.c::TRACE_RECORD_TYPE_MAPPING +record_type_event = 1 # trace/simple.c::TRACE_RECORD_TYPE_EVENT -log_header_fmt = '=QQQ' -rec_header_fmt = '=QQII' +log_header_fmt = '=QQQ' # trace/simple.c::TraceLogHeader +rec_header_fmt = '=QQII' # trace/simple.c::TraceRecord def read_header(fobj, hfmt): '''Read a trace record header''' From patchwork Tue Feb 21 09:00:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147505 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 187BEC61DA3 for ; Tue, 21 Feb 2023 09:02:53 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWW-0007hU-5J; Tue, 21 Feb 2023 04:01:20 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWV-0007fZ-1q for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:19 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWS-0005Tp-RP for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:18 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970075; bh=Cxb1trJ8foD+APDBpLzSLwgR6zNyAF1GPfBBNu6t954=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=ArWq4BVAeATN2zYAk0cKAvm/TT6YOxYXhBXSFEgSg0Pnl7v3U0adDTWK+IBOYwcyB VgV8HMwrfA40NyFD/nQx8EkXszm+jewGgvlRlZjXl9tNNdn9FexxociTfrNd11Ai87 6+eZf1H2hH0p9ElHj8UKIsgkybktiFsTNDVg1TTe3Rb3v+SONgKZzu2sRDB/cHxOpU NJlUec8ZOzS4lHwoNV7ul73eCn14MIG/Z3746l5HWYi1u4lDAT1VwPAmto2iTJolk2 Ur9j75Dgs6SG3swx140jdiUzhsAS9eD67Rt5A1eEaVQ0cCk3ECravCTMmwuIqNYFtN USuCcIQpwf62A== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 3441C962598; Tue, 21 Feb 2023 09:01:14 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 3/9] simpletrace: changed naming of edict and idtoname to improve readability Date: Tue, 21 Feb 2023 10:00:58 +0100 Message-Id: <20230221090104.86103-4-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: MOH4mnwrFonPSqSLS7xubh2TqYG1u--Y X-Proofpoint-GUID: MOH4mnwrFonPSqSLS7xubh2TqYG1u--Y X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=746 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal Readability is subjective, but I've expanded the naming of the variables and arguments, to help with understanding for new eyes on the code. Signed-off-by: Mads Ynddal Reviewed-by: Philippe Mathieu-Daudé --- scripts/simpletrace.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 7ba805443d..9981699630 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -33,17 +33,17 @@ def read_header(fobj, hfmt): return None return struct.unpack(hfmt, hdr) -def get_record(edict, idtoname, rechdr, fobj): +def get_record(event_mapping, event_id_to_name, rechdr, fobj): """Deserialize a trace record from a file into a tuple (name, timestamp, pid, arg1, ..., arg6).""" if rechdr is None: return None if rechdr[0] != dropped_event_id: event_id = rechdr[0] - name = idtoname[event_id] + name = event_id_to_name[event_id] rec = (name, rechdr[1], rechdr[3]) try: - event = edict[name] + event = event_mapping[name] except KeyError as e: sys.stderr.write('%s event is logged but is not declared ' \ 'in the trace events file, try using ' \ @@ -72,10 +72,10 @@ def get_mapping(fobj): return (event_id, name) -def read_record(edict, idtoname, fobj): +def read_record(event_mapping, event_id_to_name, fobj): """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" rechdr = read_header(fobj, rec_header_fmt) - return get_record(edict, idtoname, rechdr, fobj) + return get_record(event_mapping, event_id_to_name, rechdr, fobj) def read_trace_header(fobj): """Read and verify trace file header""" @@ -96,14 +96,14 @@ def read_trace_header(fobj): raise ValueError('Log format %d not supported with this QEMU release!' % log_version) -def read_trace_records(edict, idtoname, fobj): +def read_trace_records(event_mapping, event_id_to_name, fobj): """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6). - Note that `idtoname` is modified if the file contains mapping records. + Note that `event_id_to_name` is modified if the file contains mapping records. Args: - edict (str -> Event): events dict, indexed by name - idtoname (int -> str): event names dict, indexed by event ID + event_mapping (str -> Event): events dict, indexed by name + event_id_to_name (int -> str): event names dict, indexed by event ID fobj (file): input file """ @@ -115,9 +115,9 @@ def read_trace_records(edict, idtoname, fobj): (rectype, ) = struct.unpack('=Q', t) if rectype == record_type_mapping: event_id, name = get_mapping(fobj) - idtoname[event_id] = name + event_id_to_name[event_id] = name else: - rec = read_record(edict, idtoname, fobj) + rec = read_record(event_mapping, event_id_to_name, fobj) yield rec @@ -172,16 +172,16 @@ def process(events, log, analyzer, read_header=True): frameinfo = inspect.getframeinfo(inspect.currentframe()) dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)", frameinfo.lineno + 1, frameinfo.filename) - edict = {"dropped": dropped_event} - idtoname = {dropped_event_id: "dropped"} + event_mapping = {"dropped": dropped_event} + event_id_to_name = {dropped_event_id: "dropped"} for event in events: - edict[event.name] = event + event_mapping[event.name] = event # If there is no header assume event ID mapping matches events list if not read_header: for event_id, event in enumerate(events): - idtoname[event_id] = event.name + event_id_to_name[event_id] = event.name def build_fn(analyzer, event): if isinstance(event, str): @@ -205,9 +205,9 @@ def build_fn(analyzer, event): analyzer.begin() fn_cache = {} - for rec in read_trace_records(edict, idtoname, log): + for rec in read_trace_records(event_mapping, event_id_to_name, log): event_num = rec[0] - event = edict[event_num] + event = event_mapping[event_num] if event_num not in fn_cache: fn_cache[event_num] = build_fn(analyzer, event) fn_cache[event_num](event, rec) From patchwork Tue Feb 21 09:00:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147502 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A55EAC6379F for ; Tue, 21 Feb 2023 09:01:37 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWY-0007iB-VZ; Tue, 21 Feb 2023 04:01:23 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWX-0007ht-Bx for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:21 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWV-0005Us-PU for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:21 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970077; bh=rtmjEodPVMUzwYYrkpmLQm9O2of3D9dbaQl2KB0rulo=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=D5gaas3ozPewLlW4MR4IfA6oFenQNtWnmo7h8IzbJ5lKgBQeiaLK7ZZeuD4FYPTWo t/sZalTqoSvrdejUW9ZVVkfnPcB6BeoOqI0mEtm+0sJknPGGJFM1CpzwQ12alkRPh5 swR/IIKTEjda2ciNptofwSLV4UuxKlCRYsLPmKs/SYgPXD9wFeo5M4YO2uo+niUa0C LO/IxVApSNfc7v+BjXfcawIKgtwbp83qlnVWaHAKAzF6tlwf2b1CCVjVObyeEH5hFg U6UrLdkPQa60+RPki9vkIG0YY4iDPxytJDy5P7XOndXj1MYsm05+5XIDuGPrdejdRT uh2pVSfBZQPtw== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 4726E962DE4; Tue, 21 Feb 2023 09:01:16 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 4/9] simpletrace: update code for Python 3.11 Date: Tue, 21 Feb 2023 10:00:59 +0100 Message-Id: <20230221090104.86103-5-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: cZ0hWgeFBoV-sSyB4EZnM3M0CmC-emT7 X-Proofpoint-GUID: cZ0hWgeFBoV-sSyB4EZnM3M0CmC-emT7 X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=754 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal The call to `getargspec` was deprecated and in Python 3.11 it has been removed in favor of `getfullargspec`. Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 9981699630..7444a6e090 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -192,7 +192,7 @@ def build_fn(analyzer, event): return analyzer.catchall event_argcount = len(event.args) - fn_argcount = len(inspect.getargspec(fn)[0]) - 1 + fn_argcount = len(inspect.getfullargspec(fn)[0]) - 1 if fn_argcount == event_argcount + 1: # Include timestamp as first argument return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount])) From patchwork Tue Feb 21 09:01:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147506 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2CDF4C6379F for ; Tue, 21 Feb 2023 09:02:59 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWa-0007k3-TQ; Tue, 21 Feb 2023 04:01:24 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWY-0007iA-N3 for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:22 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWX-0005VG-0K for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:22 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970080; bh=l/aCZe1H5Hng++TSGvfhaA4HhXrphUiVh1oiy3JASog=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=BcjHBLj3lcmFbPBaI6x/g7JORDBhprdtevGeTN/CAszUDsrOeyklEzi7IXFINTA+G Xld1t4eep6RXcwhKoxTHKtZjGSUyyDcMFpGSCQ6vBKGUjmM5zsthLC98vOArHQtfWF cqUYxY4CUkdn4d01mAfKX0mJUUvO5ttgkuclfcxnWP/x0AhyLI42lUoJp3Xyx7oiJF +44XjeFvYuw/jMdkpiPY1IkPCIAGEViw5+qDLGBBSeZvMkrJKJa/DjTov4eWVr8VgK EuXRrlZPzAHBNbLPeTgx2pmwXc80RV+wBasPikMiwfw/7lYHsDDu8Q19rqbqRYIIdg tLd6Nfl/uUABw== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 64613962546; Tue, 21 Feb 2023 09:01:17 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 5/9] simpletrace: Changed Analyzer class to become context-manager Date: Tue, 21 Feb 2023 10:01:00 +0100 Message-Id: <20230221090104.86103-6-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: mjmxTAzBP5vejbrDVVtE5WnMbbuHJIoB X-Proofpoint-GUID: mjmxTAzBP5vejbrDVVtE5WnMbbuHJIoB X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=984 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal Instead of explicitly calling `begin` and `end`, we can change the class to use the context-manager paradigm. This is mostly a styling choice, used in modern Python code. But it also allows for more advanced analyzers to handle exceptions gracefully in the `__exit__` method (not demonstrated here). Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 7444a6e090..01bd47a130 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -121,12 +121,12 @@ def read_trace_records(event_mapping, event_id_to_name, fobj): yield rec -class Analyzer(object): +class Analyzer: """A trace file analyzer which processes trace records. - An analyzer can be passed to run() or process(). The begin() method is - invoked, then each trace record is processed, and finally the end() method - is invoked. + An analyzer can be passed to run() or process(). The __enter__() method is + invoked when opening the analyzer using the `with` statement, then each trace + record is processed, and finally the __exit__() method is invoked. If a method matching a trace event name exists, it is invoked to process that trace record. Otherwise the catchall() method is invoked. @@ -152,19 +152,19 @@ def runstate_set(self, timestamp, pid, new_state): ... """ - def begin(self): + def __enter__(self): """Called at the start of the trace.""" - pass + return self def catchall(self, event, rec): """Called if no specific method for processing a trace event has been found.""" pass - def end(self): + def __exit__(self, _type, value, traceback): """Called at the end of the trace.""" pass -def process(events, log, analyzer, read_header=True): +def process(events, log, analyzer_class, read_header=True): """Invoke an analyzer on each event in a log.""" if read_header: read_trace_header(log) @@ -203,15 +203,15 @@ def build_fn(analyzer, event): # Just arguments, no timestamp or pid return lambda _, rec: fn(*rec[3:3 + event_argcount]) - analyzer.begin() - fn_cache = {} - for rec in read_trace_records(event_mapping, event_id_to_name, log): - event_num = rec[0] - event = event_mapping[event_num] - if event_num not in fn_cache: - fn_cache[event_num] = build_fn(analyzer, event) - fn_cache[event_num](event, rec) - analyzer.end() + with analyzer_class() as analyzer: + fn_cache = {} + for rec in read_trace_records(event_mapping, event_id_to_name, log): + event_num = rec[0] + event = event_mapping[event_num] + if event_num not in fn_cache: + fn_cache[event_num] = build_fn(analyzer, event) + fn_cache[event_num](event, rec) + def run(analyzer): """Execute an analyzer on a trace file given on the command-line. @@ -254,4 +254,4 @@ def catchall(self, event, rec): i += 1 print(' '.join(fields)) - run(Formatter()) + run(Formatter) From patchwork Tue Feb 21 09:01:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147512 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id F3A50C6379F for ; Tue, 21 Feb 2023 09:04:38 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWc-0007kb-QN; Tue, 21 Feb 2023 04:01:26 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWa-0007k4-UH for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:24 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWZ-0005Vh-2B for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:24 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970081; bh=nBHUCSVeaJc/sZEH8GcagQNr0dcQJayGmXVTFHWPvqU=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=IHQZRRxuw/LpVRzLQasfHxwIPQJ8Ppcl2Va4G6aAJWcg8Z9J7IW5KA7krLNFME+MK Rde5fZGlPtv9S87ISsGs/afCTtgq63t7PkyR/eDMKW/7lP/i7H5QN65nP2rkTwlPhL L02y+w2rf78f2ED7i9R5W1m7r/3prK2c3gXhWlWzc9+NwMiA/AGVY4zgHo6VOhPm8y 5EY637eCuzhuil5WQ5o5g8y2N9SklEGJSvRqM9uh1yWs+L+UZvH5jZcHwOFHWLyNpH iOh/U8jC+v3wT/urCM8sWzYcoAzhLsXsEpq2Yc28jl+9vMl/py/Mlpba3jspI14fol ttB1MUKDKSSqA== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 6F1B8962D11; Tue, 21 Feb 2023 09:01:20 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 6/9] simpletrace: Simplify construction of tracing methods Date: Tue, 21 Feb 2023 10:01:01 +0100 Message-Id: <20230221090104.86103-7-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: QIGr0pon3tx98urpSxXjRerrogQxGy3l X-Proofpoint-GUID: QIGr0pon3tx98urpSxXjRerrogQxGy3l X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=880 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal By moving the dynamic argument construction to keyword-arguments, we can remove all of the specialized handling, and streamline it. If a tracing method wants to access these, they can define the kwargs, or ignore it be placing `**kwargs` at the end of the function's arguments list. Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 84 ++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 52 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 01bd47a130..df52b09dbc 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -131,16 +131,25 @@ class Analyzer: If a method matching a trace event name exists, it is invoked to process that trace record. Otherwise the catchall() method is invoked. + The methods are called with a set of keyword-arguments. These can be ignored + using `**kwargs` or defined like any keyword-argument. + + The following keyword-arguments are available: + event: Event object of current trace + event_id: The id of the event in the current trace file + timestamp_ns: The timestamp in nanoseconds of the trace + pid: The process id recorded for the given trace + Example: The following method handles the runstate_set(int new_state) trace event:: - def runstate_set(self, new_state): + def runstate_set(self, new_state, **kwargs): ... - The method can also take a timestamp argument before the trace event - arguments:: + The method can also explicitly take a timestamp keyword-argument with the + trace event arguments:: - def runstate_set(self, timestamp, new_state): + def runstate_set(self, new_state, *, timestamp, **kwargs): ... Timestamps have the uint64_t type and are in nanoseconds. @@ -148,7 +157,7 @@ def runstate_set(self, timestamp, new_state): The pid can be included in addition to the timestamp and is useful when dealing with traces from multiple processes:: - def runstate_set(self, timestamp, pid, new_state): + def runstate_set(self, new_state, *, timestamp, pid, **kwargs): ... """ @@ -156,7 +165,7 @@ def __enter__(self): """Called at the start of the trace.""" return self - def catchall(self, event, rec): + def catchall(self, *rec_args, event, timestamp_ns, pid, event_id): """Called if no specific method for processing a trace event has been found.""" pass @@ -183,34 +192,11 @@ def process(events, log, analyzer_class, read_header=True): for event_id, event in enumerate(events): event_id_to_name[event_id] = event.name - def build_fn(analyzer, event): - if isinstance(event, str): - return analyzer.catchall - - fn = getattr(analyzer, event.name, None) - if fn is None: - return analyzer.catchall - - event_argcount = len(event.args) - fn_argcount = len(inspect.getfullargspec(fn)[0]) - 1 - if fn_argcount == event_argcount + 1: - # Include timestamp as first argument - return lambda _, rec: fn(*(rec[1:2] + rec[3:3 + event_argcount])) - elif fn_argcount == event_argcount + 2: - # Include timestamp and pid - return lambda _, rec: fn(*rec[1:3 + event_argcount]) - else: - # Just arguments, no timestamp or pid - return lambda _, rec: fn(*rec[3:3 + event_argcount]) - with analyzer_class() as analyzer: - fn_cache = {} - for rec in read_trace_records(event_mapping, event_id_to_name, log): - event_num = rec[0] - event = event_mapping[event_num] - if event_num not in fn_cache: - fn_cache[event_num] = build_fn(analyzer, event) - fn_cache[event_num](event, rec) + for event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(event_mapping, event_id_to_name, log): + event = event_mapping[event_id] + fn = getattr(analyzer, event.name, analyzer.catchall) + fn(*rec_args, event=event, event_id=event_id, timestamp_ns=timestamp_ns, pid=record_pid) def run(analyzer): @@ -234,24 +220,18 @@ def run(analyzer): if __name__ == '__main__': class Formatter(Analyzer): def __init__(self): - self.last_timestamp = None - - def catchall(self, event, rec): - timestamp = rec[1] - if self.last_timestamp is None: - self.last_timestamp = timestamp - delta_ns = timestamp - self.last_timestamp - self.last_timestamp = timestamp - - fields = [event.name, '%0.3f' % (delta_ns / 1000.0), - 'pid=%d' % rec[2]] - i = 3 - for type, name in event.args: - if is_string(type): - fields.append('%s=%s' % (name, rec[i])) - else: - fields.append('%s=0x%x' % (name, rec[i])) - i += 1 - print(' '.join(fields)) + self.last_timestamp_ns = None + + def catchall(self, *rec_args, event, timestamp_ns, pid, event_id): + if self.last_timestamp_ns is None: + self.last_timestamp_ns = timestamp_ns + delta_ns = timestamp_ns - self.last_timestamp_ns + self.last_timestamp_ns = timestamp_ns + + fields = [ + f'{name}={r}' if is_string(type) else f'{name}=0x{r:x}' + for r, (type, name) in zip(rec_args, event.args) + ] + print(f'{event.name} {delta_ns / 1000:0.3f} {pid=} ' + ' '.join(fields)) run(Formatter) From patchwork Tue Feb 21 09:01:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147511 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 24C3BC61DA3 for ; Tue, 21 Feb 2023 09:04:39 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWf-0007lU-0C; Tue, 21 Feb 2023 04:01:29 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWd-0007kp-Ap for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:27 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWb-0005W8-Bg for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:27 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970083; bh=vp5ym4NBeJNJFGZweQnKwCeUJEJUDAEMOCLifdsfR+8=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=E+j373L5sR3v15DG7QaR2pE74/Kwf1298EMaNGuMR44IOOMbh5nmEStgmjuFemnuV DKmDdXP75LLdz8KXPD7gF7j83XeDCeoNXHTfFkD1iZD7DCEgDhIMGRTZSmj6w+aKxm erwsarHOB8X6RhymtJ8Z+U5TzrcC70d2REMlGGDi47UUzLkb+Pk1KxY8dDH7Ua9mTp 5sR8U+RcZecYEPDRmfSwMRnJYD6pLhBTSR/6j4emNfOOh4YHsZQg+gmpjMxvyricJ9 l8S4SwWaFt6qbjem0PKnrqDsAfcYWE4murysoOCLER1Sl+3gijhnxiXw43cECOY9G/ mthK7yo09LXGw== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id 4232F962F6E; Tue, 21 Feb 2023 09:01:22 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 7/9] simpletrace: Improved error handling on struct unpack Date: Tue, 21 Feb 2023 10:01:02 +0100 Message-Id: <20230221090104.86103-8-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: KDvqjn--q-Rw9dGnDqRtNbl-2EV__hOQ X-Proofpoint-GUID: KDvqjn--q-Rw9dGnDqRtNbl-2EV__hOQ X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=422 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal A failed call to `read_header` wouldn't be handled the same for the two different code paths (one path would try to use `None` as a list). Changed to raise exception to be handled centrally. This also allows for easier unpacking, as errors has been filtered out. Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 41 ++++++++++++++++------------------------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index df52b09dbc..61af68618f 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -30,26 +30,24 @@ def read_header(fobj, hfmt): hlen = struct.calcsize(hfmt) hdr = fobj.read(hlen) if len(hdr) != hlen: - return None + raise ValueError('Error reading header. Wrong filetype provided?') return struct.unpack(hfmt, hdr) def get_record(event_mapping, event_id_to_name, rechdr, fobj): """Deserialize a trace record from a file into a tuple (name, timestamp, pid, arg1, ..., arg6).""" - if rechdr is None: - return None - if rechdr[0] != dropped_event_id: - event_id = rechdr[0] + event_id, timestamp_ns, length, pid = rechdr + if event_id != dropped_event_id: name = event_id_to_name[event_id] - rec = (name, rechdr[1], rechdr[3]) try: event = event_mapping[name] except KeyError as e: - sys.stderr.write('%s event is logged but is not declared ' \ + sys.stderr.write(f'{e} event is logged but is not declared ' \ 'in the trace events file, try using ' \ - 'trace-events-all instead.\n' % str(e)) + 'trace-events-all instead.\n') sys.exit(1) + rec = (name, timestamp_ns, pid) for type, name in event.args: if is_string(type): l = fobj.read(4) @@ -60,9 +58,8 @@ def get_record(event_mapping, event_id_to_name, rechdr, fobj): (value,) = struct.unpack('=Q', fobj.read(8)) rec = rec + (value,) else: - rec = ("dropped", rechdr[1], rechdr[3]) - (value,) = struct.unpack('=Q', fobj.read(8)) - rec = rec + (value,) + (dropped_count,) = struct.unpack('=Q', fobj.read(8)) + rec = ("dropped", timestamp_ns, pid, dropped_count) return rec def get_mapping(fobj): @@ -79,22 +76,16 @@ def read_record(event_mapping, event_id_to_name, fobj): def read_trace_header(fobj): """Read and verify trace file header""" - header = read_header(fobj, log_header_fmt) - if header is None: - raise ValueError('Not a valid trace file!') - if header[0] != header_event_id: - raise ValueError('Not a valid trace file, header id %d != %d' % - (header[0], header_event_id)) - if header[1] != header_magic: - raise ValueError('Not a valid trace file, header magic %d != %d' % - (header[1], header_magic)) - - log_version = header[2] + _header_event_id, _header_magic, log_version = read_header(fobj, log_header_fmt) + if _header_event_id != header_event_id: + raise ValueError(f'Not a valid trace file, header id {_header_event_id} != {header_event_id}') + if _header_magic != header_magic: + raise ValueError(f'Not a valid trace file, header magic {_header_magic} != {header_magic}') + if log_version not in [0, 2, 3, 4]: - raise ValueError('Unknown version of tracelog format!') + raise ValueError(f'Unknown version {log_version} of tracelog format!') if log_version != 4: - raise ValueError('Log format %d not supported with this QEMU release!' - % log_version) + raise ValueError(f'Log format {log_version} not supported with this QEMU release!') def read_trace_records(event_mapping, event_id_to_name, fobj): """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6). From patchwork Tue Feb 21 09:01:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147510 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6773EC6379F for ; Tue, 21 Feb 2023 09:04:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWf-0007m8-O3; Tue, 21 Feb 2023 04:01:29 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWe-0007kz-3s for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:28 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWc-0005Xl-EQ for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:27 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970085; bh=x91kESM8BSQWnznHZQrSejKxgQ5+SmVdkf/WYsOczh8=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=HTDO4uQLHZ0zUimR1ZMp3y1QQpWEethMJ/OADSRVkrwZpG2x33t3kEB2989P/zUQH 15nILllmJIUQYYgkjQVHCWE2VUTZEha0+QUo1udGxjayPhMexb7Fo+1h6oWFJU8wKP vvKzyxRBvDSSW4ZlZcz8jogNh8fV6rwFUmy34AQXgUoNWUffiKs73DmCOh2qJyXPeu w57kJFFT70j/PQVA7rxXPSsZxdmS9eoIKvadSRjZhYYt2+QdxdYfRs0MxZD3JzW/KB xDsgiOfccobpSbKnUqmYgWKVe5bZreNF/m5V31EuVNuxF7vNd6PS8rkaDRjP4nOc7A Qblc83uQHZiuQ== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id E04849620E5; Tue, 21 Feb 2023 09:01:23 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 8/9] simpletrace: define exception and add handling Date: Tue, 21 Feb 2023 10:01:03 +0100 Message-Id: <20230221090104.86103-9-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: zJRubo34omgtV4CQwHKlwOFt9QzQJA8w X-Proofpoint-GUID: zJRubo34omgtV4CQwHKlwOFt9QzQJA8w X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=696 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal Define `SimpleException` to differentiate our exceptions from generic exceptions (IOError, etc.). Adapted simpletrace to support this and output to stderr. Signed-off-by: Mads Ynddal Reviewed-by: Philippe Mathieu-Daudé --- scripts/simpletrace.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 61af68618f..35d2a757c4 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -25,12 +25,15 @@ log_header_fmt = '=QQQ' # trace/simple.c::TraceLogHeader rec_header_fmt = '=QQII' # trace/simple.c::TraceRecord +class SimpleException(Exception): + pass + def read_header(fobj, hfmt): '''Read a trace record header''' hlen = struct.calcsize(hfmt) hdr = fobj.read(hlen) if len(hdr) != hlen: - raise ValueError('Error reading header. Wrong filetype provided?') + raise SimpleException('Error reading header. Wrong filetype provided?') return struct.unpack(hfmt, hdr) def get_record(event_mapping, event_id_to_name, rechdr, fobj): @@ -42,10 +45,10 @@ def get_record(event_mapping, event_id_to_name, rechdr, fobj): try: event = event_mapping[name] except KeyError as e: - sys.stderr.write(f'{e} event is logged but is not declared ' \ - 'in the trace events file, try using ' \ - 'trace-events-all instead.\n') - sys.exit(1) + raise SimpleException( + f'{e} event is logged but is not declared in the trace events' + 'file, try using trace-events-all instead.' + ) rec = (name, timestamp_ns, pid) for type, name in event.args: @@ -201,8 +204,7 @@ def run(analyzer): *no_header, trace_event_path, trace_file_path = sys.argv[1:] assert no_header == [] or no_header == ['--no-header'], 'Invalid no-header argument' except (AssertionError, ValueError): - sys.stderr.write(f'usage: {sys.argv[0]} [--no-header] \n') - sys.exit(1) + raise SimpleException(f'usage: {sys.argv[0]} [--no-header] \n') with open(trace_event_path, 'r') as events_fobj, open(trace_file_path, 'rb') as log_fobj: events = read_events(events_fobj, trace_event_path) @@ -225,4 +227,9 @@ def catchall(self, *rec_args, event, timestamp_ns, pid, event_id): ] print(f'{event.name} {delta_ns / 1000:0.3f} {pid=} ' + ' '.join(fields)) - run(Formatter) + try: + run(Formatter) + except SimpleException as e: + sys.stderr.write(e + "\n") + sys.exit(1) + From patchwork Tue Feb 21 09:01:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mads Ynddal X-Patchwork-Id: 13147504 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7989AC61DA3 for ; Tue, 21 Feb 2023 09:02:49 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1pUOWi-0007r9-3k; Tue, 21 Feb 2023 04:01:32 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWf-0007mN-W0 for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:30 -0500 Received: from mr85p00im-ztdg06011201.me.com ([17.58.23.181]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1pUOWd-0005Y6-UL for qemu-devel@nongnu.org; Tue, 21 Feb 2023 04:01:29 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ynddal.dk; s=sig1; t=1676970087; bh=OLFAeG3fivFW5vWdAB9lVX4ycP8IQRSmjytnCKj6xhE=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=LY/XIO8wXACGZ2TaipOY/t0M+fquattBfWc8wv4XRSytBrSmIyVQu5wMiXPvzQcGj l49IPJVjwLzmTRWIVQInM2Xp4VfVmXZTcBg3LrvhqUw16NoZ9g+vrafIj9qXOvjllk gvzlnDl0kUIPhlCHPivnjvwRkrZfONmUDP+Xelw5S4LAP9RQpK65w+Sj7IbjHUF0uG rEuW0G/b8tOALdJBptc/lI2Lefrxwdeiz/QK8f21RfrRxqOPGiaOlbtx7FZRnHP5U2 t8GNJyKQzgGpEL8yBhjn1Iv91x0x0FM/5eO6y8psTe3iL5HLz0CAAMWSFBWTW5oKCs /s2PmZVw3U9gg== Received: from localhost.localdomain (mr38p00im-dlb-asmtp-mailmevip.me.com [17.57.152.18]) by mr85p00im-ztdg06011201.me.com (Postfix) with ESMTPSA id B183B962FAB; Tue, 21 Feb 2023 09:01:25 +0000 (UTC) From: Mads Ynddal To: qemu-devel@nongnu.org Cc: John Snow , Stefan Hajnoczi , Cleber Rosa , Mads Ynddal Subject: [PATCH 9/9] simpletrace: Refactor to separate responsibilities Date: Tue, 21 Feb 2023 10:01:04 +0100 Message-Id: <20230221090104.86103-10-mads@ynddal.dk> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20230221090104.86103-1-mads@ynddal.dk> References: <20230221090104.86103-1-mads@ynddal.dk> MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: poc2_AyTv1_52Cqnd9C-C_IGex4TFzoO X-Proofpoint-GUID: poc2_AyTv1_52Cqnd9C-C_IGex4TFzoO X-Proofpoint-Virus-Version: =?utf-8?q?vendor=3Dfsecure_engine=3D1=2E1=2E170-?= =?utf-8?q?22c6f66c430a71ce266a39bfe25bc2903e8d5c8f=3A6=2E0=2E425=2C18=2E0?= =?utf-8?q?=2E816=2C17=2E0=2E605=2E474=2E0000000_definitions=3D2022-01-18=5F?= =?utf-8?q?01=3A2022-01-14=5F01=2C2022-01-18=5F01=2C2020-01-23=5F02_signatur?= =?utf-8?q?es=3D0?= X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 mlxlogscore=973 phishscore=0 adultscore=0 spamscore=0 clxscore=1030 bulkscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2209130000 definitions=main-2302210078 Received-SPF: pass client-ip=17.58.23.181; envelope-from=mads@ynddal.dk; helo=mr85p00im-ztdg06011201.me.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Mads Ynddal Moved event_mapping and event_id_to_name down one level in the function call-stack to keep variable instantiation and usage closer (`process` and `run` has no use of the variables; `read_trace_records` does). Instead of passing event_mapping and event_id_to_name to the bottom of the call-stack, we move their use to `read_trace_records`. This separates responsibility and ownership of the information. `read_record` now just reads the arguments from the file-object by knowning the total number of bytes. Parsing it to specific arguments is moved up to `read_trace_records`. Special handling of dropped events removed, as they can be handled by the general code. Signed-off-by: Mads Ynddal --- scripts/simpletrace.py | 121 +++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 66 deletions(-) diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py index 35d2a757c4..465fcac609 100755 --- a/scripts/simpletrace.py +++ b/scripts/simpletrace.py @@ -24,6 +24,7 @@ log_header_fmt = '=QQQ' # trace/simple.c::TraceLogHeader rec_header_fmt = '=QQII' # trace/simple.c::TraceRecord +rec_header_fmt_len = struct.calcsize(rec_header_fmt) class SimpleException(Exception): pass @@ -36,35 +37,6 @@ def read_header(fobj, hfmt): raise SimpleException('Error reading header. Wrong filetype provided?') return struct.unpack(hfmt, hdr) -def get_record(event_mapping, event_id_to_name, rechdr, fobj): - """Deserialize a trace record from a file into a tuple - (name, timestamp, pid, arg1, ..., arg6).""" - event_id, timestamp_ns, length, pid = rechdr - if event_id != dropped_event_id: - name = event_id_to_name[event_id] - try: - event = event_mapping[name] - except KeyError as e: - raise SimpleException( - f'{e} event is logged but is not declared in the trace events' - 'file, try using trace-events-all instead.' - ) - - rec = (name, timestamp_ns, pid) - for type, name in event.args: - if is_string(type): - l = fobj.read(4) - (len,) = struct.unpack('=L', l) - s = fobj.read(len) - rec = rec + (s,) - else: - (value,) = struct.unpack('=Q', fobj.read(8)) - rec = rec + (value,) - else: - (dropped_count,) = struct.unpack('=Q', fobj.read(8)) - rec = ("dropped", timestamp_ns, pid, dropped_count) - return rec - def get_mapping(fobj): (event_id, ) = struct.unpack('=Q', fobj.read(8)) (len, ) = struct.unpack('=L', fobj.read(4)) @@ -72,10 +44,11 @@ def get_mapping(fobj): return (event_id, name) -def read_record(event_mapping, event_id_to_name, fobj): - """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, arg1, ..., arg6).""" - rechdr = read_header(fobj, rec_header_fmt) - return get_record(event_mapping, event_id_to_name, rechdr, fobj) +def read_record(fobj): + """Deserialize a trace record from a file into a tuple (event_num, timestamp, pid, args).""" + event_id, timestamp_ns, record_length, record_pid = read_header(fobj, rec_header_fmt) + args_payload = fobj.read(record_length - rec_header_fmt_len) + return (event_id, timestamp_ns, record_pid, args_payload) def read_trace_header(fobj): """Read and verify trace file header""" @@ -90,30 +63,60 @@ def read_trace_header(fobj): if log_version != 4: raise ValueError(f'Log format {log_version} not supported with this QEMU release!') -def read_trace_records(event_mapping, event_id_to_name, fobj): - """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, pid, arg1, ..., arg6). - - Note that `event_id_to_name` is modified if the file contains mapping records. +def read_trace_records(events, fobj, read_header): + """Deserialize trace records from a file, yielding record tuples (event, event_num, timestamp, pid, arg1, ..., arg6). Args: event_mapping (str -> Event): events dict, indexed by name - event_id_to_name (int -> str): event names dict, indexed by event ID fobj (file): input file + read_header (bool): whether to headers were read from fobj """ - while True: - t = fobj.read(8) - if len(t) == 0: - break + frameinfo = inspect.getframeinfo(inspect.currentframe()) + dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)", + frameinfo.lineno + 1, frameinfo.filename) + + event_mapping = {e.name: e for e in events} + event_mapping["dropped"] = dropped_event + event_id_to_name = {dropped_event_id: "dropped"} + + # If there is no header assume event ID mapping matches events list + if not read_header: + for event_id, event in enumerate(events): + event_id_to_name[event_id] = event.name + while t := fobj.read(8): (rectype, ) = struct.unpack('=Q', t) if rectype == record_type_mapping: - event_id, name = get_mapping(fobj) - event_id_to_name[event_id] = name + event_id, event_name = get_mapping(fobj) + event_id_to_name[event_id] = event_name else: - rec = read_record(event_mapping, event_id_to_name, fobj) - - yield rec + event_id, timestamp_ns, pid, args_payload = read_record(fobj) + event_name = event_id_to_name[event_id] + + try: + event = event_mapping[event_name] + except KeyError as e: + raise SimpleException( + f'{e} event is logged but is not declared in the trace events' + 'file, try using trace-events-all instead.' + ) + + offset = 0 + args = [] + for type, _ in event.args: + if is_string(type): + (len,) = struct.unpack_from('=L', args_payload, offset=offset) + offset += 4 + s = args_payload[offset:offset+len] + offset += len + args.append(s) + else: + (value,) = struct.unpack_from('=Q', args_payload, offset=offset) + offset += 8 + args.append(value) + + yield (event_mapping[event_name], event_name, timestamp_ns, pid) + tuple(args) class Analyzer: """A trace file analyzer which processes trace records. @@ -167,28 +170,15 @@ def __exit__(self, _type, value, traceback): """Called at the end of the trace.""" pass -def process(events, log, analyzer_class, read_header=True): +def process(events_fobj, trace_event_path, log_fobj, analyzer_class, read_header=True): """Invoke an analyzer on each event in a log.""" if read_header: - read_trace_header(log) - - frameinfo = inspect.getframeinfo(inspect.currentframe()) - dropped_event = Event.build("Dropped_Event(uint64_t num_events_dropped)", - frameinfo.lineno + 1, frameinfo.filename) - event_mapping = {"dropped": dropped_event} - event_id_to_name = {dropped_event_id: "dropped"} + read_trace_header(log_fobj) - for event in events: - event_mapping[event.name] = event - - # If there is no header assume event ID mapping matches events list - if not read_header: - for event_id, event in enumerate(events): - event_id_to_name[event_id] = event.name + events = read_events(events_fobj, trace_event_path) with analyzer_class() as analyzer: - for event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(event_mapping, event_id_to_name, log): - event = event_mapping[event_id] + for event, event_id, timestamp_ns, record_pid, *rec_args in read_trace_records(events, log_fobj, read_header): fn = getattr(analyzer, event.name, analyzer.catchall) fn(*rec_args, event=event, event_id=event_id, timestamp_ns=timestamp_ns, pid=record_pid) @@ -207,8 +197,7 @@ def run(analyzer): raise SimpleException(f'usage: {sys.argv[0]} [--no-header] \n') with open(trace_event_path, 'r') as events_fobj, open(trace_file_path, 'rb') as log_fobj: - events = read_events(events_fobj, trace_event_path) - process(events, log_fobj, analyzer, read_header=not no_header) + process(events_fobj, trace_event_path, log_fobj, analyzer, read_header=not no_header) if __name__ == '__main__': class Formatter(Analyzer):