Bug 1427877 - Add support for C-C-specific telemetry probes. r=mkmelin
authorGeoff Lankow <geoff@darktrojan.net> and Ben Campbell <benc@thunderbird.net>
Sun, 22 Sep 2019 23:16:13 +0200
changeset 36905 e6dd9b872738cce894ea344bd859b092d1a01384
parent 36904 981dc700defb0a6146dbb74bdcc7e374f6961173
child 36906 f3f61fcc001af6ca42bfe1b3ca45f8f22a768ce7
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewersmkmelin
bugs1427877
Bug 1427877 - Add support for C-C-specific telemetry probes. r=mkmelin
mail/components/telemetry/Events.yaml
mail/components/telemetry/Histograms.json
mail/components/telemetry/README.md
mail/components/telemetry/Scalars.yaml
mail/components/test/unit/test_telemetry_buildconfig.js
mail/components/test/unit/xpcshell.ini
mail/moz.configure
new file mode 100644
--- /dev/null
+++ b/mail/components/telemetry/Events.yaml
@@ -0,0 +1,25 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file contains Thunderbird-specific telemetry Event definitions, which
+# are added on top of the Firefox ones (in /toolkit/components/telemetry).
+# To avoid name clashes, all the Thunderbird events will be under a "tb"
+# category.
+
+# A category used for unit tests.
+# Under normal operation, these won't be invoked.
+tb.test:
+  test:
+    objects: ["object1", "object2", "object3"]
+    bug_numbers: [1427877]
+    notification_emails:
+      - "telemetry-client-dev@thunderbird.net"
+    record_in_processes: ["main"]
+    description: This is a test entry for Telemetry.
+    expiry_version: never
+    extra_keys:
+      key1: This is just a test description.
+    products:
+      - thunderbird
+
new file mode 100644
--- /dev/null
+++ b/mail/components/telemetry/Histograms.json
@@ -0,0 +1,16 @@
+{
+  "TELEMETRY_TEST_TB_CATEGORICAL": {
+    "record_in_processes": ["main", "content"],
+    "products": ["thunderbird"],
+    "alert_emails": ["telemetry-client-dev@thunderbird.net"],
+    "bug_numbers": [1427877],
+    "expires_in_version": "never",
+    "kind": "categorical",
+    "labels": [
+      "CommonLabel",
+      "Label2",
+      "Label3"
+    ],
+    "description": "A testing histogram; not meant to be touched"
+  }
+}
new file mode 100644
--- /dev/null
+++ b/mail/components/telemetry/README.md
@@ -0,0 +1,125 @@
+# Notes on telemetry in Thunderbird
+
+## Hooking into the build process
+
+The comm-central probe definitions in this directory (`Events.yaml`,
+`Scalars.yaml` and `Histograms.json`) are used _in addition_ to
+their mozilla-central counterparts (in `toolkit/components/telemetry/`).
+
+As part of the mozilla-central telemetry build process, scripts are used to
+generate the C++ files which define the probe registry (enums, string tables
+etc).
+
+Because of this code generation, the extra comm-central probe definitions
+need to be included when the mozilla-central telemetry is built.
+
+This is done by setting `MOZ_TELEMETRY_EXTRA_*` config values. You can
+see these in `comm/mail/moz.configure`.
+These config values are used by `toolkit/components/telemetry/moz.build`
+(mozilla-central) to pass the extra probe definitions to the code
+generation scripts.
+
+The build scripts can be found under `toolkit/components/telemetry/build_scripts`.
+They are written in Python.
+
+## Naming probes
+
+To avoid clashing with the mozilla-central probes, we'll be pretty liberal
+about slapping on prefixes to our definitions.
+
+For Events and Scalars, we keep everything under `tb.`.
+
+For Histograms, we use a `TB_` or `TELEMETRY_TEST_TB_` prefix.
+
+(Why not just `TB_`? Because the telemetry test helper functions
+`getSnapshotForHistograms()`/`getSnapshotForKeyedHistograms()` have an option
+to filter out histograms with a `TELEMETRY_TEST_` prefix).
+
+
+## Enabling telemetry
+
+### Compile-time
+
+Telemetry is not compiled in by default. You need to add the following line
+to your mozconfig:
+
+    export MOZ_TELEMETRY_REPORTING=1
+
+The nightly and release configs have this setting already (`$ grep -r MOZ_TELEMETRY_ mail/config/mozconfigs`).
+
+
+### At run time
+
+There's a complex set of conditions to enable telemetry reporting.
+The runtime settings needed for a minimal test setup are:
+
+- `toolkit.telemetry.server` - URL where the collected data will be POSTed to
+   (`https://incoming.telemetry.mozilla.org`). So if you're running a local
+   server for testing, you'll likely want this to be some localhost URL.
+- `toolkit.telemetry.server.owner` - The owner of the server (`Mozilla`).
+   The implication is that it's polite to change this if you're running a
+   non-Mozilla server.
+- `toolkit.telemetry.send.overrideOfficialCheck` - usually, telemetry is only
+   send for official builds (ie `export MOZILLA_OFFICIAL=1` in `mozconfig`).
+   Setting this to `true` enables sending for unofficial builds.
+- `datareporting.policy.dataSubmissionEnabled` - allows submission to the
+   server.
+- `datareporting.policy.dataSubmissionPolicyBypassNotification` - bypasses the
+   checks to see if the policy has been shown and agreed to by the user. Set it
+   to `true` for testing.
+- `toolkit.telemetry.log.level` - very handy for watching telemetry activity in
+   the javascript console. `Trace`, `Debug`, `Info`, `Warn`, etc...
+
+example (values to paste into prefs.js):
+
+```
+user_pref("toolkit.telemetry.server", "http://localhost:8080/wibble");
+user_pref("toolkit.telemetry.server_owner", "Nobody");
+user_pref("datareporting.policy.dataSubmissionPolicyBypassNotification",true);
+user_pref("datareporting.policy.dataSubmissionEnabled", true);
+user_pref("toolkit.telemetry.log.level", "Trace");
+user_pref("toolkit.telemetry.send.overrideOfficialCheck", true);
+```
+
+## Troubleshooting
+
+### Running a test server
+
+To run a test server locally to dump out the sent data, try
+https://github.com/mozilla/gzipServer
+(or alternatively https://github.com/bcampbell/webhole).
+
+Make sure you set `toolkit.telemetry.server`/`toolkit.telemetry.server_owner`
+to point to your local server.
+
+### Log output
+
+If you've got logging on (eg `user_pref("toolkit.telemetry.log.level", "Trace");`),
+the output will show up on the javascript console:
+
+    Menu => "Tools" => "Developer Tools" => "Error Console"
+
+If data isn't showing up, keep an eye out for messages in the console.
+For example: "Telemetry is not allowed to send pings" is an indication that
+the official-build check is failing (overridden by
+`toolkit.telemetry.send.overrideOfficialCheck`).
+
+### Test pings
+
+From the javascript console, you can force an immediate test ping:
+
+```
+Cu.import("resource://gre/modules/TelemetrySession.jsm");
+TelemetrySession.testPing()
+```
+
+## Further documentation
+
+The Telemetry documentation index is at:
+
+https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/index.html
+
+There's a good summary of settings (both compile-time and run-time prefs):
+
+https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/internals/preferences.html
+
new file mode 100644
--- /dev/null
+++ b/mail/components/telemetry/Scalars.yaml
@@ -0,0 +1,52 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at http://mozilla.org/MPL/2.0/.
+
+# This file contains Thunderbird-specific telemetry Scalar definitions, which
+# are added on top of the Firefox ones (in /toolkit/components/telemetry).
+# To avoid name clashes, all the TB scalars will be under a "tb" section.
+# They are submitted with the "main" pings and can be inspected in about:telemetry.
+
+# The following section is for probes testing the Telemetry system.
+# Under normal operation, these won't be invoked.
+tb.test:
+  unsigned_int_kind:
+    bug_numbers:
+      - 1427877
+    description: >
+      This is a test uint type with a really long description, maybe spanning even multiple
+      lines, to just prove a point: everything works just fine.
+    expires: never
+    products:
+      - 'thunderbird'
+    kind: uint
+    notification_emails:
+      - "telemetry-client-dev@thunderbird.net"
+    record_in_processes:
+      - 'main'
+
+  string_kind:
+    bug_numbers:
+      - 1427877
+    description: A string test type with a one line comment that works just fine!
+    expires: never
+    products:
+      - 'thunderbird'
+    kind: string
+    notification_emails:
+      - "telemetry-client-dev@thunderbird.net"
+    record_in_processes:
+      - 'main'
+
+  boolean_kind:
+    bug_numbers:
+      - 1427877
+    description: A boolean test type with a one line comment that works just fine!
+    expires: never
+    products:
+      - 'thunderbird'
+    kind: boolean
+    notification_emails:
+      - "telemetry-client-dev@thunderbird.net"
+    record_in_processes:
+      - 'main'
new file mode 100644
--- /dev/null
+++ b/mail/components/test/unit/test_telemetry_buildconfig.js
@@ -0,0 +1,147 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test is a copy of parts of the following tests:
+//
+// * toolkit/components/telemetry/tests/unit/test_TelemetryEvents.js
+// * toolkit/components/telemetry/tests/unit/test_TelemetryHistograms.js
+// * toolkit/components/telemetry/tests/unit/test_TelemetryScalars.js
+//
+// The probe names have been changed to probes that only exist in a Thunderbird build.
+// If this test begins to fail, check for recent changes in toolkit/components/telemetry.
+
+ChromeUtils.defineModuleGetter(
+  this,
+  "TelemetryTestUtils",
+  "resource://testing-common/TelemetryTestUtils.jsm"
+);
+
+const Telemetry = Services.telemetry;
+
+const UINT_SCALAR = "tb.test.unsigned_int_kind";
+const STRING_SCALAR = "tb.test.string_kind";
+const BOOLEAN_SCALAR = "tb.test.boolean_kind";
+
+/**
+ * Check that stored events correspond to expectations.
+ *
+ * @param {Array} summaries - Summary of the expected events.
+ * @param {Boolean} clearScalars - Whether to clear out data after snapshotting.
+ */
+function checkEventSummary(summaries, clearScalars) {
+  let scalars = Telemetry.getSnapshotForKeyedScalars("main", clearScalars);
+
+  for (let [process, [category, eObject, method], count] of summaries) {
+    let uniqueEventName = `${category}#${eObject}#${method}`;
+    let summaryCount;
+    if (process === "dynamic") {
+      summaryCount =
+        scalars.dynamic["telemetry.dynamic_event_counts"][uniqueEventName];
+    } else {
+      summaryCount =
+        scalars[process]["telemetry.event_counts"][uniqueEventName];
+    }
+    Assert.equal(
+      summaryCount,
+      count,
+      `${uniqueEventName} had wrong summary count`
+    );
+  }
+}
+
+/**
+ * Test Thunderbird events are included in the build.
+ */
+add_task(async function test_recording_state() {
+  Telemetry.clearEvents();
+  Telemetry.clearScalars();
+
+  const events = [["tb.test", "test", "object1"]];
+
+  // Recording off by default.
+  events.forEach(e => Telemetry.recordEvent(...e));
+  TelemetryTestUtils.assertEvents([]);
+  // But still expect a non-zero summary count.
+  checkEventSummary(events.map(e => ["parent", e, 1]), true);
+
+  // Once again, with recording on.
+  Telemetry.setEventRecordingEnabled("tb.test", true);
+  events.forEach(e => Telemetry.recordEvent(...e));
+  TelemetryTestUtils.assertEvents(events);
+  checkEventSummary(events.map(e => ["parent", e, 1]), true);
+});
+
+/**
+ * Test Thunderbird histograms are included in the build.
+ */
+add_task(async function test_categorical_histogram() {
+  let h1 = Telemetry.getHistogramById("TELEMETRY_TEST_TB_CATEGORICAL");
+  for (let v of ["CommonLabel", "CommonLabel", "Label2", "Label3"]) {
+    h1.add(v);
+  }
+  for (let s of ["", "Label4", "1234"]) {
+    // The |add| method should not throw for unexpected values, but rather
+    // print an error message in the console.
+    h1.add(s);
+  }
+
+  let snapshot = h1.snapshot();
+  Assert.deepEqual(snapshot.values, { 0: 2, 1: 1, 2: 1, 3: 0 });
+  // sum is a little meaningless for categorical histograms, but hey.
+  // (CommonLabel is 0, Label2 is 1, Label3 is 2)
+  Assert.equal(snapshot.sum, 0 * 2 + 1 * 1 + 2 * 1);
+  Assert.deepEqual(snapshot.range, [1, 50]);
+});
+
+/**
+ * Test Thunderbird scalars are included in the build.
+ */
+add_task(async function test_serializationFormat() {
+  Telemetry.clearScalars();
+
+  // Set the scalars to a known value.
+  const expectedUint = 3785;
+  const expectedString = "some value";
+  Telemetry.scalarSet(UINT_SCALAR, expectedUint);
+  Telemetry.scalarSet(STRING_SCALAR, expectedString);
+  Telemetry.scalarSet(BOOLEAN_SCALAR, true);
+
+  // Get a snapshot of the scalars for the main process (internally called "default").
+  const scalars = TelemetryTestUtils.getProcessScalars("parent");
+
+  // Check that they are serialized to the correct format.
+  Assert.equal(
+    typeof scalars[UINT_SCALAR],
+    "number",
+    UINT_SCALAR + " must be serialized to the correct format."
+  );
+  Assert.ok(
+    Number.isInteger(scalars[UINT_SCALAR]),
+    UINT_SCALAR + " must be a finite integer."
+  );
+  Assert.equal(
+    scalars[UINT_SCALAR],
+    expectedUint,
+    UINT_SCALAR + " must have the correct value."
+  );
+  Assert.equal(
+    typeof scalars[STRING_SCALAR],
+    "string",
+    STRING_SCALAR + " must be serialized to the correct format."
+  );
+  Assert.equal(
+    scalars[STRING_SCALAR],
+    expectedString,
+    STRING_SCALAR + " must have the correct value."
+  );
+  Assert.equal(
+    typeof scalars[BOOLEAN_SCALAR],
+    "boolean",
+    BOOLEAN_SCALAR + " must be serialized to the correct format."
+  );
+  Assert.equal(
+    scalars[BOOLEAN_SCALAR],
+    true,
+    BOOLEAN_SCALAR + " must have the correct value."
+  );
+});
--- a/mail/components/test/unit/xpcshell.ini
+++ b/mail/components/test/unit/xpcshell.ini
@@ -2,8 +2,9 @@
 head = head_mailcomponents.js
 tail =
 support-files = data/*
 
 [test_about_support.js]
 [test_autoconfigFetchDisk.js]
 [test_autoconfigUtils.js]
 [test_autoconfigXML.js]
+[test_telemetry_buildconfig.js]
--- a/mail/moz.configure
+++ b/mail/moz.configure
@@ -76,14 +76,18 @@ imply_option('MOZ_BLOCK_PROFILE_DOWNGRAD
 
 with only_when(target_is_linux & compile_environment):
     option(env='MOZ_NO_PIE_COMPAT',
            help='Enable non-PIE wrapper')
 
     set_config('MOZ_NO_PIE_COMPAT',
                depends_if('MOZ_NO_PIE_COMPAT')(lambda _: True))
 
+set_config('MOZ_TELEMETRY_EXTRA_HISTOGRAM_FILES', ['/comm/mail/components/telemetry/Histograms.json'])
+set_config('MOZ_TELEMETRY_EXTRA_SCALAR_FILES', ['/comm/mail/components/telemetry/Scalars.yaml'])
+set_config('MOZ_TELEMETRY_EXTRA_EVENT_FILES', ['/comm/mail/components/telemetry/Events.yaml'])
+
 include('../build/moz.configure/gecko_source.configure')
 
 include('../mailnews/moz.configure')
 
 imply_option('--enable-app-system-headers', True)
 include('../../toolkit/moz.configure')