1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
8 ChromeUtils.defineESModuleGetters(lazy, {
9 TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs",
10 UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
11 sendStandalonePing: "resource://gre/modules/TelemetrySend.sys.mjs",
14 const PREF_BRANCH = "browser.ping-centre.";
16 const TELEMETRY_PREF = `${PREF_BRANCH}telemetry`;
17 const LOGGING_PREF = `${PREF_BRANCH}log`;
19 const FHR_UPLOAD_ENABLED_PREF = "datareporting.healthreport.uploadEnabled";
22 * Observe various notifications and send them to a telemetry endpoint.
24 * @param {Object} options
25 * @param {string} options.topic - a unique ID for users of PingCentre to distinguish
26 * their data on the server side.
28 export class PingCentre {
29 constructor(options) {
31 throw new Error("Must specify topic.");
34 this._topic = options.topic;
35 this._prefs = Services.prefs.getBranch("");
37 this._enabled = this._prefs.getBoolPref(TELEMETRY_PREF);
38 this._onTelemetryPrefChange = this._onTelemetryPrefChange.bind(this);
39 this._prefs.addObserver(TELEMETRY_PREF, this._onTelemetryPrefChange);
41 this._fhrEnabled = this._prefs.getBoolPref(FHR_UPLOAD_ENABLED_PREF);
42 this._onFhrPrefChange = this._onFhrPrefChange.bind(this);
43 this._prefs.addObserver(FHR_UPLOAD_ENABLED_PREF, this._onFhrPrefChange);
45 this.logging = this._prefs.getBoolPref(LOGGING_PREF);
46 this._onLoggingPrefChange = this._onLoggingPrefChange.bind(this);
47 this._prefs.addObserver(LOGGING_PREF, this._onLoggingPrefChange);
51 return this._enabled && this._fhrEnabled;
54 _onLoggingPrefChange(aSubject, aTopic, prefKey) {
55 this.logging = this._prefs.getBoolPref(prefKey);
58 _onTelemetryPrefChange(aSubject, aTopic, prefKey) {
59 this._enabled = this._prefs.getBoolPref(prefKey);
62 _onFhrPrefChange(aSubject, aTopic, prefKey) {
63 this._fhrEnabled = this._prefs.getBoolPref(prefKey);
66 _createExperimentsPayload() {
67 let activeExperiments = lazy.TelemetryEnvironment.getActiveExperiments();
69 for (let experimentID in activeExperiments) {
71 activeExperiments[experimentID] &&
72 activeExperiments[experimentID].branch
74 experiments[experimentID] = {
75 branch: activeExperiments[experimentID].branch,
82 _createStructuredIngestionPing(data) {
83 let experiments = this._createExperimentsPayload();
84 let locale = data.locale || Services.locale.appLocaleAsBCP47;
88 version: AppConstants.MOZ_APP_VERSION,
89 release_channel: lazy.UpdateUtils.getUpdateChannel(false),
96 // We route through this helper because it gets hooked in testing.
97 static _sendStandalonePing(endpoint, payload) {
98 return lazy.sendStandalonePing(endpoint, payload);
102 * Sends a ping to the Structured Ingestion telemetry pipeline.
104 * The payload would be compressed using gzip.
106 * @param {Object} data The payload to be sent.
107 * @param {String} endpoint The destination endpoint. Note that Structured Ingestion
108 * requires a different endpoint for each ping. It's up to the
109 * caller to provide that. See more details at
110 * https://github.com/mozilla/gcp-ingestion/blob/master/docs/edge.md#postput-request
111 * @param {String} namespace Optional. The structured ingestion namespace.
112 * Used for data collection.
114 sendStructuredIngestionPing(data, endpoint, namespace = undefined) {
116 return Promise.resolve();
119 const ping = this._createStructuredIngestionPing(data);
120 const payload = JSON.stringify(ping);
123 Services.console.logStringMessage(
124 `TELEMETRY PING (${this._topic}): ${payload}\n`
128 let gleanNamespace = "other";
130 case "activity-stream":
131 gleanNamespace = "activity_stream";
133 case "messaging-system":
134 gleanNamespace = "messaging_system";
136 case "contextual-services":
137 gleanNamespace = "contextual_services";
141 return PingCentre._sendStandalonePing(endpoint, payload).then(
143 Glean.pingCentre.sendSuccessesByNamespace[gleanNamespace].add(1);
146 Glean.pingCentre.sendFailures.add(1);
147 Glean.pingCentre.sendFailuresByNamespace[gleanNamespace].add(1);
149 `Structured Ingestion ping failure with error: ${event.type}`
157 this._prefs.removeObserver(TELEMETRY_PREF, this._onTelemetryPrefChange);
158 this._prefs.removeObserver(LOGGING_PREF, this._onLoggingPrefChange);
159 this._prefs.removeObserver(
160 FHR_UPLOAD_ENABLED_PREF,
161 this._onFhrPrefChange
169 export const PingCentreConstants = {
170 FHR_UPLOAD_ENABLED_PREF,