Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
const lazy = {};
ChromeUtils.defineLazyGetter(lazy, "console", () => {
return console.createInstance({
maxLogLevelPref: "toolkit.telemetry.translations.logLevel",
prefix: "TranslationsTelemetry",
});
});
/**
* Telemetry functions for Translations actors
*/
export class TranslationsTelemetry {
/**
* A cached value to hold the current flowId.
*/
static #flowId = null;
/**
* Logs the telemetry event to the console if enabled by toolkit.telemetry.translations.logLevel
*
* @param {Function} caller - The calling function.
* @param {object} [data] - Optional data passed to telemetry.
*/
static logEventToConsole(caller, data) {
const id = TranslationsTelemetry.getOrCreateFlowId().substring(0, 5);
lazy.console?.debug(
`flowId[${id}]: ${caller.name}`,
...(data ? [data] : [])
);
}
/**
* Telemetry functions for the Full Page Translations panel.
*
* @returns {FullPageTranslationsPanelTelemetry}
*/
static fullPagePanel() {
return FullPageTranslationsPanelTelemetry;
}
/**
* Telemetry functions for the SelectTranslationsPanel.
*
* @returns {SelectTranslationsPanelTelemetry}
*/
static selectTranslationsPanel() {
return SelectTranslationsPanelTelemetry;
}
/**
* Telemetry functions for the AboutTranslations page.
*
* @returns {AboutTranslationsPageTelemetry}
*/
static aboutTranslationsPage() {
return AboutTranslationsPageTelemetry;
}
/**
* Forces the creation of a new Translations telemetry flowId and returns it.
*
* @returns {string}
*/
static createFlowId() {
const flowId = crypto.randomUUID();
TranslationsTelemetry.#flowId = flowId;
return flowId;
}
/**
* Returns a Translations telemetry flowId by retrieving the cached value
* if available, or creating a new one otherwise.
*
* @returns {string}
*/
static getOrCreateFlowId() {
// If we have the flowId cached, return it.
if (TranslationsTelemetry.#flowId) {
return TranslationsTelemetry.#flowId;
}
// If no flowId exists, create one.
return TranslationsTelemetry.createFlowId();
}
/**
* Records a telemetry event when full page translation fails.
*
* @param {string} errorMessage
*/
static onError(errorMessage) {
Glean.translations.errorRate.addToNumerator(1);
Glean.translations.error.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
reason: errorMessage,
});
TranslationsTelemetry.logEventToConsole(TranslationsTelemetry.onError, {
errorMessage,
});
}
/**
* Records a telemetry event when a full-page translation request is sent.
*
* @param {object} data
* @param {boolean} data.autoTranslate
* @param {string} data.docLangTag
* @param {string} data.fromLanguage
* @param {string} data.toLanguage
* @param {string} data.topPreferredLanguage
* @param {string} data.requestTarget
* @param {number} data.sourceTextCodeUnits
* @param {number} data.sourceTextWordCount
*/
static onTranslate(data) {
const {
autoTranslate,
docLangTag,
fromLanguage,
requestTarget,
toLanguage,
topPreferredLanguage,
sourceTextCodeUnits,
sourceTextWordCount,
} = data;
Glean.translations.requestsCount.add(1);
Glean.translations.requestCount[requestTarget ?? "full_page"].add(1);
Glean.translations.translationRequest.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
from_language: fromLanguage,
to_language: toLanguage,
auto_translate: autoTranslate,
document_language: docLangTag,
top_preferred_language: topPreferredLanguage,
request_target: requestTarget ?? "full_page",
source_text_code_units: sourceTextCodeUnits,
source_text_word_count: sourceTextWordCount,
});
TranslationsTelemetry.logEventToConsole(
TranslationsTelemetry.onTranslate,
data
);
}
static onRestorePage() {
Glean.translations.restorePage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
TranslationsTelemetry.onRestorePage
);
}
}
/**
* Telemetry functions for the FullPageTranslationsPanel UI
*/
class FullPageTranslationsPanelTelemetry {
/**
* Records a telemetry event when the FullPageTranslationsPanel is opened.
*
* @param {object} data
* @param {string} data.viewName
* @param {string} data.docLangTag
* @param {boolean} data.autoShow
* @param {boolean} data.maintainFlow
* @param {boolean} data.openedFromAppMenu
*/
static onOpen(data) {
Glean.translationsPanel.open.record({
flow_id: data.maintainFlow
? TranslationsTelemetry.getOrCreateFlowId()
: TranslationsTelemetry.createFlowId(),
auto_show: data.autoShow,
view_name: data.viewName,
document_language: data.docLangTag,
opened_from: data.openedFromAppMenu ? "appMenu" : "translationsButton",
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onOpen,
data
);
}
static onClose() {
Glean.translationsPanel.close.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onClose
);
}
static onOpenFromLanguageMenu() {
Glean.translationsPanel.openFromLanguageMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onOpenFromLanguageMenu
);
}
static onChangeFromLanguage(langTag) {
Glean.translationsPanel.changeFromLanguage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
language: langTag,
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onChangeFromLanguage,
{
langTag,
}
);
}
static onCloseFromLanguageMenu() {
Glean.translationsPanel.closeFromLanguageMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onCloseFromLanguageMenu
);
}
static onOpenToLanguageMenu() {
Glean.translationsPanel.openToLanguageMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onOpenToLanguageMenu
);
}
static onChangeToLanguage(langTag) {
Glean.translationsPanel.changeToLanguage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
language: langTag,
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onChangeToLanguage,
{
langTag,
}
);
}
static onCloseToLanguageMenu() {
Glean.translationsPanel.closeToLanguageMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onChangeToLanguage
);
}
static onOpenSettingsMenu() {
Glean.translationsPanel.openSettingsMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onOpenSettingsMenu
);
}
static onCloseSettingsMenu() {
Glean.translationsPanel.closeSettingsMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onCloseSettingsMenu
);
}
static onCancelButton() {
Glean.translationsPanel.cancelButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onCancelButton
);
}
static onChangeSourceLanguageButton() {
Glean.translationsPanel.changeSourceLanguageButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onChangeSourceLanguageButton
);
}
static onDismissErrorButton() {
Glean.translationsPanel.dismissErrorButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onDismissErrorButton
);
}
static onRestorePageButton() {
Glean.translationsPanel.restorePageButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onRestorePageButton
);
}
static onTranslateButton() {
Glean.translationsPanel.translateButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onTranslateButton
);
}
static onAlwaysOfferTranslations(toggledOn) {
Glean.translationsPanel.alwaysOfferTranslations.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
toggled_on: toggledOn,
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onAlwaysOfferTranslations,
{
toggledOn,
}
);
}
static onAlwaysTranslateLanguage(langTag, toggledOn) {
Glean.translationsPanel.alwaysTranslateLanguage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
language: langTag,
toggled_on: toggledOn,
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onAlwaysTranslateLanguage,
{
langTag,
toggledOn,
}
);
}
static onNeverTranslateLanguage(langTag, toggledOn) {
Glean.translationsPanel.neverTranslateLanguage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
language: langTag,
toggled_on: toggledOn,
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onNeverTranslateLanguage,
{
langTag,
toggledOn,
}
);
}
static onNeverTranslateSite(toggledOn) {
Glean.translationsPanel.neverTranslateSite.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
toggled_on: toggledOn,
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onNeverTranslateSite,
{
toggledOn,
}
);
}
static onManageLanguages() {
Glean.translationsPanel.manageLanguages.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onManageLanguages
);
}
static onAboutTranslations() {
Glean.translationsPanel.aboutTranslations.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onAboutTranslations
);
}
static onLearnMoreLink() {
Glean.translationsPanel.learnMore.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
FullPageTranslationsPanelTelemetry.onLearnMoreLink
);
}
}
/**
* Telemetry functions for the SelectTranslationsPanel UI
*/
class SelectTranslationsPanelTelemetry {
/**
* Records a telemetry event when the SelectTranslationsPanel is opened.
*
* @param {object} data
* @param {string} data.docLangTag
* @param {boolean} data.maintainFlow
* @param {string} data.fromLanguage
* @param {string} data.toLanguage
* @param {string} data.topPreferredLanguage
* @param {string} data.textSource
*/
static onOpen(data) {
Glean.translationsSelectTranslationsPanel.open.record({
flow_id: data.maintainFlow
? TranslationsTelemetry.getOrCreateFlowId()
: TranslationsTelemetry.createFlowId(),
document_language: data.docLangTag,
from_language: data.fromLanguage,
to_language: data.toLanguage,
top_preferred_language: data.topPreferredLanguage,
text_source: data.textSource,
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onOpen,
data
);
}
static onClose() {
Glean.translationsSelectTranslationsPanel.close.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onClose
);
}
static onCancelButton() {
Glean.translationsSelectTranslationsPanel.cancelButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onCancelButton
);
}
static onCopyButton() {
Glean.translationsSelectTranslationsPanel.copyButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onCopyButton
);
}
static onDoneButton() {
Glean.translationsSelectTranslationsPanel.doneButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onDoneButton
);
}
static onTranslateButton({ detectedLanguage, fromLanguage, toLanguage }) {
Glean.translationsSelectTranslationsPanel.translateButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
detected_language: detectedLanguage,
from_language: fromLanguage,
to_language: toLanguage,
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onTranslateButton,
{
detectedLanguage,
fromLanguage,
toLanguage,
}
);
}
static onTranslateFullPageButton() {
Glean.translationsSelectTranslationsPanel.translateFullPageButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onTranslateFullPageButton
);
}
static onTryAgainButton() {
Glean.translationsSelectTranslationsPanel.tryAgainButton.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onTryAgainButton
);
}
static onChangeFromLanguage({ previousLangTag, currentLangTag, docLangTag }) {
Glean.translationsSelectTranslationsPanel.changeFromLanguage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
document_language: docLangTag,
previous_language: previousLangTag,
language: currentLangTag,
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onChangeFromLanguage,
{ previousLangTag, currentLangTag, docLangTag }
);
}
static onChangeToLanguage(langTag) {
Glean.translationsSelectTranslationsPanel.changeToLanguage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
language: langTag,
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onChangeToLanguage,
{ langTag }
);
}
static onOpenSettingsMenu() {
Glean.translationsSelectTranslationsPanel.openSettingsMenu.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onOpenSettingsMenu
);
}
static onTranslationSettings() {
Glean.translationsSelectTranslationsPanel.translationSettings.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onTranslationSettings
);
}
static onAboutTranslations() {
Glean.translationsSelectTranslationsPanel.aboutTranslations.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onAboutTranslations
);
}
static onInitializationFailureMessage() {
Glean.translationsSelectTranslationsPanel.initializationFailureMessage.record(
{
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
}
);
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onInitializationFailureMessage
);
}
/**
* Records a telemetry event when the translation-failure message is displayed.
*
* @param {object} data
* @param {string} data.fromLanguage
* @param {string} data.toLanguage
*/
static onTranslationFailureMessage(data) {
Glean.translationsSelectTranslationsPanel.translationFailureMessage.record({
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
from_language: data.fromLanguage,
to_language: data.toLanguage,
});
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onTranslationFailureMessage,
data
);
}
/**
* Records a telemetry event when the unsupported-language message is displayed.
*
* @param {object} data
* @param {string} data.docLangTag
* @param {string} data.detectedLanguage
*/
static onUnsupportedLanguageMessage(data) {
Glean.translationsSelectTranslationsPanel.unsupportedLanguageMessage.record(
{
flow_id: TranslationsTelemetry.getOrCreateFlowId(),
document_language: data.docLangTag,
detected_language: data.detectedLanguage,
}
);
TranslationsTelemetry.logEventToConsole(
SelectTranslationsPanelTelemetry.onUnsupportedLanguageMessage,
data
);
}
}
/**
* Telemetry functions for the AboutTranslations Page
*/
class AboutTranslationsPageTelemetry {
/**
* Records when the about:translations page is opened.
*
* @param {object} data
* @param {boolean} data.maintainFlow
*/
static onOpen(data) {
Glean.translationsAboutTranslationsPage.open.record({
flow_id: data.maintainFlow
? TranslationsTelemetry.getOrCreateFlowId()
: TranslationsTelemetry.createFlowId(),
});
TranslationsTelemetry.logEventToConsole(
AboutTranslationsPageTelemetry.onOpen,
data
);
}
}