Commit 68fda66a authored by Richard Knoll's avatar Richard Knoll Committed by Chromium LUCI CQ

Add timing metrics for mute notifications

Adds additional timing metrics for the mute notifications feature:
- How much time passes before the user takes an action on the
  notification
- How long a screen capture session lasts
- How much time passes from start of a session until the user reveals
  notification content again

Bug: 1131375
Change-Id: I70e99cfe5f5726c4372930df84b3a90c37970629
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2617942Reviewed-by: default avatarBrian White <bcwhite@chromium.org>
Reviewed-by: default avatarPeter Beverloo <peter@chromium.org>
Commit-Queue: Richard Knoll <knollr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843123}
parent 739fdb20
...@@ -102,7 +102,7 @@ void ScreenCaptureNotificationBlocker::OnAction( ...@@ -102,7 +102,7 @@ void ScreenCaptureNotificationBlocker::OnAction(
case MutedNotificationHandler::Action::kShowClick: case MutedNotificationHandler::Action::kShowClick:
state_ = NotifyState::kShowAll; state_ = NotifyState::kShowAll;
NotifyBlockingStateChanged(); NotifyBlockingStateChanged();
ReportSessionMetrics(); ReportSessionMetrics(/*revealed=*/true);
break; break;
} }
} }
...@@ -116,19 +116,29 @@ void ScreenCaptureNotificationBlocker::OnIsCapturingDisplayChanged( ...@@ -116,19 +116,29 @@ void ScreenCaptureNotificationBlocker::OnIsCapturingDisplayChanged(
capturing_web_contents_.erase(web_contents); capturing_web_contents_.erase(web_contents);
if (capturing_web_contents_.empty()) { if (capturing_web_contents_.empty()) {
ReportSessionMetrics(); ReportSessionMetrics(/*revealed=*/false);
muted_notification_count_ = 0; muted_notification_count_ = 0;
replaced_notification_count_ = 0; replaced_notification_count_ = 0;
closed_notification_count_ = 0; closed_notification_count_ = 0;
reported_session_metrics_ = false; reported_session_metrics_ = false;
state_ = NotifyState::kNotifyMuted; state_ = NotifyState::kNotifyMuted;
last_screen_capture_session_start_time_ = base::TimeTicks();
CloseMuteNotification(); CloseMuteNotification();
} else if (last_screen_capture_session_start_time_.is_null()) {
last_screen_capture_session_start_time_ = base::TimeTicks::Now();
} }
NotifyBlockingStateChanged(); NotifyBlockingStateChanged();
} }
void ScreenCaptureNotificationBlocker::ReportSessionMetrics() { void ScreenCaptureNotificationBlocker::ReportSessionMetrics(bool revealed) {
auto elapsed_time =
base::TimeTicks::Now() - last_screen_capture_session_start_time_;
base::UmaHistogramLongTimes(
base::StrCat({"Notifications.Blocker.ScreenCapture.",
revealed ? "RevealDuration" : "SessionDuration"}),
elapsed_time);
if (reported_session_metrics_) if (reported_session_metrics_)
return; return;
...@@ -141,9 +151,16 @@ void ScreenCaptureNotificationBlocker::ReportSessionMetrics() { ...@@ -141,9 +151,16 @@ void ScreenCaptureNotificationBlocker::ReportSessionMetrics() {
void ScreenCaptureNotificationBlocker::ReportMuteNotificationAction( void ScreenCaptureNotificationBlocker::ReportMuteNotificationAction(
MutedNotificationHandler::Action action) { MutedNotificationHandler::Action action) {
std::string action_suffix = MutedActionSuffix(action);
RecordScreenCaptureCount( RecordScreenCaptureCount(
base::StrCat({"Action.", MutedActionSuffix(action)}), base::StrCat({"Action.", action_suffix}),
muted_notification_count_ + replaced_notification_count_); muted_notification_count_ + replaced_notification_count_);
auto elapsed_time = base::TimeTicks::Now() - last_mute_notification_time_;
base::UmaHistogramMediumTimes(
base::StrCat(
{"Notifications.Blocker.ScreenCapture.ActionTiming.", action_suffix}),
elapsed_time);
} }
void ScreenCaptureNotificationBlocker::DisplayMuteNotification() { void ScreenCaptureNotificationBlocker::DisplayMuteNotification() {
...@@ -169,6 +186,8 @@ void ScreenCaptureNotificationBlocker::DisplayMuteNotification() { ...@@ -169,6 +186,8 @@ void ScreenCaptureNotificationBlocker::DisplayMuteNotification() {
notification_display_service_->Display( notification_display_service_->Display(
NotificationHandler::Type::NOTIFICATIONS_MUTED, notification, NotificationHandler::Type::NOTIFICATIONS_MUTED, notification,
/*metadata=*/nullptr); /*metadata=*/nullptr);
last_mute_notification_time_ = base::TimeTicks::Now();
} }
void ScreenCaptureNotificationBlocker::CloseMuteNotification() { void ScreenCaptureNotificationBlocker::CloseMuteNotification() {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/scoped_observer.h" #include "base/scoped_observer.h"
#include "base/time/time.h"
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/browser/notifications/muted_notification_handler.h" #include "chrome/browser/notifications/muted_notification_handler.h"
#include "chrome/browser/notifications/notification_blocker.h" #include "chrome/browser/notifications/notification_blocker.h"
...@@ -55,7 +56,7 @@ class ScreenCaptureNotificationBlocker ...@@ -55,7 +56,7 @@ class ScreenCaptureNotificationBlocker
FRIEND_TEST_ALL_PREFIXES(ScreenCaptureNotificationBlockerTest, FRIEND_TEST_ALL_PREFIXES(ScreenCaptureNotificationBlockerTest,
ObservesMediaStreamCaptureIndicator); ObservesMediaStreamCaptureIndicator);
void ReportSessionMetrics(); void ReportSessionMetrics(bool revealed);
void ReportMuteNotificationAction(MutedNotificationHandler::Action action); void ReportMuteNotificationAction(MutedNotificationHandler::Action action);
void DisplayMuteNotification(); void DisplayMuteNotification();
void CloseMuteNotification(); void CloseMuteNotification();
...@@ -77,6 +78,10 @@ class ScreenCaptureNotificationBlocker ...@@ -77,6 +78,10 @@ class ScreenCaptureNotificationBlocker
int closed_notification_count_ = 0; int closed_notification_count_ = 0;
// Flag if metrics have been reported for the current screen capture session. // Flag if metrics have been reported for the current screen capture session.
bool reported_session_metrics_ = false; bool reported_session_metrics_ = false;
// Timestamp of when the last "muted" notification got shown.
base::TimeTicks last_mute_notification_time_;
// Timestamp of when the last screen capture session started.
base::TimeTicks last_screen_capture_session_start_time_;
// The |notification_display_service_| owns a NotificationDisplayQueue which // The |notification_display_service_| owns a NotificationDisplayQueue which
// owns |this| so a raw pointer is safe here. // owns |this| so a raw pointer is safe here.
......
...@@ -124,8 +124,11 @@ class ScreenCaptureNotificationBlockerTest : public testing::Test { ...@@ -124,8 +124,11 @@ class ScreenCaptureNotificationBlockerTest : public testing::Test {
return notifications[0]; return notifications[0];
} }
protected:
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private: private:
content::BrowserTaskEnvironment task_environment_;
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
TestingProfile profile_; TestingProfile profile_;
content::TestWebContentsFactory web_contents_factory_; content::TestWebContentsFactory web_contents_factory_;
...@@ -346,9 +349,16 @@ TEST_F(ScreenCaptureNotificationBlockerTest, CloseHistogram) { ...@@ -346,9 +349,16 @@ TEST_F(ScreenCaptureNotificationBlockerTest, CloseHistogram) {
CreateNotification(GURL("https://example2.com")); CreateNotification(GURL("https://example2.com"));
blocker().OnBlockedNotification(notification, /*replaced*/ false); blocker().OnBlockedNotification(notification, /*replaced*/ false);
auto action_delay = base::TimeDelta::FromSeconds(5);
task_environment_.FastForwardBy(action_delay);
SimulateClose(/*by_user=*/true); SimulateClose(/*by_user=*/true);
histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/1, /*count=*/1); histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/1, /*count=*/1);
histogram_tester.ExpectTotalCount(kHistogram, /*count=*/1); histogram_tester.ExpectTotalCount(kHistogram, /*count=*/1);
histogram_tester.ExpectUniqueTimeSample(
"Notifications.Blocker.ScreenCapture.ActionTiming.Close", action_delay,
/*count=*/1);
blocker().OnBlockedNotification(notification, /*replaced*/ false); blocker().OnBlockedNotification(notification, /*replaced*/ false);
SimulateClose(/*by_user=*/true); SimulateClose(/*by_user=*/true);
...@@ -370,9 +380,16 @@ TEST_F(ScreenCaptureNotificationBlockerTest, BodyClickHistogram) { ...@@ -370,9 +380,16 @@ TEST_F(ScreenCaptureNotificationBlockerTest, BodyClickHistogram) {
CreateNotification(GURL("https://example2.com")); CreateNotification(GURL("https://example2.com"));
blocker().OnBlockedNotification(notification, /*replaced*/ false); blocker().OnBlockedNotification(notification, /*replaced*/ false);
auto action_delay = base::TimeDelta::FromSeconds(5);
task_environment_.FastForwardBy(action_delay);
SimulateClick(/*action_index=*/base::nullopt); SimulateClick(/*action_index=*/base::nullopt);
histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/1, /*count=*/1); histogram_tester.ExpectBucketCount(kHistogram, /*sample=*/1, /*count=*/1);
histogram_tester.ExpectTotalCount(kHistogram, /*count=*/1); histogram_tester.ExpectTotalCount(kHistogram, /*count=*/1);
histogram_tester.ExpectUniqueTimeSample(
"Notifications.Blocker.ScreenCapture.ActionTiming.Body", action_delay,
/*count=*/1);
blocker().OnBlockedNotification(notification, /*replaced*/ false); blocker().OnBlockedNotification(notification, /*replaced*/ false);
SimulateClick(/*action_index=*/base::nullopt); SimulateClick(/*action_index=*/base::nullopt);
...@@ -389,10 +406,17 @@ TEST_F(ScreenCaptureNotificationBlockerTest, ShowClickHistogram) { ...@@ -389,10 +406,17 @@ TEST_F(ScreenCaptureNotificationBlockerTest, ShowClickHistogram) {
CreateNotification(GURL("https://example2.com")); CreateNotification(GURL("https://example2.com"));
blocker().OnBlockedNotification(notification, /*replaced*/ false); blocker().OnBlockedNotification(notification, /*replaced*/ false);
auto action_delay = base::TimeDelta::FromSeconds(5);
task_environment_.FastForwardBy(action_delay);
SimulateClick(kShowActionIndex); SimulateClick(kShowActionIndex);
histogram_tester.ExpectUniqueSample( histogram_tester.ExpectUniqueSample(
"Notifications.Blocker.ScreenCapture.Action.Show", /*sample=*/1, "Notifications.Blocker.ScreenCapture.Action.Show", /*sample=*/1,
/*count=*/1); /*count=*/1);
histogram_tester.ExpectUniqueTimeSample(
"Notifications.Blocker.ScreenCapture.ActionTiming.Show", action_delay,
/*count=*/1);
} }
TEST_F(ScreenCaptureNotificationBlockerTest, SessionEndHistograms) { TEST_F(ScreenCaptureNotificationBlockerTest, SessionEndHistograms) {
...@@ -432,3 +456,33 @@ TEST_F(ScreenCaptureNotificationBlockerTest, SessionEndHistograms) { ...@@ -432,3 +456,33 @@ TEST_F(ScreenCaptureNotificationBlockerTest, SessionEndHistograms) {
"Notifications.Blocker.ScreenCapture.ClosedCount", /*sample=*/1, "Notifications.Blocker.ScreenCapture.ClosedCount", /*sample=*/1,
/*count=*/1); /*count=*/1);
} }
TEST_F(ScreenCaptureNotificationBlockerTest, SessionTimingHistograms) {
base::HistogramTester histogram_tester;
content::WebContents* contents =
CreateWebContents(GURL("https://example1.com"));
blocker().OnIsCapturingDisplayChanged(contents, true);
message_center::Notification notification =
CreateNotification(GURL("https://example2.com"));
blocker().OnBlockedNotification(notification, /*replaced*/ false);
auto click_delay = base::TimeDelta::FromSeconds(3);
task_environment_.FastForwardBy(click_delay);
SimulateClick(kShowActionIndex);
auto session_delay = base::TimeDelta::FromSeconds(5);
task_environment_.FastForwardBy(session_delay);
blocker().OnIsCapturingDisplayChanged(contents, false);
histogram_tester.ExpectUniqueTimeSample(
"Notifications.Blocker.ScreenCapture.RevealDuration", click_delay,
/*count=*/1);
histogram_tester.ExpectUniqueTimeSample(
"Notifications.Blocker.ScreenCapture.SessionDuration",
click_delay + session_delay,
/*count=*/1);
}
...@@ -86,7 +86,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -86,7 +86,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</histogram> </histogram>
<histogram name="Notifications.Blocker.ScreenCapture.Action.{Action}" <histogram name="Notifications.Blocker.ScreenCapture.Action.{Action}"
units="notifications" expires_after="M91"> units="notifications" expires_after="M93">
<owner>knollr@chromium.org</owner> <owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner> <owner>peter@chromium.org</owner>
<summary> <summary>
...@@ -102,8 +102,24 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -102,8 +102,24 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</token> </token>
</histogram> </histogram>
<histogram name="Notifications.Blocker.ScreenCapture.ActionTiming.{Action}"
units="ms" expires_after="M93">
<owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner>
<summary>
Records the time between showing the 'Notifications muted' notification and
the user taking an action on it. Logged each time the user interacts with
the notification. {Action}
</summary>
<token key="Action">
<variant name="Body"/>
<variant name="Close"/>
<variant name="Show"/>
</token>
</histogram>
<histogram name="Notifications.Blocker.ScreenCapture.ClosedCount" <histogram name="Notifications.Blocker.ScreenCapture.ClosedCount"
units="notifications" expires_after="2021-06-20"> units="notifications" expires_after="M93">
<owner>knollr@chromium.org</owner> <owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner> <owner>peter@chromium.org</owner>
<summary> <summary>
...@@ -114,7 +130,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -114,7 +130,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</histogram> </histogram>
<histogram name="Notifications.Blocker.ScreenCapture.MutedCount" <histogram name="Notifications.Blocker.ScreenCapture.MutedCount"
units="notifications" expires_after="2021-06-20"> units="notifications" expires_after="M93">
<owner>knollr@chromium.org</owner> <owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner> <owner>peter@chromium.org</owner>
<summary> <summary>
...@@ -127,7 +143,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -127,7 +143,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</histogram> </histogram>
<histogram name="Notifications.Blocker.ScreenCapture.ReplacedCount" <histogram name="Notifications.Blocker.ScreenCapture.ReplacedCount"
units="notifications" expires_after="2021-06-20"> units="notifications" expires_after="M93">
<owner>knollr@chromium.org</owner> <owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner> <owner>peter@chromium.org</owner>
<summary> <summary>
...@@ -137,6 +153,28 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -137,6 +153,28 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary> </summary>
</histogram> </histogram>
<histogram name="Notifications.Blocker.ScreenCapture.RevealDuration" units="ms"
expires_after="M93">
<owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner>
<summary>
Records the time from the start of a screen capture session until the user
decided to reveal notification content again. Only logged if and when the
user takes that action.
</summary>
</histogram>
<histogram name="Notifications.Blocker.ScreenCapture.SessionDuration"
units="ms" expires_after="M93">
<owner>knollr@chromium.org</owner>
<owner>peter@chromium.org</owner>
<summary>
Records the length of a screen capture session. Notifications will be muted
initially but the user may reveal them during a session. This metric will be
logged after the screen capture session ends.
</summary>
</histogram>
<histogram name="Notifications.Chime.Android.Events" enum="ChimeEvent" <histogram name="Notifications.Chime.Android.Events" enum="ChimeEvent"
expires_after="never"> expires_after="never">
<owner>hesen@chromium.org</owner> <owner>hesen@chromium.org</owner>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment