blob: b280bc5abf76ec92214094e827b31a8459e1cdcd [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_COMPOSE_CORE_BROWSER_COMPOSE_METRICS_H_
#define COMPONENTS_COMPOSE_CORE_BROWSER_COMPOSE_METRICS_H_
#include "base/time/time.h"
#include "components/compose/core/browser/compose_enums.mojom.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
namespace base {
class TimeDelta;
} // namespace base
namespace compose {
// Compose histogram names.
extern const char kComposeDialogOpenLatency[];
extern const char kComposeDialogSelectionLength[];
extern const char kComposeRequestReason[];
extern const char kComposeRequestDurationOkSuffix[];
extern const char kComposeRequestDurationErrorSuffix[];
extern const char kComposeRequestStatus[];
extern const char kComposeSessionComposeCount[];
extern const char kComposeSessionCloseReason[];
extern const char kComposeSessionDialogShownCount[];
extern const char kComposeSessionEventCounts[];
extern const char kComposeSessionDuration[];
extern const char kComposeSessionOverOneDay[];
extern const char kComposeSessionUndoCount[];
extern const char kComposeSessionUpdateInputCount[];
extern const char kComposeShowStatus[];
extern const char kComposeFirstRunSessionCloseReason[];
extern const char kComposeFirstRunSessionDialogShownCount[];
extern const char kComposeMSBBSessionCloseReason[];
extern const char kComposeMSBBSessionDialogShownCount[];
extern const char kInnerTextNodeOffsetFound[];
extern const char kComposeContextMenuCtr[];
extern const char kComposeProactiveNudgeCtr[];
extern const char kComposeSelectionNudgeCtr[];
extern const char kComposeProactiveNudgeShowStatus[];
extern const char kOpenComposeDialogResult[];
extern const char kComposeStartSessionEntryPoint[];
extern const char kComposeResumeSessionEntryPoint[];
// Enum for calculating the CTR of the Compose context menu item.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. Keep in sync with
// ComposeContextMenuCtrEvent in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeContextMenuCtrEvent {
kMenuItemDisplayed = 0,
kMenuItemClicked = 1,
kMaxValue = kMenuItemClicked,
};
// Keep in sync with ComposeRequestReason in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeRequestReason {
// When the ComposeUpfrontInputModes featuer is enabled, the "first request"
// is split between one of three input modes.
// TODO(b/371054228): Deprecate the kFirstRequest bucket when upfront inputs
// launches.
kFirstRequest = 0,
kRetryRequest = 1,
kUpdateRequest = 2,
kLengthShortenRequest = 3,
kLengthElaborateRequest = 4,
kToneCasualRequest = 5,
kToneFormalRequest = 6,
kFirstRequestPolishMode = 7,
kFirstRequestElaborateMode = 8,
kFirstRequestFormalizeMode = 9,
kMaxValue = kFirstRequestFormalizeMode,
};
// Close reasons for sessions that start with FRE or MSBB dialogs.
// Keep in sync with ComposeFreOrMsbbSessionCloseReasonType in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeFreOrMsbbSessionCloseReason {
kAbandoned = 0,
kCloseButtonPressed = 1,
kAckedOrAcceptedWithoutInsert = 2,
kAckedOrAcceptedWithInsert = 3,
kReplacedWithNewSession = 4,
kExceededMaxDuration = 5,
kMaxValue = kExceededMaxDuration,
};
// Keep in sync with ComposeSessionCloseReasonType in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeSessionCloseReason {
kInsertedResponse = 0,
kCloseButtonPressed = 1,
kAbandoned = 2, // Tab closed or navigated away with an open session.
kReplacedWithNewSession = 3,
kCanceledBeforeResponseReceived =
4, // Close button pressed with pending navigation.
kExceededMaxDuration = 5,
kEndedAtFre = 6,
kAckedFreEndedAtMsbb = 7,
kEndedAtMsbb = 8,
kMaxValue = kEndedAtMsbb,
};
// Keep in sync with ComposeSessionEventCounts in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeSessionEventTypes {
kMainDialogShown = 0,
kFREShown = 1,
kFREAccepted = 2,
kMSBBShown = 3,
kMSBBSettingsOpened = 4,
kMSBBEnabled = 5,
kStartedWithSelection = 6,
kCreateClicked = 7,
kUpdateClicked = 8,
kRetryClicked = 9,
kUndoClicked = 10,
kShortenClicked = 11,
kElaborateClicked = 12,
kCasualClicked = 13,
kFormalClicked = 14,
kThumbsDown = 15,
kThumbsUp = 16,
kInsertClicked = 17,
kCloseClicked = 18,
kEditClicked = 19,
kCancelEditClicked = 20,
kAnyModifierUsed = 21,
kRedoClicked = 22,
kResultEdited = 23,
kEditedResultInserted = 24,
kSuccessfulRequest = 25,
kFailedRequest = 26,
kComposeDialogOpened = 27,
kMaxValue = kComposeDialogOpened,
};
// Enum for recording the show status of both the HMW context menu item and
// the proactive nudge. These values are persisted to logs. Entries should not
// be renumbered and numeric values should never be reused. Keep in sync with
// ComposeShowStatus in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeShowStatus {
kShouldShow = 0,
kGenericBlocked = 1,
kIncompatibleFieldType = 2,
// DEPRECATED: there is a MSBB dialog now.
// kDisabledMsbb = 3,
kSignedOut = 4,
kUnsupportedLanguage = 5,
kFormFieldInCrossOriginFrame = 6,
kPerUrlChecksFailed = 7,
kUserNotAllowedByOptimizationGuide = 8,
kNotComposeEligible = 9,
kIncorrectScheme = 10,
kFormFieldNestedInFencedFrame = 11,
kComposeFeatureFlagDisabled = 12,
kDisabledOnChromeOS = 13,
kAutocompleteOff = 14,
kWritingSuggestionsFalse = 15,
kProactiveNudgeFeatureDisabled = 16,
kProactiveNudgeDisabledGloballyByUserPreference = 17,
kProactiveNudgeDisabledForSiteByUserPreference = 18,
kProactiveNudgeDisabledByServerConfig = 19,
kProactiveNudgeUnknownServerConfig = 20,
// DEPRECATED: now using the segmentation platform.
// kRandomlyBlocked = 21,
kProactiveNudgeDisabledByMSBB = 22,
kProactiveNudgeBlockedBySegmentationPlatform = 23,
kComposeNotEnabledInCountry = 24,
kUndefinedCountry = 25,
kMaxValue = kUndefinedCountry,
};
// Enum for calculating the CTR of the Compose proactive nudge.
// Keep in sync with ComposeNudgeCtrEvent in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeNudgeCtrEvent {
kNudgeDisplayed = 0,
kDialogOpened = 1,
kUserDisabledProactiveNudge = 2,
kUserDisabledSite = 3,
kOpenSettings = 4,
kMaxValue = kOpenSettings,
};
// Enum for recording the entry point for starting or resuming a Compose
// session. Keep in sync with ComposeEntryPoint in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeEntryPoint {
kContextMenu = 0,
kProactiveNudge = 1,
kSelectionNudge = 2,
kSavedStateNudge = 3,
kSavedStateNotification = 4,
kMaxValue = kSavedStateNotification,
};
enum class EvalLocation : int {
// Response was evaluated on the server.
kServer,
// Response was evaluated on the device.
kOnDevice,
};
// Keep in sync with ComposeSessionEvalLocation in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class SessionEvalLocation {
// No responses were evaluated.
kNone = 0,
// All responses were evaluated on the server.
kServer = 1,
// All responses were evaluated on the device.
kOnDevice = 2,
// Some responses were evaluated on the server and some on the device.
kMixed = 3,
kMaxValue = kMixed,
};
// Enum for recording the feedback state of a Compose request.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. Keep in sync with
// ComposeRequestFeedback in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeRequestFeedback {
kNoFeedback = 0,
kPositiveFeedback = 1,
kNegativeFeedback = 2,
kRequestError = 3,
kMaxValue = kRequestError,
};
// The output metric for the proactive nudge segmentation model. Represents what
// effect the nudge had on the user's engagement. Keep in sync with
// ProactiveNudgeDerivedEngagement in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ProactiveNudgeDerivedEngagement {
// The user didn't interact with the nudge.
kIgnored,
// The user disabled the nudge on this site using the three-dot menu.
kNudgeDisabledOnSingleSite,
// The user disabled the nudge on all sites using the three-dot menu.
kNudgeDisabledOnAllSites,
// User clicked the nudge, but didn't press generate in Compose.
kOpenedComposeMinimalUse,
// User clicked the nudge, pressed generate at least once, but didn't accept
// the suggestion.
kGeneratedComposeSuggestion,
// User clicked, pressed generate, and accepted a suggestion.
kAcceptedComposeSuggestion,
kMaxValue = kAcceptedComposeSuggestion,
};
// Struct containing event and logging information for an individual
// |ComposeSession|.
struct ComposeSessionEvents {
ComposeSessionEvents();
ComposeSessionEvents(ComposeSessionEvents& e) = delete;
ComposeSessionEvents& operator=(ComposeSessionEvents& e) = delete;
~ComposeSessionEvents() = default;
// Logging counters.
// Times we have opened Compose to any section (main, FRE, or MSBB).
unsigned int compose_dialog_open_count = 0;
// Times we have shown the Compose prompot (i.e. past the FRE & MSBB).
unsigned int compose_prompt_view_count = 0;
// The total number of Compose Requests for the session.
unsigned int compose_requests_count = 0;
// The total number of successful Compose requests.
unsigned int successful_requests_count = 0;
// The total number of Compose requests with an error.
unsigned int failed_requests_count = 0;
// Times we have shown the first run view.
unsigned int fre_view_count = 0;
// Times we have shown the view to enable MSBB.
unsigned int msbb_view_count = 0;
// Times the user has pressed "undo" this session.
unsigned int undo_count = 0;
// Times the user has pressed "redo" this session.
unsigned int redo_count = 0;
// Times the user has edited the result text this session.
unsigned int result_edit_count = 0;
// Compose request after input edited.
unsigned int update_input_count = 0;
// Times the user has pressed the "Retry" button.
unsigned int regenerate_count = 0;
// Times the user has picked the "Shorter" option.
unsigned int shorten_count = 0;
// Times the user has picked the "Elaborate" option.
unsigned int lengthen_count = 0;
// Times the user has picked the "Formal" option.
unsigned int formal_count = 0;
// Times the user has picked the "Casual" option.
unsigned int casual_count = 0;
// Logging flags
// True if the FRE was completed in the session.
bool fre_completed_in_session = false;
// True if the MSBB settings were opened.
bool msbb_settings_opened = false;
// True if the MSBB was enabled in the session.
bool msbb_enabled_in_session = false;
// True if the session started from the proactive nudge.
bool started_with_proactive_nudge = false;
// True if the session started with selected text.
bool has_initial_text = false;
// True if thumbs up was ever clicked during the session.
bool has_thumbs_up = false;
// True if thumbs down was ever clicked during the session.
bool has_thumbs_down = false;
// True if the results were eventually inserted back to the web page.
bool inserted_results = false;
// True if an edited result was eventually inserted back to the web page.
bool edited_result_inserted = false;
// True if the the user closed the compose session via the "x" button.
bool close_clicked = false;
// True if the user has pressed the "Edit" button this session.
bool did_click_edit = false;
// True if the user has pressed "Cancel" on the editing view for this session.
bool did_click_cancel_on_edit = false;
// Number of on-device responses received.
unsigned int on_device_responses = 0;
// Number of server responses received.
unsigned int server_responses = 0;
// True if amy compose response was filtered
bool session_contained_filtered_response = false;
// True if any compose response contained error
bool session_contained_any_error = false;
};
// Enum with the possible reasons for it being impossible to open the Compose
// dialog after the user requested it.
// Keep in sync with OpenComposeDialogResult in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class OpenComposeDialogResult {
kSuccess = 0,
kNoChromeComposeClient = 1,
kNoRenderFrameHost = 2,
kNoContentAutofillDriver = 3,
kAutofillFormDataNotFound = 4,
kAutofillFormFieldDataNotFound = 5,
kNoWebContents = 6,
kFailedCreatingComposeDialogView = 7,
kAutofillFormDataNotFoundAfterSelectAll = 8,
kMaxValue = kAutofillFormDataNotFoundAfterSelectAll
};
// Enum to log if the inner text successfuly found an offset
// Keep in sync with ComposeInnerTextNodeOffset in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeInnerTextNodeOffset {
kNoOffsetFound = 0,
kOffsetFound = 1,
kMaxValue = kOffsetFound
};
// Enum to log if all text was selected on behalf of the user.
// Keep in sync with ComposeSelectAllStatus in
// src/tools/metrics/histograms/metadata/compose/enums.xml.
enum class ComposeSelectAllStatus {
kNoSelectAll = 0,
kSelectedAll = 1,
kMaxValue = kSelectedAll
};
// Class that automatically reports any UKM metrics for the page-level Compose
// UKM as defined in go/ukm-collection-chrome-compose.
class PageUkmTracker {
public:
PageUkmTracker(ukm::SourceId source_id);
~PageUkmTracker();
// The compose menu item was shown in a context menu.
void MenuItemShown();
// The compose menu item was clicked, opening Compose.
void MenuItemClicked();
// The composed text was accepted and inserted into the webpage by the user.
void ComposeTextInserted();
// Records that the proactive nudge should show. Recorded anytime the
// proactive nudge could be shown even if the nudge is eventually blocked.
void ComposeProactiveNudgeShouldShow();
// The compose proactive nudge was shown.
void ProactiveNudgeShown();
// The compose proactive nudge was opened.
void ProactiveNudgeOpened();
// Mark that proactive nudge preferences were set during this page load.
void ProactiveNudgeDisabledGlobally();
void ProactiveNudgeDisabledForSite();
// The compose dialog was requested but not shown due to problems obtaining
// form data from Autofill.
void ShowDialogAbortedDueToMissingFormData();
void ShowDialogAbortedDueToMissingFormFieldData();
// Records UKM if any of the above events happened during this object's
// lifetime. Called in the destructor.
void MaybeLogUkm();
private:
bool event_was_recorded_ = false;
unsigned int menu_item_shown_count_ = 0;
unsigned int menu_item_clicked_count_ = 0;
unsigned int compose_text_inserted_count_ = 0;
unsigned int proactive_nudge_should_show_count_ = 0;
unsigned int proactive_nudge_shown_count_ = 0;
unsigned int proactive_nudge_opened_count_ = 0;
bool proactive_nudge_disabled_globally_ = false;
bool proactive_nudge_disabled_for_site_ = false;
unsigned int missing_form_data_count_ = 0;
unsigned int missing_form_field_data_count_ = 0;
ukm::SourceId source_id;
};
void LogComposeContextMenuCtr(ComposeContextMenuCtrEvent event);
void LogComposeContextMenuShowStatus(ComposeShowStatus status);
void LogComposeProactiveNudgeCtr(ComposeNudgeCtrEvent event);
void LogComposeSelectionNudgeCtr(ComposeNudgeCtrEvent event);
void LogComposeProactiveNudgeShowStatus(ComposeShowStatus status);
void LogOpenComposeDialogResult(OpenComposeDialogResult result);
void LogStartSessionEntryPoint(ComposeEntryPoint entry_point);
void LogResumeSessionEntryPoint(ComposeEntryPoint entry_point);
void LogComposeRequestReason(ComposeRequestReason reason);
void LogComposeRequestReason(EvalLocation eval_location,
ComposeRequestReason reason);
void LogComposeRequestStatus(bool page_language_supported,
compose::mojom::ComposeStatus status);
void LogComposeRequestStatus(EvalLocation eval_location,
bool page_language_supported,
compose::mojom::ComposeStatus status);
// Log the duration of a compose request. |is_ok| indicates the status of
// the request.
void LogComposeRequestDuration(base::TimeDelta duration,
EvalLocation eval_location,
bool is_ok);
void LogComposeSessionCloseReason(ComposeSessionCloseReason reason);
void LogComposeFirstRunSessionCloseReason(
ComposeFreOrMsbbSessionCloseReason reason);
// Log session based metrics when a FRE session ends.
void LogComposeFirstRunSessionDialogShownCount(
ComposeFreOrMsbbSessionCloseReason reason,
int dialog_shown_count);
void LogComposeMSBBSessionCloseReason(
ComposeFreOrMsbbSessionCloseReason reason);
// Log session based metrics when a consent session ends.
void LogComposeMSBBSessionDialogShownCount(
ComposeFreOrMsbbSessionCloseReason reason,
int dialog_shown_count);
SessionEvalLocation GetSessionEvalLocationFromEvents(
const ComposeSessionEvents& session_events);
std::optional<EvalLocation> GetEvalLocationFromEvents(
const ComposeSessionEvents& session_events);
// Log session based metrics when a session ends.
// Should only be called once per session.
void LogComposeSessionCloseMetrics(ComposeSessionCloseReason reason,
const ComposeSessionEvents& session_events);
// Log session based UKM metrics when the session ends.
void LogComposeSessionCloseUkmMetrics(
ukm::SourceId source_id,
const ComposeSessionEvents& session_events);
// Log the amount trimmed from the inner text from the page (in bytes) when the
// dialog is opened.
void LogComposeDialogInnerTextShortenedBy(int shortened_by);
// Log the size (in bytes) of the untrimmed inner text from the page when the
// dialog is opened.
void LogComposeDialogInnerTextSize(int size);
// Log if the inner text node offset was found successfully.
void LogComposeDialogInnerTextOffsetFound(bool inner_offset_found);
// Log the time taken for the dialog to be fully shown and interactable.
void LogComposeDialogOpenLatency(base::TimeDelta duration);
// Log the character length of the selection when the dialog is opened.
void LogComposeDialogSelectionLength(int length);
// Log the session duration with |session_suffix| applied to histogram name.
void LogComposeSessionDuration(
base::TimeDelta session_duration,
std::string session_suffix = "",
std::optional<EvalLocation> eval_location = std::nullopt);
void LogComposeRequestFeedback(EvalLocation eval_location,
ComposeRequestFeedback feedback);
void LogComposeSelectAllStatus(ComposeSelectAllStatus select_all_status);
// Emit an enum for for each event present in `session_events`.
// Split the event counts histogram on `eval_location` if provided.
void LogComposeSessionEventCounts(std::optional<EvalLocation> eval_location,
const ComposeSessionEvents& session_events);
} // namespace compose
#endif // COMPONENTS_COMPOSE_CORE_BROWSER_COMPOSE_METRICS_H_