blob: 4b70000c53e95c450d3862e6f57f64aecb9521b1 [file] [log] [blame]
#!/usr/bin/env python
import errno
import glob
import json
import os
import time
from timing import monotonic_time_nanos
# We need to optionally include some functions for Windows.
import platform
if platform.system() == 'Windows':
import ctypes
def create_symlink(original, symlink):
if os.path.lexists(symlink):
os.remove(symlink)
if platform.system() == 'Windows':
k32 = ctypes.windll.LoadLibrary("kernel32.dll")
k32.CreateSymbolicLinkA(symlink, original, 1)
else:
os.symlink(original, symlink)
class _TraceEventPhases(object):
BEGIN = 'B'
END = 'E'
IMMEDIATE = 'I'
COUNTER = 'C'
ASYNC_START = 'S'
ASYNC_FINISH = 'F'
OBJECT_SNAPSHOT = 'O'
OBJECT_NEW = 'N'
OBJECT_DELETE = 'D'
METADATA = 'M'
class Tracing(object):
_trace_events = [
{
'name': 'process_name',
'ph': _TraceEventPhases.METADATA,
'pid': os.getpid(),
'args': {'name': 'buck.py'}
}
]
def __init__(self, name, args={}):
self.name = name
self.args = args
self.pid = os.getpid()
def __enter__(self):
now_us = monotonic_time_nanos() / 1000
self._add_trace_event(
'buck-launcher',
self.name,
_TraceEventPhases.BEGIN,
self.pid,
1,
now_us,
self.args)
def __exit__(self, x_type, x_value, x_traceback):
now_us = monotonic_time_nanos() / 1000
self._add_trace_event(
'buck-launcher',
self.name,
_TraceEventPhases.END,
self.pid,
1,
now_us,
self.args)
@staticmethod
def _add_trace_event(
category,
name,
phase,
pid,
tid,
ts,
args):
Tracing._trace_events.append({
'cat': category,
'name': name,
'ph': phase,
'pid': pid,
'tid': tid,
'ts': ts,
'args': args})
@staticmethod
def write_to_dir(buck_log_dir, build_id):
filename_time = time.strftime('%Y-%m-%d.%H-%M-%S')
trace_filename = os.path.join(
buck_log_dir, 'launch.{0}.{1}.trace'.format(filename_time, build_id))
trace_filename_link = os.path.join(buck_log_dir, 'launch.trace')
try:
os.makedirs(buck_log_dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
with open(trace_filename, 'w') as f:
json.dump(Tracing._trace_events, f)
create_symlink(trace_filename, trace_filename_link)
Tracing.clean_up_old_logs(buck_log_dir)
@staticmethod
def clean_up_old_logs(buck_log_dir, logs_to_keep=25):
traces = filter(os.path.isfile, glob.glob(os.path.join(buck_log_dir, 'launch.*.trace')))
traces = sorted(traces, key=os.path.getmtime)
for f in traces[:-logs_to_keep]:
os.remove(f)