From nobody Tue Sep 16 07:15:03 2025 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40473C4708D for ; Thu, 5 Jan 2023 03:04:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229960AbjAEDEs (ORCPT ); Wed, 4 Jan 2023 22:04:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55238 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229641AbjAEDEp (ORCPT ); Wed, 4 Jan 2023 22:04:45 -0500 Received: from mail-yw1-x1149.google.com (mail-yw1-x1149.google.com [IPv6:2607:f8b0:4864:20::1149]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9D2911178 for ; Wed, 4 Jan 2023 19:04:44 -0800 (PST) Received: by mail-yw1-x1149.google.com with SMTP id 00721157ae682-487b0bf1117so216594357b3.5 for ; Wed, 04 Jan 2023 19:04:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:mime-version:message-id:date:from:to:cc:subject :date:message-id:reply-to; bh=lfkNLp5G5wuHv2XWWcgX8O/KJXZf1fcYl8/hPFMILT0=; b=DwzvpEzrUCyVoe99pSECCLFmrkStqGsbEM+qZOvLcYPEbAM6sHAlnMtuj4IVTj4CG9 XymFGvFvyydvhs04qS/xBHcIVzVLJ6qfGb9tmbKq9qnVNUaonzTHEZv+0eixCiPIeIRt fHXrlHqtby4RIuQ8gp3knFd7VdOWixUUaKOWVVjHiOeVsiF+RR4/Jo+9ziTN8dJ4MuEj Jd5oi2nM6nW2muRVQ5BWFbXYKY9k5XBaWEj02OP2iwLtX2DzEPZtDypoUcTRyZ+Rh7r/ qq4IdoKLw9LvpcUke2XolHKpu/g4Mju0uI79l09ljFhK9Zmj+ZRhJWvwZiew2Tswixlk vYKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:mime-version:message-id:date:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=lfkNLp5G5wuHv2XWWcgX8O/KJXZf1fcYl8/hPFMILT0=; b=J/bFJGxcU12DnffVJWP6Ki0iL9A+R6V/Hsw7/Fu9CgyV2dJMFH/BcF9QfqSmwCFCnk GHAEfRnuvi9ZS+xHk4Vb5eqLrJ6jM2G7qmVGRWGjamYdaymGwjON6CWeYBZf0pnJw6s+ Zd8SH42n8Z+8j0y5A0+7MZguCMVxudQjL5/pGONApOu7ls6LpBdrVI2nKpNV1pF5Gghc Xd0DI8N28Ryg9sOhT1EFMRchS4++CVo3rjjBi2PLRifkTaf9J4RhqdWN4zWMm74mHdGu j7vPxUUqhxYfWHlpaM1EBsubN/aj0MO86x6RTpkIz6YEObdnYyl4J8v3LzPdG81MXyJq c/4g== X-Gm-Message-State: AFqh2koH3rMFgilE7kzvTGFJM5Bz09zX3sq4bxPGQXQEyI9oxmRHJ2Cs 8uxUoxllpAsmV4Mc6qdjAnkZ991yRVfL X-Google-Smtp-Source: AMrXdXuisK5mAqlwmvkpFdxhPjG8DpYhx5FFU3xnFObYy1LV8aptLQvUkfB/FW5qEwEAzG/vzfyNqMD0xDoA X-Received: from irogers.svl.corp.google.com ([2620:15c:2d4:203:1e55:c3f8:c203:8c48]) (user=irogers job=sendgmr) by 2002:a25:2fc5:0:b0:706:bafd:6f95 with SMTP id v188-20020a252fc5000000b00706bafd6f95mr4072901ybv.55.1672887883928; Wed, 04 Jan 2023 19:04:43 -0800 (PST) Date: Wed, 4 Jan 2023 19:04:34 -0800 Message-Id: <20230105030434.255603-1-irogers@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.39.0.314.g84b9a713c41-goog Subject: [PATCH v1] perf script flamegraph: Avoid d3-flame-graph package dependency From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org, 996839@bugs.debian.org, Andreas Gerstmayr , Martin Spier , Brendan Gregg Cc: Ian Rogers Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently flame graph generation requires a d3-flame-graph template to be installed. Unfortunately this is hard to come by for things like Debian [1]. If the template isn't installed warn and download it from jsdelivr CDN. If downloading fails generate a minimal flame graph again with the javascript coming from jsdelivr CDN. [1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=3D996839 Signed-off-by: Ian Rogers Acked-by or Reviewed-by for the change? It would be nice to resolve --- tools/perf/scripts/python/flamegraph.py | 63 ++++++++++++++++++------- 1 file changed, 45 insertions(+), 18 deletions(-) diff --git a/tools/perf/scripts/python/flamegraph.py b/tools/perf/scripts/p= ython/flamegraph.py index b6af1dd5f816..808b0e1c9be5 100755 --- a/tools/perf/scripts/python/flamegraph.py +++ b/tools/perf/scripts/python/flamegraph.py @@ -25,6 +25,27 @@ import io import argparse import json import subprocess +import urllib.request + +minimal_html =3D """ + + + +
+ + + +""" =20 # pylint: disable=3Dtoo-few-public-methods class Node: @@ -50,15 +71,18 @@ class FlameGraphCLI: self.args =3D args self.stack =3D Node("all", "root") =20 - if self.args.format =3D=3D "html" and \ - not os.path.isfile(self.args.template): - print("Flame Graph template {} does not exist. Please install " - "the js-d3-flame-graph (RPM) or libjs-d3-flame-graph (de= b) " - "package, specify an existing flame graph template " - "(--template PATH) or another output format " - "(--format FORMAT).".format(self.args.template), - file=3Dsys.stderr) - sys.exit(1) + if self.args.format =3D=3D "html": + if os.path.isfile(self.args.template): + self.template =3D f"file://{self.args.template}" + else: + print(f""" +Warning: Flame Graph template '{self.args.template}' +does not exist, a template will be downloaded via http. To avoid this +please install a package such as the js-d3-flame-graph or +libjs-d3-flame-graph, specify an existing flame graph template +(--template PATH) or another output format (--format FORMAT). +""", file=3Dsys.stderr) + self.template =3D "https://cdn.jsdelivr.net/npm/d3-flame-graph= @4.1.3/dist/templates/d3-flamegraph-base.html" =20 @staticmethod def get_libtype_from_dso(dso): @@ -129,15 +153,18 @@ class FlameGraphCLI: options_json =3D json.dumps(options) =20 try: - with io.open(self.args.template, encoding=3D"utf-8") as te= mplate: - output_str =3D ( - template.read() - .replace("/** @options_json **/", options_json) - .replace("/** @flamegraph_json **/", stacks_json) - ) - except IOError as err: - print("Error reading template file: {}".format(err), file= =3Dsys.stderr) - sys.exit(1) + with urllib.request.urlopen(self.template) as template: + output_str =3D '\n'.join([ + l.decode('utf-8') for l in template.readlines() + ]) + except Exception as err: + print(f"Error reading template {self.template}: {err}\n" + "a minimal flame graph will be generated", file=3Dsy= s.stderr) + output_str =3D minimal_html + + output_str =3D output_str.replace("/** @options_json **/", opt= ions_json) + output_str =3D output_str.replace("/** @flamegraph_json **/", = stacks_json) + output_fn =3D self.args.output or "flamegraph.html" else: output_str =3D stacks_json --=20 2.39.0.314.g84b9a713c41-goog