diff options
Diffstat (limited to 'devtools/client/webconsole/middleware/event-telemetry.js')
-rw-r--r-- | devtools/client/webconsole/middleware/event-telemetry.js | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/devtools/client/webconsole/middleware/event-telemetry.js b/devtools/client/webconsole/middleware/event-telemetry.js new file mode 100644 index 0000000000..bf5b203af6 --- /dev/null +++ b/devtools/client/webconsole/middleware/event-telemetry.js @@ -0,0 +1,129 @@ +/* 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/. */ + +"use strict"; + +const { + FILTER_TEXT_SET, + FILTER_TOGGLE, + DEFAULT_FILTERS_RESET, + EVALUATE_EXPRESSION, + MESSAGES_ADD, + PERSIST_TOGGLE, + REVERSE_SEARCH_INPUT_TOGGLE, + REVERSE_SEARCH_NEXT, + REVERSE_SEARCH_BACK, +} = require("resource://devtools/client/webconsole/constants.js"); + +/** + * Event telemetry middleware is responsible for logging specific events to telemetry. + */ +function eventTelemetryMiddleware(telemetry, store) { + return next => action => { + const oldState = store.getState(); + const res = next(action); + + const state = store.getState(); + + const filterChangeActions = [ + FILTER_TEXT_SET, + FILTER_TOGGLE, + DEFAULT_FILTERS_RESET, + ]; + + if (filterChangeActions.includes(action.type)) { + filterChange({ + action, + state, + oldState, + telemetry, + }); + } else if (action.type === MESSAGES_ADD) { + messagesAdd({ action, telemetry }); + } else if (action.type === PERSIST_TOGGLE) { + telemetry.recordEvent( + "persist_changed", + "webconsole", + String(state.ui.persistLogs) + ); + } else if (action.type === EVALUATE_EXPRESSION) { + // Send telemetry event. If we are in the browser toolbox we send -1 as the + // toolbox session id. + + telemetry.recordEvent("execute_js", "webconsole", null, { + lines: action.expression.split(/\n/).length, + input: state.ui.editor ? "multiline" : "inline", + }); + + if (action.from === "reverse-search") { + telemetry.recordEvent("reverse_search", "webconsole", null, { + functionality: "evaluate expression", + }); + } + } else if ( + action.type === REVERSE_SEARCH_INPUT_TOGGLE && + state.ui.reverseSearchInputVisible + ) { + telemetry.recordEvent("reverse_search", "webconsole", action.access, { + functionality: "open", + }); + } else if (action.type === REVERSE_SEARCH_NEXT) { + telemetry.recordEvent("reverse_search", "webconsole", action.access, { + functionality: "navigate next", + }); + } else if (action.type === REVERSE_SEARCH_BACK) { + telemetry.recordEvent("reverse_search", "webconsole", action.access, { + functionality: "navigate previous", + }); + } + + return res; + }; +} + +function filterChange({ action, state, oldState, telemetry }) { + const oldFilterState = oldState.filters; + const filterState = state.filters; + const activeFilters = []; + const inactiveFilters = []; + for (const [key, value] of Object.entries(filterState)) { + if (value) { + activeFilters.push(key); + } else { + inactiveFilters.push(key); + } + } + + let trigger; + if (action.type === FILTER_TOGGLE) { + trigger = action.filter; + } else if (action.type === DEFAULT_FILTERS_RESET) { + trigger = "reset"; + } else if (action.type === FILTER_TEXT_SET) { + if (oldFilterState.text !== "" && filterState.text !== "") { + return; + } + + trigger = "text"; + } + + telemetry.recordEvent("filters_changed", "webconsole", null, { + trigger, + active: activeFilters.join(","), + inactive: inactiveFilters.join(","), + }); +} + +function messagesAdd({ action, telemetry }) { + const { messages } = action; + for (const message of messages) { + if (message.level === "error" && message.source === "javascript") { + telemetry + .getKeyedHistogramById("DEVTOOLS_JAVASCRIPT_ERROR_DISPLAYED") + .add(message.errorMessageName || "Unknown", true); + } + } +} + +module.exports = eventTelemetryMiddleware; |