2019-11-01 22:33:28 +03:00
|
|
|
# Copyright (c) Facebook, Inc. and its affiliates.
|
2019-03-26 03:09:11 +03:00
|
|
|
#
|
|
|
|
# This software may be used and distributed according to the terms of the
|
2019-11-01 22:33:28 +03:00
|
|
|
# GNU General Public License version 2.
|
|
|
|
|
|
|
|
# perftrace.py - Module for tracing performance
|
|
|
|
|
2019-11-08 01:19:52 +03:00
|
|
|
import inspect
|
2019-03-26 03:09:11 +03:00
|
|
|
from contextlib import contextmanager
|
|
|
|
|
2019-12-04 21:53:06 +03:00
|
|
|
# pyre-fixme[21]: Could not find `bindings`.
|
2019-11-05 02:49:48 +03:00
|
|
|
from bindings import tracing
|
|
|
|
|
2019-11-08 01:19:52 +03:00
|
|
|
from . import util
|
2019-05-03 23:06:13 +03:00
|
|
|
|
2019-03-26 03:09:11 +03:00
|
|
|
|
2019-11-05 02:49:48 +03:00
|
|
|
# Native tracing utilities
|
|
|
|
|
|
|
|
tracer = tracing.singleton
|
|
|
|
|
|
|
|
|
2019-11-08 01:19:52 +03:00
|
|
|
def editspan(
|
|
|
|
meta,
|
|
|
|
_edit=tracer.edit,
|
|
|
|
_currentframe=inspect.currentframe,
|
|
|
|
_wrapfunc=tracing.wrapfunc,
|
|
|
|
_spanid=tracing.wrapfunc.spanid,
|
|
|
|
):
|
2019-11-05 02:49:48 +03:00
|
|
|
"""Edit the current native span. meta: [(key, value)]"""
|
2019-11-08 01:19:52 +03:00
|
|
|
# Find the "spanid" from the callsite stack
|
|
|
|
spanid = None
|
|
|
|
frame = _currentframe().f_back
|
|
|
|
while frame is not None:
|
|
|
|
funcname = frame.f_code.co_name
|
|
|
|
func = frame.f_globals.get(funcname)
|
|
|
|
if getattr(func, "isperftrace", False) and isinstance(func, _wrapfunc):
|
|
|
|
# Got the function! Use wrapfunc.spanid to read the spanid.
|
|
|
|
frame = None
|
|
|
|
spanid = _spanid(func)
|
|
|
|
break
|
|
|
|
# Try the parent frame
|
|
|
|
frame = frame.f_back
|
|
|
|
if spanid is not None:
|
|
|
|
_edit(spanid, meta)
|
|
|
|
|
|
|
|
|
|
|
|
# PerfTrace wrappers
|
2019-03-26 03:09:11 +03:00
|
|
|
|
|
|
|
|
2019-03-26 03:09:11 +03:00
|
|
|
@contextmanager
|
|
|
|
def trace(name):
|
2019-11-08 01:19:52 +03:00
|
|
|
spanid = tracer.span([("name", name), ("cat", "perftrace")])
|
2019-11-05 02:49:48 +03:00
|
|
|
tracer.enter(spanid)
|
2019-03-26 03:09:11 +03:00
|
|
|
try:
|
|
|
|
yield
|
|
|
|
finally:
|
2019-11-05 02:49:48 +03:00
|
|
|
tracer.exit(spanid)
|
2019-03-26 03:09:11 +03:00
|
|
|
|
|
|
|
|
|
|
|
def traceflag(flagname):
|
|
|
|
"""Records the given flag name as being associated with the latest trace
|
|
|
|
point."""
|
2019-11-05 02:49:48 +03:00
|
|
|
# XXX: No multi-flag support for now.
|
|
|
|
editspan([("flag", flagname)])
|
|
|
|
|
2019-03-26 03:09:11 +03:00
|
|
|
|
|
|
|
def tracevalue(name, value):
|
|
|
|
"""Records the given name=value as being associated with the latest trace
|
|
|
|
point. This will overwrite any previous value with that name."""
|
2019-11-05 02:49:48 +03:00
|
|
|
editspan([(name, str(value))])
|
|
|
|
|
2019-03-26 03:09:11 +03:00
|
|
|
|
|
|
|
def tracebytes(name, value):
|
|
|
|
"""Records the given name=value as being associated with the latest trace
|
|
|
|
point. The value is treated as bytes and will be added to any previous value
|
|
|
|
set to the same name."""
|
2019-11-05 02:49:48 +03:00
|
|
|
# XXX: Rust tracing does not do an addition - But there do not seem to be
|
|
|
|
# any users relying on the behavior.
|
|
|
|
editspan([(name, str(value))])
|
|
|
|
|
2019-03-26 03:09:11 +03:00
|
|
|
|
|
|
|
def tracefunc(name):
|
|
|
|
"""Decorator that indicates this entire function should be wrapped in a
|
|
|
|
trace."""
|
|
|
|
|
|
|
|
def wrapper(func):
|
2019-11-08 01:19:52 +03:00
|
|
|
func.meta = [("name", name), ("cat", "perftrace")]
|
|
|
|
if util.istest():
|
|
|
|
func.meta.append(("line", "_"))
|
|
|
|
func.isperftrace = True
|
|
|
|
return tracing.wrapfunc(func)
|
2019-03-26 03:09:11 +03:00
|
|
|
|
|
|
|
return wrapper
|