Trace: anchor events to kernel boot, mark first GET /
- Trace reads /proc/stat btime and /proc/uptime at import so every event in /api/diag/timing can be expressed as 'seconds since power-on' (uptime_at_anchor + ev.t). - Web.StaticFileHandler.prepare emits 'web.first_root_get' the first time chromium hits / or /index.html, so we can see when the kiosk browser actually started loading the UI on cold boot.
This commit is contained in:
@@ -37,6 +37,38 @@ _events = [] # list of dicts: {t, name, fields}
|
|||||||
_ui_timing = None # last timeline POSTed by the browser
|
_ui_timing = None # last timeline POSTed by the browser
|
||||||
|
|
||||||
|
|
||||||
|
def _read_kernel_anchors():
|
||||||
|
"""Return (btime_wall, uptime_at_anchor) so we can express bbctrl events
|
||||||
|
in seconds since kernel boot.
|
||||||
|
|
||||||
|
btime_wall: wall-clock epoch seconds when the kernel booted (from
|
||||||
|
/proc/stat 'btime').
|
||||||
|
uptime_at_anchor: monotonic offset (seconds since kernel boot) at the
|
||||||
|
moment Trace was imported. Equivalent to (Trace anchor) - btime
|
||||||
|
in wall time, but read directly from /proc/uptime so it isn't
|
||||||
|
sensitive to wall-clock skew.
|
||||||
|
"""
|
||||||
|
btime = None
|
||||||
|
uptime_at_anchor = None
|
||||||
|
try:
|
||||||
|
with open('/proc/stat') as f:
|
||||||
|
for line in f:
|
||||||
|
if line.startswith('btime '):
|
||||||
|
btime = int(line.split()[1])
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
with open('/proc/uptime') as f:
|
||||||
|
uptime_at_anchor = float(f.read().split()[0])
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return btime, uptime_at_anchor
|
||||||
|
|
||||||
|
|
||||||
|
_btime_wall, _uptime_at_anchor = _read_kernel_anchors()
|
||||||
|
|
||||||
|
|
||||||
def now():
|
def now():
|
||||||
return time.monotonic() - _t0_monotonic
|
return time.monotonic() - _t0_monotonic
|
||||||
|
|
||||||
@@ -91,6 +123,14 @@ def set_ui_timing(data):
|
|||||||
_ui_timing = data
|
_ui_timing = data
|
||||||
|
|
||||||
|
|
||||||
|
def _current_uptime():
|
||||||
|
try:
|
||||||
|
with open('/proc/uptime') as f:
|
||||||
|
return float(f.read().split()[0])
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def timeline():
|
def timeline():
|
||||||
with _lock:
|
with _lock:
|
||||||
events = list(_events)
|
events = list(_events)
|
||||||
@@ -102,6 +142,11 @@ def timeline():
|
|||||||
'pid': os.getpid(),
|
'pid': os.getpid(),
|
||||||
'events': events,
|
'events': events,
|
||||||
'ui': _ui_timing,
|
'ui': _ui_timing,
|
||||||
|
# Kernel-boot anchors so the timeline can be expressed in
|
||||||
|
# "seconds since power on".
|
||||||
|
'btime_wall': _btime_wall,
|
||||||
|
'uptime_at_anchor': _uptime_at_anchor,
|
||||||
|
'uptime_now': _current_uptime(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -999,6 +999,23 @@ class StaticFileHandler(tornado.web.StaticFileHandler):
|
|||||||
self.set_header('Cache-Control',
|
self.set_header('Cache-Control',
|
||||||
'no-store, no-cache, must-revalidate, max-age=0')
|
'no-store, no-cache, must-revalidate, max-age=0')
|
||||||
|
|
||||||
|
def prepare(self):
|
||||||
|
# Mark the first request for the index page so we can see when
|
||||||
|
# chromium actually started fetching the UI on cold boot.
|
||||||
|
try:
|
||||||
|
app = self.application
|
||||||
|
if not getattr(app, '_first_root_get', False):
|
||||||
|
# Treat any GET '/' or '/index.html' as the root fetch.
|
||||||
|
p = self.request.path
|
||||||
|
if p in ('/', '/index.html', ''):
|
||||||
|
app._first_root_get = True
|
||||||
|
import bbctrl.Trace as _T
|
||||||
|
_T.mark('web.first_root_get',
|
||||||
|
ip=self.request.remote_ip,
|
||||||
|
ua=(self.request.headers.get('User-Agent') or '')[:60])
|
||||||
|
except Exception: pass
|
||||||
|
return super().prepare()
|
||||||
|
|
||||||
class Web(tornado.web.Application):
|
class Web(tornado.web.Application):
|
||||||
def __init__(self, args, ioloop):
|
def __init__(self, args, ioloop):
|
||||||
self.args = args
|
self.args = args
|
||||||
|
|||||||
Reference in New Issue
Block a user