Bug 1427877 - Add support for C-C-specific telemetry probes. r=mkmelin
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')