diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs')
-rw-r--r-- | toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs b/toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs new file mode 100644 index 0000000000..dfee5d0ff6 --- /dev/null +++ b/toolkit/components/telemetry/dap/DAPVisitCounter.sys.mjs @@ -0,0 +1,160 @@ +/* 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/. */ + +import { DAPTelemetrySender } from "./DAPTelemetrySender.sys.mjs"; + +let lazy = {}; + +ChromeUtils.defineLazyGetter(lazy, "logConsole", function () { + return console.createInstance({ + prefix: "DAPVisitCounter", + maxLogLevelPref: "toolkit.telemetry.dap.logLevel", + }); +}); +ChromeUtils.defineESModuleGetters(lazy, { + AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs", + NimbusFeatures: "resource://nimbus/ExperimentAPI.sys.mjs", + PlacesUtils: "resource://gre/modules/PlacesUtils.sys.mjs", + setTimeout: "resource://gre/modules/Timer.sys.mjs", +}); + +export const DAPVisitCounter = new (class { + startup() { + this._asyncShutdownBlocker = async () => { + lazy.logConsole.debug(`Sending on shutdown.`); + await this.send(2 * 1000, "shutdown"); + }; + + lazy.AsyncShutdown.quitApplicationGranted.addBlocker( + "DAPVisitCounter: sending data", + this._asyncShutdownBlocker + ); + + const listener = events => { + // Even using the event.hidden flag there mayb be some double counting + // here. It would have to be fixed in the Places API. + for (const event of events) { + lazy.logConsole.debug(`Visited: ${event.url}`); + if (event.hidden) { + continue; + } + for (const counter of this.counters) { + for (const pattern of counter.patterns) { + if (pattern.matches(event.url)) { + lazy.logConsole.debug(`${pattern.pattern} matched!`); + counter.count += 1; + } + } + } + } + }; + + lazy.NimbusFeatures.dapTelemetry.onUpdate(async (event, reason) => { + if (typeof this.counters !== "undefined") { + await this.send(30 * 1000, "nimbus-update"); + } + this.initialize_counters(); + }); + + if (typeof this.counters === "undefined") { + this.initialize_counters(); + } + + lazy.PlacesUtils.observers.addListener(["page-visited"], listener); + + lazy.setTimeout(() => this.timed_send(), this.timeout_value()); + } + + initialize_counters() { + let experiments = lazy.NimbusFeatures.dapTelemetry.getVariable( + "visitCountingExperimentList" + ); + + this.counters = []; + // This allows two different formats for distributing the URLs for the + // experiment. The experiments get quite large and over 4096 bytes they + // result in a warning (when mirrored in a pref as in this case). + if (Array.isArray(experiments)) { + for (const experiment of experiments) { + let counter = { experiment, count: 0, patterns: [] }; + this.counters.push(counter); + for (const url of experiment.urls) { + let mpattern = new MatchPattern(url); + counter.patterns.push(mpattern); + } + } + } else { + for (const [task, urls] of Object.entries(experiments)) { + for (const [idx, url] of urls.entries()) { + const fullUrl = `*://${url}/*`; + + this.counters.push({ + experiment: { + task_id: task, + task_veclen: 20, + bucket: idx, + }, + count: 0, + patterns: [new MatchPattern(fullUrl)], + }); + } + } + } + } + + async timed_send() { + lazy.logConsole.debug("Sending on timer."); + await this.send(30 * 1000, "periodic"); + lazy.setTimeout(() => this.timed_send(), this.timeout_value()); + } + + timeout_value() { + const MINUTE = 60 * 1000; + return MINUTE * (9 + Math.random() * 2); // 9 - 11 minutes + } + + async send(timeout, reason) { + let collected_measurements = new Map(); + for (const counter of this.counters) { + if (!collected_measurements.has(counter.experiment.task_id)) { + collected_measurements.set( + counter.experiment.task_id, + new Uint8Array(counter.experiment.task_veclen) + ); + } + collected_measurements.get(counter.experiment.task_id)[ + counter.experiment.bucket + ] = counter.count; + counter.count = 0; + } + + let send_promises = []; + for (const [task_id, measurement] of collected_measurements) { + let task = { + id: task_id, + time_precision: 60, + measurement_type: "vecu8", + }; + + send_promises.push( + DAPTelemetrySender.sendDAPMeasurement( + task, + measurement, + timeout, + reason + ) + ); + } + await Promise.all(send_promises); + } + + show() { + for (const counter of this.counters) { + lazy.logConsole.info( + `Experiment: ${counter.experiment.url} -> ${counter.count}` + ); + } + return this.counters; + } +})(); |