lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAP-5=fUeOw1RKHoYL3eXbq=H-bTTNviRO2t_-11DN9KP1uEZFQ@mail.gmail.com>
Date:   Tue, 15 Aug 2023 01:48:11 -0700
From:   Ian Rogers <irogers@...gle.com>
To:     Anup Sharma <anupnewsmail@...il.com>
Cc:     Peter Zijlstra <peterz@...radead.org>,
        Ingo Molnar <mingo@...hat.com>,
        Arnaldo Carvalho de Melo <acme@...nel.org>,
        Mark Rutland <mark.rutland@....com>,
        Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
        Jiri Olsa <jolsa@...nel.org>,
        Namhyung Kim <namhyung@...nel.org>,
        Adrian Hunter <adrian.hunter@...el.com>,
        linux-perf-users@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [RESEND PATCH] perf scripts python: launch the profiler UI on the
 default browser with the appropriate URL

On Wed, Aug 9, 2023 at 6:21 AM Anup Sharma <anupnewsmail@...il.com> wrote:
>
> All required libraries have been imported and make sure that
> none of them are external dependencies. To achieve this, created
> a virt env and verified.
>
> Modified usage information and added combined command.
>
> Modified the main() function to read the --save-only command-line
> option and set the output_file variable accordingly.
>
> Modified the trace_end() function to check for the output_file variable.
> If it is set, the profiler data is saved to a local file in Gecko
> Profile format, or the profiler.firefox.com is opened on the default browser.
>
> Included trace_begin() to initialize the Firefox Profiler and launch
> the default browser to display the profiler.firefox.com.
>
> Added a new function launchFirefox() to start a local server and launch the
> profiler UI on the default browser with the appropriate URL.
>
> Created the "CORSRequestHandler" class to enable Cross-Origin Resource Sharing.
>
> Summary:
> This integration now includes a exiting feature to conveniently host the
> Gecko Profile data on a local server and open it directly in the default
> web browser. This means that users can now effortlessly visualize and
> analyze the profiler results with just a single click. The addition of the
> --save-only command-line option allows users to save the profiler output
> to a local file in Gecko Profile format, but the real highlight lies
> in the capability to seamlessly launch a local server, making the data
> accessible to Firefox Profiler via a web browser. In addition, it's
> important to highlight that all data are hosted locally, eliminating
> any concerns about data privacy rules and regulations.
>
> Signed-off-by: Anup Sharma <anupnewsmail@...il.com>

Hi Anup,

I'm not able to replicate the behavior of a running server. What I get is:
```
$ sudo bash -c "export PERF_EXEC_PATH=`pwd`/tools/perf/ && perf script
gecko -F 99 -a sleep 1"
Staring Firefox Profiler on your default browser...
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
[ perf gecko: Captured and wrote into gecko_profile.json ]
$
```
ie the process immediately terminates. The same is true for
record/report. Could you take a look?

Thanks,
Ian

> ---
>  tools/perf/scripts/python/gecko.py | 70 +++++++++++++++++++++++++++---
>  1 file changed, 63 insertions(+), 7 deletions(-)
>
> diff --git a/tools/perf/scripts/python/gecko.py b/tools/perf/scripts/python/gecko.py
> index 278c3aed282a..bc5a72f94bfa 100644
> --- a/tools/perf/scripts/python/gecko.py
> +++ b/tools/perf/scripts/python/gecko.py
> @@ -1,4 +1,4 @@
> -# firefox-gecko-converter.py - Convert perf record output to Firefox's gecko profile format
> +# gecko.py - Convert perf record output to Firefox's gecko profile format
>  # SPDX-License-Identifier: GPL-2.0
>  #
>  # The script converts perf.data to Gecko Profile Format,
> @@ -7,14 +7,26 @@
>  # Usage:
>  #
>  #     perf record -a -g -F 99 sleep 60
> -#     perf script report gecko > output.json
> +#     perf script report gecko
> +#
> +# Combined:
> +#
> +#     perf script gecko -F 99 -a sleep 60
>
>  import os
>  import sys
> +import time
>  import json
> +import string
> +import random
>  import argparse
> +import threading
> +import webbrowser
> +import urllib.parse
> +from os import system
>  from functools import reduce
>  from dataclasses import dataclass, field
> +from http.server import HTTPServer, SimpleHTTPRequestHandler, test
>  from typing import List, Dict, Optional, NamedTuple, Set, Tuple, Any
>
>  # Add the Perf-Trace-Util library to the Python path
> @@ -40,9 +52,15 @@ CATEGORIES = None
>  # The product name is used by the profiler UI to show the Operating system and Processor.
>  PRODUCT = os.popen('uname -op').read().strip()
>
> +# store the output file
> +output_file = None
> +
>  # Here key = tid, value = Thread
>  tid_to_thread = dict()
>
> +# The HTTP server is used to serve the profile to the profiler UI.
> +http_server_thread = None
> +
>  # The category index is used by the profiler UI to show the color of the flame graph.
>  USER_CATEGORY_INDEX = 0
>  KERNEL_CATEGORY_INDEX = 1
> @@ -278,9 +296,19 @@ def process_event(param_dict: Dict) -> None:
>                 tid_to_thread[tid] = thread
>         thread._add_sample(comm=comm, stack=stack, time_ms=time_stamp)
>
> +def trace_begin() -> None:
> +       global output_file
> +       if (output_file is None):
> +               print("Staring Firefox Profiler on your default browser...")
> +               global http_server_thread
> +               http_server_thread = threading.Thread(target=test, args=(CORSRequestHandler, HTTPServer,))
> +               http_server_thread.daemon = True
> +               http_server_thread.start()
> +
>  # Trace_end runs at the end and will be used to aggregate
>  # the data into the final json object and print it out to stdout.
>  def trace_end() -> None:
> +       global output_file
>         threads = [thread._to_json_dict() for thread in tid_to_thread.values()]
>
>         # Schema: https://github.com/firefox-devtools/profiler/blob/53970305b51b9b472e26d7457fee1d66cd4e2737/src/types/gecko-profile.js#L305
> @@ -305,22 +333,50 @@ def trace_end() -> None:
>                 "processes": [],
>                 "pausedRanges": [],
>         }
> -       json.dump(gecko_profile_with_meta, sys.stdout, indent=2)
> +       # launch the profiler on local host if not specified --save-only args, otherwise print to file
> +       if (output_file is None):
> +               output_file = 'gecko_profile.json'
> +               with open(output_file, 'w') as f:
> +                       json.dump(gecko_profile_with_meta, f, indent=2)
> +               launchFirefox(output_file)
> +               time.sleep(1)
> +               print(f'[ perf gecko: Captured and wrote into {output_file} ]')
> +       else:
> +               print(f'[ perf gecko: Captured and wrote into {output_file} ]')
> +               with open(output_file, 'w') as f:
> +                       json.dump(gecko_profile_with_meta, f, indent=2)
> +
> +# Used to enable Cross-Origin Resource Sharing (CORS) for requests coming from 'https://profiler.firefox.com', allowing it to access resources from this server.
> +class CORSRequestHandler(SimpleHTTPRequestHandler):
> +       def end_headers (self):
> +               self.send_header('Access-Control-Allow-Origin', 'https://profiler.firefox.com')
> +               SimpleHTTPRequestHandler.end_headers(self)
> +
> +# start a local server to serve the gecko_profile.json file to the profiler.firefox.com
> +def launchFirefox(file):
> +       safe_string = urllib.parse.quote_plus(f'http://localhost:8000/{file}')
> +       url = 'https://profiler.firefox.com/from-url/' + safe_string
> +       webbrowser.open(f'{url}')
>
>  def main() -> None:
> +       global output_file
>         global CATEGORIES
> -       parser = argparse.ArgumentParser(description="Convert perf.data to Firefox\'s Gecko Profile format")
> +       parser = argparse.ArgumentParser(description="Convert perf.data to Firefox\'s Gecko Profile format which can be uploaded to profiler.firefox.com for visualization")
>
>         # Add the command-line options
>         # Colors must be defined according to this:
>         # https://github.com/firefox-devtools/profiler/blob/50124adbfa488adba6e2674a8f2618cf34b59cd2/res/css/categories.css
> -       parser.add_argument('--user-color', default='yellow', help='Color for the User category')
> -       parser.add_argument('--kernel-color', default='orange', help='Color for the Kernel category')
> +       parser.add_argument('--user-color', default='yellow', help='Color for the User category', choices=['yellow', 'blue', 'purple', 'green', 'orange', 'red', 'grey', 'magenta'])
> +       parser.add_argument('--kernel-color', default='orange', help='Color for the Kernel category', choices=['yellow', 'blue', 'purple', 'green', 'orange', 'red', 'grey', 'magenta'])
> +       # If --save-only is specified, the output will be saved to a file instead of opening Firefox's profiler directly.
> +       parser.add_argument('--save-only', help='Save the output to a file instead of opening Firefox\'s profiler')
> +
>         # Parse the command-line arguments
>         args = parser.parse_args()
>         # Access the values provided by the user
>         user_color = args.user_color
>         kernel_color = args.kernel_color
> +       output_file = args.save_only
>
>         CATEGORIES = [
>                 {
> @@ -336,4 +392,4 @@ def main() -> None:
>         ]
>
>  if __name__ == '__main__':
> -    main()
> +       main()
> --
> 2.34.1
>

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ