Skip to content

Commit

Permalink
Merge pull request #25208 from brave/leo-p3a-entry
Browse files Browse the repository at this point in the history
Add additional entry points to Leo acquisition source metric, add most used Leo entry point metric
  • Loading branch information
DJAndries authored Aug 28, 2024
2 parents f78ce98 + 95860f5 commit b95388f
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 42 deletions.
28 changes: 26 additions & 2 deletions browser/ui/commander/simple_command_source.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,38 @@
#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "brave/app/command_utils.h"
#include "brave/browser/ui/commander/command_source.h"
#include "brave/browser/ui/commander/fuzzy_finder.h"
#include "brave/components/ai_chat/core/common/buildflags/buildflags.h"
#include "chrome/browser/ui/accelerator_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "brave/browser/ui/commander/command_source.h"
#include "brave/browser/ui/commander/fuzzy_finder.h"
#include "ui/base/accelerators/accelerator.h"

#if BUILDFLAG(ENABLE_AI_CHAT)
#include "brave/app/brave_command_ids.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/misc_metrics/process_misc_metrics.h"
#include "brave/components/ai_chat/core/browser/ai_chat_metrics.h"
#endif

namespace commander {

namespace {

void MaybeReportCommandExecution(int command_id) {
#if BUILDFLAG(ENABLE_AI_CHAT)
if (command_id == IDC_TOGGLE_AI_CHAT) {
ai_chat::AIChatMetrics* metrics =
g_brave_browser_process->process_misc_metrics()->ai_chat_metrics();
CHECK(metrics);
metrics->HandleOpenViaEntryPoint(ai_chat::EntryPoint::kOmniboxCommand);
}
#endif
}

} // namespace

SimpleCommandSource::SimpleCommandSource() = default;
SimpleCommandSource::~SimpleCommandSource() = default;

Expand Down Expand Up @@ -60,6 +83,7 @@ CommandSource::CommandResults SimpleCommandSource::GetCommands(

item->command = base::BindOnce(
[](Browser* browser, int command_id) {
MaybeReportCommandExecution(command_id);
chrome::ExecuteCommand(browser, command_id);
},
// Unretained is safe here, as the commands will be reset if the browser
Expand Down
2 changes: 1 addition & 1 deletion browser/ui/views/sidebar/sidebar_items_contents_view.cc
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ void SidebarItemsContentsView::OnItemPressed(const views::View* item,
ai_chat::AIChatMetrics* metrics =
g_brave_browser_process->process_misc_metrics()->ai_chat_metrics();
CHECK(metrics);
metrics->HandleOpenViaSidebar();
metrics->HandleOpenViaEntryPoint(ai_chat::EntryPoint::kSidebar);
}
#endif
controller->ActivatePanelItem(item_model.built_in_item_type);
Expand Down
8 changes: 8 additions & 0 deletions browser/ui/views/toolbar/ai_chat_button.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <memory>

#include "brave/app/brave_command_ids.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/misc_metrics/process_misc_metrics.h"
#include "brave/components/ai_chat/core/browser/ai_chat_metrics.h"
#include "brave/components/ai_chat/core/common/pref_names.h"
#include "brave/components/vector_icons/vector_icons.h"
#include "brave/grit/brave_generated_resources.h"
Expand Down Expand Up @@ -74,6 +77,11 @@ AIChatButton::~AIChatButton() = default;

void AIChatButton::ButtonPressed() {
chrome::ExecuteCommand(&browser_.get(), IDC_TOGGLE_AI_CHAT);

ai_chat::AIChatMetrics* metrics =
g_brave_browser_process->process_misc_metrics()->ai_chat_metrics();
CHECK(metrics);
metrics->HandleOpenViaEntryPoint(ai_chat::EntryPoint::kToolbarButton);
}

BEGIN_METADATA(AIChatButton)
Expand Down
13 changes: 13 additions & 0 deletions browser/ui/views/toolbar/brave_app_menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
#include "brave/browser/ui/views/toolbar/brave_vpn_toggle_button.h"
#endif

#if BUILDFLAG(ENABLE_AI_CHAT)
#include "brave/components/ai_chat/core/browser/ai_chat_metrics.h"
#endif

using views::MenuItemView;

namespace {
Expand Down Expand Up @@ -213,6 +217,15 @@ void BraveAppMenu::OnMenuClosed(views::MenuItemView* menu) {
void BraveAppMenu::RecordMenuUsage(int command_id) {
misc_metrics::MenuGroup group;

#if BUILDFLAG(ENABLE_AI_CHAT)
if (command_id == IDC_TOGGLE_AI_CHAT) {
ai_chat::AIChatMetrics* metrics =
g_brave_browser_process->process_misc_metrics()->ai_chat_metrics();
CHECK(metrics);
metrics->HandleOpenViaEntryPoint(ai_chat::EntryPoint::kMenuItem);
}
#endif

switch (command_id) {
case IDC_NEW_WINDOW:
case IDC_NEW_TAB:
Expand Down
105 changes: 73 additions & 32 deletions components/ai_chat/core/browser/ai_chat_metrics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,33 @@ constexpr char kImproveActionKey[] = "improve";
constexpr char kChangeToneActionKey[] = "tone";
constexpr char kChangeLengthActionKey[] = "length";

const char* GetContextMenuActionKey(ContextMenuAction action) {
switch (action) {
case ContextMenuAction::kSummarize:
return kSummarizeActionKey;
case ContextMenuAction::kExplain:
return kExplainActionKey;
case ContextMenuAction::kParaphrase:
return kParaphraseActionKey;
case ContextMenuAction::kCreateTagline:
return kCreateTaglineActionKey;
case ContextMenuAction::kCreateSocialMedia:
return kCreateSocialMediaActionKey;
case ContextMenuAction::kImprove:
return kImproveActionKey;
case ContextMenuAction::kChangeTone:
return kChangeToneActionKey;
case ContextMenuAction::kChangeLength:
return kChangeLengthActionKey;
default:
NOTREACHED_IN_MIGRATION();
return nullptr;
}
}
constexpr char kOmniboxItemEntryPointKey[] = "omnibox_item";
constexpr char kSidebarEntryPointKey[] = "sidebar";
constexpr char kContextMenuEntryPointKey[] = "context_menu";
constexpr char kToolbarButtonEntryPointKey[] = "toolbar_button";
constexpr char kMenuItemEntryPointKey[] = "menu_item";
constexpr char kOmniboxCommandEntryPointKey[] = "omnibox_command";

constexpr auto kContextMenuActionKeys =
base::MakeFixedFlatMap<ContextMenuAction, const char*>(
{{ContextMenuAction::kSummarize, kSummarizeActionKey},
{ContextMenuAction::kExplain, kExplainActionKey},
{ContextMenuAction::kParaphrase, kParaphraseActionKey},
{ContextMenuAction::kCreateTagline, kCreateTaglineActionKey},
{ContextMenuAction::kCreateSocialMedia, kCreateSocialMediaActionKey},
{ContextMenuAction::kImprove, kImproveActionKey},
{ContextMenuAction::kChangeTone, kChangeToneActionKey},
{ContextMenuAction::kChangeLength, kChangeLengthActionKey}});

constexpr auto kEntryPointKeys =
base::MakeFixedFlatMap<EntryPoint, const char*>(
{{EntryPoint::kOmniboxItem, kOmniboxItemEntryPointKey},
{EntryPoint::kSidebar, kSidebarEntryPointKey},
{EntryPoint::kContextMenu, kContextMenuEntryPointKey},
{EntryPoint::kToolbarButton, kToolbarButtonEntryPointKey},
{EntryPoint::kMenuItem, kMenuItemEntryPointKey},
{EntryPoint::kOmniboxCommand, kOmniboxCommandEntryPointKey}});

#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

void ReportHistogramForSidebarExperiment(
Expand Down Expand Up @@ -132,12 +136,17 @@ AIChatMetrics::AIChatMetrics(PrefService* local_state)
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
local_state_(local_state) {
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
for (int i = static_cast<int>(ContextMenuAction::kSummarize);
i <= static_cast<int>(ContextMenuAction::kMaxValue); i++) {
for (int i = 0; i <= static_cast<int>(ContextMenuAction::kMaxValue); i++) {
ContextMenuAction action = static_cast<ContextMenuAction>(i);
context_menu_usage_storages_[action] = std::make_unique<WeeklyStorage>(
local_state_, prefs::kBraveChatP3AContextMenuUsages,
GetContextMenuActionKey(action));
kContextMenuActionKeys.at(action));
}
for (int i = 0; i <= static_cast<int>(EntryPoint::kMaxValue); i++) {
EntryPoint entry_point = static_cast<EntryPoint>(i);
entry_point_storages_[entry_point] = std::make_unique<WeeklyStorage>(
local_state_, prefs::kBraveChatP3AContextMenuUsages,
kEntryPointKeys.at(entry_point));
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
}
Expand Down Expand Up @@ -211,7 +220,7 @@ void AIChatMetrics::RecordReset() {
UMA_HISTOGRAM_EXACT_LINEAR(kEnabledHistogramName,
std::numeric_limits<int>::max() - 1, 3);
UMA_HISTOGRAM_EXACT_LINEAR(kAcquisitionSourceHistogramName,
std::numeric_limits<int>::max() - 1, 3);
std::numeric_limits<int>::max() - 1, 6);
}

void AIChatMetrics::OnPremiumStatusUpdated(bool is_new_user,
Expand Down Expand Up @@ -249,7 +258,7 @@ void AIChatMetrics::RecordNewPrompt() {

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
void AIChatMetrics::RecordOmniboxOpen() {
acquisition_source_ = AcquisitionSource::kOmnibox;
HandleOpenViaEntryPoint(EntryPoint::kOmniboxItem);
omnibox_open_storage_.AddDelta(1);
omnibox_autocomplete_storage_.AddDelta(1);
ReportOmniboxCounts();
Expand All @@ -261,17 +270,23 @@ void AIChatMetrics::RecordOmniboxSearchQuery() {
}

void AIChatMetrics::RecordContextMenuUsage(ContextMenuAction action) {
acquisition_source_ = AcquisitionSource::kContextMenu;
HandleOpenViaEntryPoint(EntryPoint::kContextMenu);
context_menu_usage_storages_[action]->AddDelta(1);
local_state_->SetTime(prefs::kBraveChatP3ALastContextMenuUsageTime,
base::Time::Now());
ReportContextMenuMetrics();
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

void AIChatMetrics::HandleOpenViaSidebar() {
acquisition_source_ = AcquisitionSource::kSidebar;
void AIChatMetrics::HandleOpenViaEntryPoint(EntryPoint entry_point) {
acquisition_source_ = entry_point;

auto* storage = entry_point_storages_.at(entry_point).get();
CHECK(storage);
storage->AddDelta(1u);

ReportEntryPointUsageMetric();
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

void AIChatMetrics::ReportAllMetrics() {
periodic_report_timer_.Start(
Expand All @@ -282,6 +297,7 @@ void AIChatMetrics::ReportAllMetrics() {
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
ReportOmniboxCounts();
ReportContextMenuMetrics();
ReportEntryPointUsageMetric();
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
}

Expand Down Expand Up @@ -403,6 +419,31 @@ void AIChatMetrics::ReportContextMenuMetrics() {
7);
}
}

void AIChatMetrics::ReportEntryPointUsageMetric() {
if (!is_enabled_) {
return;
}

uint64_t entry_point_total_max = 0;
std::optional<EntryPoint> most_used_entry_point;

for (int i = 0; i <= static_cast<int>(EntryPoint::kMaxValue); i++) {
EntryPoint entry_point = static_cast<EntryPoint>(i);
uint64_t entry_point_total =
entry_point_storages_[entry_point]->GetWeeklySum();
if (entry_point_total > entry_point_total_max) {
most_used_entry_point = entry_point;
entry_point_total_max = entry_point_total;
}
}

if (most_used_entry_point) {
UMA_HISTOGRAM_ENUMERATION(kMostUsedEntryPointHistogramName,
*most_used_entry_point);
}
}

#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

} // namespace ai_chat
21 changes: 15 additions & 6 deletions components/ai_chat/core/browser/ai_chat_metrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <memory>
#include <optional>

#include "base/containers/flat_map.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/wall_clock_timer.h"
#include "brave/components/ai_chat/core/common/mojom/ai_chat.mojom.h"
Expand Down Expand Up @@ -59,12 +60,17 @@ inline constexpr char kUsageWeeklySidebarEnabledBHistogramName[] =
"Brave.AIChat.UsageWeekly.SidebarEnabledB";
inline constexpr char kChatCountNebulaHistogramName[] =
"Brave.AIChat.ChatCount.Nebula";
inline constexpr char kMostUsedEntryPointHistogramName[] =
"Brave.AIChat.MostUsedEntryPoint";

enum class AcquisitionSource {
kOmnibox = 0,
enum class EntryPoint {
kOmniboxItem = 0,
kSidebar = 1,
kContextMenu = 2,
kMaxValue = kContextMenu
kToolbarButton = 3,
kMenuItem = 4,
kOmniboxCommand = 5,
kMaxValue = kOmniboxCommand
};

enum class ContextMenuAction {
Expand Down Expand Up @@ -106,10 +112,9 @@ class AIChatMetrics {
void RecordOmniboxSearchQuery();

void RecordContextMenuUsage(ContextMenuAction action);
void HandleOpenViaEntryPoint(EntryPoint entry_point);
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

void HandleOpenViaSidebar();

void OnPremiumStatusUpdated(bool is_new_user,
mojom::PremiumStatus premium_status,
mojom::PremiumInfoPtr);
Expand All @@ -121,12 +126,13 @@ class AIChatMetrics {
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
void ReportOmniboxCounts();
void ReportContextMenuMetrics();
void ReportEntryPointUsageMetric();
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

bool is_enabled_ = false;
bool is_premium_ = false;
bool premium_check_in_progress_ = false;
std::optional<AcquisitionSource> acquisition_source_ = std::nullopt;
std::optional<EntryPoint> acquisition_source_ = std::nullopt;

WeeklyStorage chat_count_storage_;
WeeklyStorage prompt_count_storage_;
Expand All @@ -136,6 +142,9 @@ class AIChatMetrics {

TimePeriodStorage omnibox_open_storage_;
TimePeriodStorage omnibox_autocomplete_storage_;

base::flat_map<EntryPoint, std::unique_ptr<WeeklyStorage>>
entry_point_storages_;
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)

base::OneShotTimer report_debounce_timer_;
Expand Down
Loading

0 comments on commit b95388f

Please sign in to comment.