bug 1517909 - format build telemetry time correctly when seconds has no fractional component. r=nalexander
authorTed Mielczarek <ted@mielczarek.org>
Tue, 08 Jan 2019 21:29:26 +0000
changeset 513303 3a11ad73f5b8
parent 513302 639924062722
child 513304 9c8923903d73
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1517909
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1517909 - format build telemetry time correctly when seconds has no fractional component. r=nalexander It turns out that Python's `datetime.isoformat` method will leave off the fractional component of seconds if it would be all zeroes, but the voluptuous `Datetime` validator wants it to be present, so it's possible to hit an error if you run mach at exactly an integer second. This patch switches from `isoformat` to `strftime` with an explicit format string instead. Differential Revision: https://phabricator.services.mozilla.com/D15981
python/mach/mach/test/test_telemetry.py
python/mach/mach/test/zero_microseconds.py
python/mozbuild/mozbuild/telemetry.py
--- a/python/mach/mach/test/test_telemetry.py
+++ b/python/mach/mach/test/test_telemetry.py
@@ -149,10 +149,17 @@ def test_registrar_dispatch(run_mach):
     # from within the same interpreter as the `mach python` command.
     data = run_mach('python', '--exec-file',
                     os.path.join(os.path.dirname(__file__), 'registrar_dispatch.py'))
     assert len(data) == 1
     d = data[0]
     assert d['command'] == 'python'
 
 
+def test_zero_microseconds(run_mach):
+    data = run_mach('python', '--exec-file',
+                    os.path.join(os.path.dirname(__file__), 'zero_microseconds.py'))
+    d = data[0]
+    assert d['command'] == 'python'
+
+
 if __name__ == '__main__':
     mozunit.main()
new file mode 100644
--- /dev/null
+++ b/python/mach/mach/test/zero_microseconds.py
@@ -0,0 +1,14 @@
+# This code is loaded via `mach python --exec-file`, so it runs in the scope of
+# the `mach python` command.
+old = self._mach_context.post_dispatch_handler  # noqa: F821
+
+
+def handler(context, handler, instance, result,
+            start_time, end_time, depth, args):
+    global old
+    # Round off sub-second precision.
+    old(context, handler, instance, result,
+        int(start_time), end_time, depth, args)
+
+
+self._mach_context.post_dispatch_handler = handler  # noqa: F821
--- a/python/mozbuild/mozbuild/telemetry.py
+++ b/python/mozbuild/mozbuild/telemetry.py
@@ -253,18 +253,18 @@ def gather_telemetry(command='', success
     `paths` is a dict whose keys are pathnames and values are sigils that should be used to
     replace those pathnames.
 
     Any absolute paths on the command line will be made relative to `paths` or replaced
     with a placeholder to avoid including paths from developer's machines.
     '''
     data = {
         'client_id': get_client_id(mach_context.state_dir),
-        # Simplest way to get an rfc3339 datetime string, AFAICT.
-        'time': datetime.utcfromtimestamp(start_time).isoformat(b'T') + 'Z',
+        # Get an rfc3339 datetime string.
+        'time': datetime.utcfromtimestamp(start_time).strftime('%Y-%m-%dT%H:%M:%S.%fZ'),
         'command': command,
         'argv': filter_args(command, sys.argv, paths),
         'success': success,
         # TODO: use a monotonic clock: https://bugzilla.mozilla.org/show_bug.cgi?id=1481624
         'duration_ms': int((end_time - start_time) * 1000),
         'build_opts': get_build_opts(substs),
         'system': get_system_info(),
         # TODO: exception: https://bugzilla.mozilla.org/show_bug.cgi?id=1481617