| // 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_ |