contrib/catapipe.py
author Boris Feld <boris.feld@octobus.net>
Fri, 07 Sep 2018 11:17:34 -0400
changeset 39501 993d7e2c8b79
parent 39252 9a81f126f9fa
child 39513 e9706686451b
permissions -rwxr-xr-x
snapshot: make sure we'll never refine delta base from a reused source The point of reusing delta from the source is to avoid doing computation when applying a bundle. Refining such delta would go against that spirit. We do not have refining logic in place yet. This code needed to be moved out of the way before we could start adding such logic.

#!/usr/bin/env python3
#
# Copyright 2018 Google LLC.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""Tool read primitive events from a pipe to produce a catapult trace.

For now the event stream supports

  START $SESSIONID ...

and

  END $SESSIONID ...

events. Everything after the SESSIONID (which must not contain spaces)
is used as a label for the event. Events are timestamped as of when
they arrive in this process and are then used to produce catapult
traces that can be loaded in Chrome's about:tracing utility. It's
important that the event stream *into* this process stay simple,
because we have to emit it from the shell scripts produced by
run-tests.py.

Typically you'll want to place the path to the named pipe in the
HGCATAPULTSERVERPIPE environment variable, which both run-tests and hg
understand.
"""
from __future__ import absolute_import, print_function

import argparse
import datetime
import json
import os

_TYPEMAP = {
    'START': 'B',
    'END': 'E',
}

_threadmap = {}

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('pipe', type=str, nargs=1,
                        help='Path of named pipe to create and listen on.')
    parser.add_argument('output', default='trace.json', type=str, nargs='?',
                        help='Path of named pipe to create and listen on.')
    parser.add_argument('--debug', default=False, action='store_true',
                        help='Print useful debug messages')
    args = parser.parse_args()
    fn = args.pipe[0]
    os.mkfifo(fn)
    try:
        with open(fn) as f, open(args.output, 'w') as out:
            out.write('[\n')
            start = datetime.datetime.now()
            while True:
                ev = f.readline().strip()
                if not ev:
                    continue
                now = datetime.datetime.now()
                if args.debug:
                    print(ev)
                verb, session, label = ev.split(' ', 2)
                if session not in _threadmap:
                    _threadmap[session] = len(_threadmap)
                pid = _threadmap[session]
                ts_micros = (now - start).total_seconds() * 1000000
                out.write(json.dumps(
                    {
                        "name": label,
                        "cat": "misc",
                        "ph": _TYPEMAP[verb],
                        "ts": ts_micros,
                        "pid": pid,
                        "tid": 1,
                        "args": {}
                    }))
                out.write(',\n')
    finally:
        os.unlink(fn)

if __name__ == '__main__':
    main()