Commit c33de832 authored by chinsenj's avatar chinsenj Committed by Commit Bot

capture_mode: Add metrics for the number of consecutive screenshots.

This CL adds metrics for counting the number of consecutive screenshots
a user takes. Visit go/capture-mode-metrics to see other planned
metrics.

Test: manual + added
Bug: 1140182
Change-Id: Ic1b39e3601fd890ad42b9d9e18678b60793cd7cb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2532997
Commit-Queue: Jeremy Chinsen <chinsenj@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarIlya Sherman <isherman@chromium.org>
Reviewed-by: default avatarWeilun Shi <sweilun@chromium.org>
Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827364}
parent 410645d5
...@@ -54,6 +54,11 @@ namespace { ...@@ -54,6 +54,11 @@ namespace {
CaptureModeController* g_instance = nullptr; CaptureModeController* g_instance = nullptr;
// The amount of time that can elapse from the prior screenshot to be considered
// consecutive.
constexpr base::TimeDelta kConsecutiveScreenshotThreshold =
base::TimeDelta::FromSeconds(5);
constexpr char kScreenCaptureNotificationId[] = "capture_mode_notification"; constexpr char kScreenCaptureNotificationId[] = "capture_mode_notification";
constexpr char kScreenCaptureStoppedNotificationId[] = constexpr char kScreenCaptureStoppedNotificationId[] =
"capture_mode_stopped_notification"; "capture_mode_stopped_notification";
...@@ -247,7 +252,12 @@ CaptureModeController::CaptureModeController( ...@@ -247,7 +252,12 @@ CaptureModeController::CaptureModeController(
// service. // service.
{base::MayBlock(), base::TaskPriority::BEST_EFFORT, {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
recording_service_client_receiver_(this) { recording_service_client_receiver_(this),
num_consecutive_screenshots_scheduler_(
FROM_HERE,
kConsecutiveScreenshotThreshold,
this,
&CaptureModeController::RecordAndResetConsecutiveScreenshots) {
DCHECK_EQ(g_instance, nullptr); DCHECK_EQ(g_instance, nullptr);
g_instance = this; g_instance = this;
...@@ -259,14 +269,14 @@ CaptureModeController::CaptureModeController( ...@@ -259,14 +269,14 @@ CaptureModeController::CaptureModeController(
num_screenshots_taken_in_last_day_scheduler_.Start( num_screenshots_taken_in_last_day_scheduler_.Start(
FROM_HERE, base::TimeDelta::FromDays(1), FROM_HERE, base::TimeDelta::FromDays(1),
base::BindRepeating( base::BindRepeating(
&CaptureModeController::RecordNumberOfScreenshotsTakenInLastDay, &CaptureModeController::RecordAndResetScreenshotsTakenInLastDay,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
// Schedule recording of the number of screenshots taken per week. // Schedule recording of the number of screenshots taken per week.
num_screenshots_taken_in_last_week_scheduler_.Start( num_screenshots_taken_in_last_week_scheduler_.Start(
FROM_HERE, base::TimeDelta::FromDays(7), FROM_HERE, base::TimeDelta::FromDays(7),
base::BindRepeating( base::BindRepeating(
&CaptureModeController::RecordNumberOfScreenshotsTakenInLastWeek, &CaptureModeController::RecordAndResetScreenshotsTakenInLastWeek,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
// TODO(afakhry): Explore starting this only when a video recording starts, so // TODO(afakhry): Explore starting this only when a video recording starts, so
...@@ -513,6 +523,9 @@ void CaptureModeController::CaptureImage() { ...@@ -513,6 +523,9 @@ void CaptureModeController::CaptureImage() {
++num_screenshots_taken_in_last_day_; ++num_screenshots_taken_in_last_day_;
++num_screenshots_taken_in_last_week_; ++num_screenshots_taken_in_last_week_;
++num_consecutive_screenshots_;
num_consecutive_screenshots_scheduler_.Reset();
} }
void CaptureModeController::CaptureVideo() { void CaptureModeController::CaptureVideo() {
...@@ -684,18 +697,21 @@ base::FilePath CaptureModeController::BuildPath(const char* const format_string, ...@@ -684,18 +697,21 @@ base::FilePath CaptureModeController::BuildPath(const char* const format_string,
GetTimeStr(exploded_time, delegate_->Uses24HourFormat()).c_str())); GetTimeStr(exploded_time, delegate_->Uses24HourFormat()).c_str()));
} }
void CaptureModeController::RecordNumberOfScreenshotsTakenInLastDay() { void CaptureModeController::RecordAndResetScreenshotsTakenInLastDay() {
base::UmaHistogramCounts100("Ash.CaptureModeController.ScreenshotsPerDay", RecordNumberOfScreenshotsTakenInLastDay(num_screenshots_taken_in_last_day_);
num_screenshots_taken_in_last_day_);
num_screenshots_taken_in_last_day_ = 0; num_screenshots_taken_in_last_day_ = 0;
} }
void CaptureModeController::RecordNumberOfScreenshotsTakenInLastWeek() { void CaptureModeController::RecordAndResetScreenshotsTakenInLastWeek() {
base::UmaHistogramCounts1000("Ash.CaptureModeController.ScreenshotsPerWeek", RecordNumberOfScreenshotsTakenInLastWeek(num_screenshots_taken_in_last_week_);
num_screenshots_taken_in_last_week_);
num_screenshots_taken_in_last_week_ = 0; num_screenshots_taken_in_last_week_ = 0;
} }
void CaptureModeController::RecordAndResetConsecutiveScreenshots() {
RecordNumberOfConsecutiveScreenshots(num_consecutive_screenshots_);
num_consecutive_screenshots_ = 0;
}
void CaptureModeController::OnVideoRecordCountDownFinished() { void CaptureModeController::OnVideoRecordCountDownFinished() {
// If this event is dispatched after the capture session was cancelled or // If this event is dispatched after the capture session was cancelled or
// destroyed, this should be a no-op. // destroyed, this should be a no-op.
......
...@@ -185,8 +185,12 @@ class ASH_EXPORT CaptureModeController ...@@ -185,8 +185,12 @@ class ASH_EXPORT CaptureModeController
base::Time timestamp) const; base::Time timestamp) const;
// Records the number of screenshots taken. // Records the number of screenshots taken.
void RecordNumberOfScreenshotsTakenInLastDay(); void RecordAndResetScreenshotsTakenInLastDay();
void RecordNumberOfScreenshotsTakenInLastWeek(); void RecordAndResetScreenshotsTakenInLastWeek();
// Records the number of consecutive screenshots taken within 5s of each
// other.
void RecordAndResetConsecutiveScreenshots();
// Called when the video record 3-seconds count down finishes. // Called when the video record 3-seconds count down finishes.
void OnVideoRecordCountDownFinished(); void OnVideoRecordCountDownFinished();
...@@ -250,10 +254,16 @@ class ASH_EXPORT CaptureModeController ...@@ -250,10 +254,16 @@ class ASH_EXPORT CaptureModeController
base::RepeatingTimer num_screenshots_taken_in_last_day_scheduler_; base::RepeatingTimer num_screenshots_taken_in_last_day_scheduler_;
base::RepeatingTimer num_screenshots_taken_in_last_week_scheduler_; base::RepeatingTimer num_screenshots_taken_in_last_week_scheduler_;
// Counters used to track the number of screenshots taken. // Counters used to track the number of screenshots taken. These values are
// not persisted across crashes, restarts or sessions so they only provide a
// rough approximation.
int num_screenshots_taken_in_last_day_ = 0; int num_screenshots_taken_in_last_day_ = 0;
int num_screenshots_taken_in_last_week_ = 0; int num_screenshots_taken_in_last_week_ = 0;
// Counter used to track the number of consecutive screenshots taken.
int num_consecutive_screenshots_ = 0;
base::DelayTimer num_consecutive_screenshots_scheduler_;
// The time when OnVideoRecordCountDownFinished is called and video has // The time when OnVideoRecordCountDownFinished is called and video has
// started recording. It is used when video has finished recording for metrics // started recording. It is used when video has finished recording for metrics
// collection. // collection.
......
...@@ -11,13 +11,19 @@ namespace ash { ...@@ -11,13 +11,19 @@ namespace ash {
namespace { namespace {
constexpr char kCaptureRegionAdjustmentHistogramName[] =
"Ash.CaptureModeController.CaptureRegionAdjusted";
constexpr char kBarButtonHistogramName[] = constexpr char kBarButtonHistogramName[] =
"Ash.CaptureModeController.BarButtons"; "Ash.CaptureModeController.BarButtons";
constexpr char kCaptureRegionAdjustmentHistogramName[] =
"Ash.CaptureModeController.CaptureRegionAdjusted";
constexpr char kConsecutiveScreenshotHistogramName[] =
"Ash.CaptureModeController.ConsecutiveScreenshots";
constexpr char kEntryHistogramName[] = "Ash.CaptureModeController.EntryPoint"; constexpr char kEntryHistogramName[] = "Ash.CaptureModeController.EntryPoint";
constexpr char kRecordTimeHistogramName[] = constexpr char kRecordTimeHistogramName[] =
"Ash.CaptureModeController.ScreenRecordingLength"; "Ash.CaptureModeController.ScreenRecordingLength";
constexpr char kScreenshotsPerDayHistogramName[] =
"Ash.CaptureModeController.ScreenshotsPerDay";
constexpr char kScreenshotsPerWeekHistogramName[] =
"Ash.CaptureModeController.ScreenshotsPerWeek";
constexpr char kSwitchesFromInitialModeHistogramName[] = constexpr char kSwitchesFromInitialModeHistogramName[] =
"Ash.CaptureModeController.SwitchesFromInitialCaptureMode"; "Ash.CaptureModeController.SwitchesFromInitialCaptureMode";
...@@ -41,12 +47,6 @@ void RecordCaptureModeEntryType(CaptureModeEntryType entry_type) { ...@@ -41,12 +47,6 @@ void RecordCaptureModeEntryType(CaptureModeEntryType entry_type) {
GetCaptureModeHistogramName(kEntryHistogramName), entry_type); GetCaptureModeHistogramName(kEntryHistogramName), entry_type);
} }
void RecordNumberOfCaptureRegionAdjustments(int num_adjustments) {
base::UmaHistogramCounts100(
GetCaptureModeHistogramName(kCaptureRegionAdjustmentHistogramName),
num_adjustments);
}
void RecordCaptureModeRecordTime(int64_t length_in_seconds) { void RecordCaptureModeRecordTime(int64_t length_in_seconds) {
// Use custom counts macro instead of custom times so we can record in // Use custom counts macro instead of custom times so we can record in
// seconds instead of milliseconds. The max bucket is 3 hours. // seconds instead of milliseconds. The max bucket is 3 hours.
...@@ -60,4 +60,29 @@ void RecordCaptureModeSwitchesFromInitialMode(bool switched) { ...@@ -60,4 +60,29 @@ void RecordCaptureModeSwitchesFromInitialMode(bool switched) {
base::UmaHistogramBoolean(kSwitchesFromInitialModeHistogramName, switched); base::UmaHistogramBoolean(kSwitchesFromInitialModeHistogramName, switched);
} }
void RecordNumberOfCaptureRegionAdjustments(int num_adjustments) {
base::UmaHistogramCounts100(
GetCaptureModeHistogramName(kCaptureRegionAdjustmentHistogramName),
num_adjustments);
}
void RecordNumberOfConsecutiveScreenshots(int num_consecutive_screenshots) {
if (num_consecutive_screenshots > 1) {
base::UmaHistogramCounts100(kConsecutiveScreenshotHistogramName,
num_consecutive_screenshots);
}
}
void RecordNumberOfScreenshotsTakenInLastDay(
int num_screenshots_taken_in_last_day) {
base::UmaHistogramCounts100(kScreenshotsPerDayHistogramName,
num_screenshots_taken_in_last_day);
}
void RecordNumberOfScreenshotsTakenInLastWeek(
int num_screenshots_taken_in_last_week) {
base::UmaHistogramCounts100(kScreenshotsPerWeekHistogramName,
num_screenshots_taken_in_last_week);
}
} // namespace ash } // namespace ash
...@@ -40,6 +40,12 @@ void RecordCaptureModeBarButtonType(CaptureModeBarButtonType button_type); ...@@ -40,6 +40,12 @@ void RecordCaptureModeBarButtonType(CaptureModeBarButtonType button_type);
// Records the method the user enters capture mode given by |entry_type|. // Records the method the user enters capture mode given by |entry_type|.
void RecordCaptureModeEntryType(CaptureModeEntryType entry_type); void RecordCaptureModeEntryType(CaptureModeEntryType entry_type);
// Records the length in seconds of a recording taken by capture mode.
void RecordCaptureModeRecordTime(int64_t length_in_seconds);
// Records if the user has switched modes during a capture session.
void RecordCaptureModeSwitchesFromInitialMode(bool switched);
// Records the number of times a user adjusts a capture region. This includes // Records the number of times a user adjusts a capture region. This includes
// moving and resizing. The count is started when a user sets the capture source // moving and resizing. The count is started when a user sets the capture source
// as a region. The count is recorded and reset when a user performs a capture. // as a region. The count is recorded and reset when a user performs a capture.
...@@ -47,11 +53,17 @@ void RecordCaptureModeEntryType(CaptureModeEntryType entry_type); ...@@ -47,11 +53,17 @@ void RecordCaptureModeEntryType(CaptureModeEntryType entry_type);
// capture sources. // capture sources.
void RecordNumberOfCaptureRegionAdjustments(int num_adjustments); void RecordNumberOfCaptureRegionAdjustments(int num_adjustments);
// Records the length in seconds of a recording taken by capture mode. // Records the number of times a user consecutively screenshots. Only records a
void RecordCaptureModeRecordTime(int64_t length_in_seconds); // sample if |num_consecutive_screenshots| is greater than 1.
void RecordNumberOfConsecutiveScreenshots(int num_consecutive_screenshots);
// Records if the user has switched modes during a capture session. // Records the number of screenshots taken. This metric is meant to be a rough
void RecordCaptureModeSwitchesFromInitialMode(bool switched); // approximation so its counts are not persisted across crashes, restarts or
// sessions.
void RecordNumberOfScreenshotsTakenInLastDay(
int num_screenshots_taken_in_last_day);
void RecordNumberOfScreenshotsTakenInLastWeek(
int num_screenshots_taken_in_last_week);
} // namespace ash } // namespace ash
......
...@@ -115,6 +115,8 @@ class CaptureModeSessionTestApi { ...@@ -115,6 +115,8 @@ class CaptureModeSessionTestApi {
class CaptureModeTest : public AshTestBase { class CaptureModeTest : public AshTestBase {
public: public:
CaptureModeTest() = default; CaptureModeTest() = default;
CaptureModeTest(base::test::TaskEnvironment::TimeSource time)
: AshTestBase(time) {}
CaptureModeTest(const CaptureModeTest&) = delete; CaptureModeTest(const CaptureModeTest&) = delete;
CaptureModeTest& operator=(const CaptureModeTest&) = delete; CaptureModeTest& operator=(const CaptureModeTest&) = delete;
~CaptureModeTest() override = default; ~CaptureModeTest() override = default;
...@@ -1480,4 +1482,53 @@ TEST_F(CaptureModeTest, FullscreenCapture) { ...@@ -1480,4 +1482,53 @@ TEST_F(CaptureModeTest, FullscreenCapture) {
EXPECT_FALSE(controller->IsActive()); EXPECT_FALSE(controller->IsActive());
} }
// A test class that uses a mock time task environment.
class CaptureModeMockTimeTest : public CaptureModeTest {
public:
CaptureModeMockTimeTest()
: CaptureModeTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
CaptureModeMockTimeTest(const CaptureModeMockTimeTest&) = delete;
CaptureModeMockTimeTest& operator=(const CaptureModeMockTimeTest&) = delete;
~CaptureModeMockTimeTest() override = default;
};
// Tests that the consecutive screenshots histogram is recorded properly.
TEST_F(CaptureModeMockTimeTest, ConsecutiveScreenshotsHistograms) {
constexpr char kConsecutiveScreenshotsHistogram[] =
"Ash.CaptureModeController.ConsecutiveScreenshots";
base::HistogramTester histogram_tester;
auto take_n_screenshots = [this](int n) {
for (int i = 0; i < n; ++i) {
auto* controller = StartImageRegionCapture();
controller->PerformCapture();
}
};
// Take three consecutive screenshots. Should only record after 5 seconds.
StartImageRegionCapture();
const gfx::Rect capture_region(200, 200, 400, 400);
SelectRegion(capture_region);
take_n_screenshots(3);
histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 3, 0);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 3, 1);
// Take only one screenshot. This should not be recorded.
take_n_screenshots(1);
histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 1, 0);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 1, 0);
// Take a screenshot, change source and take another screenshot. This should
// count as 2 consecutive screenshots.
take_n_screenshots(1);
auto* controller = StartCaptureSession(CaptureModeSource::kFullscreen,
CaptureModeType::kImage);
controller->PerformCapture();
histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 2, 0);
task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(5));
histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 2, 1);
}
} // namespace ash } // namespace ash
...@@ -184,7 +184,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -184,7 +184,7 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</histogram> </histogram>
<histogram name="Ash.CaptureModeController.BarButtons.{TabletOrClamshell}" <histogram name="Ash.CaptureModeController.BarButtons.{TabletOrClamshell}"
enum="CaptureModeEntryType" expires_after="2021-09-29"> enum="CaptureModeBarButtonType" expires_after="2021-09-29">
<owner>chinsenj@chromium.org</owner> <owner>chinsenj@chromium.org</owner>
<owner>gzadina@google.com</owner> <owner>gzadina@google.com</owner>
<summary> <summary>
...@@ -210,6 +210,16 @@ reviews. Googlers can read more about this at go/gwsq-gerrit. ...@@ -210,6 +210,16 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
<token key="TabletOrClamshell" variants="DisplayModes"/> <token key="TabletOrClamshell" variants="DisplayModes"/>
</histogram> </histogram>
<histogram name="Ash.CaptureModeController.ConsecutiveScreenshots"
units="consecutive screenshots" expires_after="2021-11-10">
<owner>chinsenj@chromium.org</owner>
<owner>gzadina@google.com</owner>
<summary>
Records the number of consecutive screenshots the user takes within 5s of
each other, regardless of capture options.
</summary>
</histogram>
<histogram name="Ash.CaptureModeController.EntryPoint.{TabletOrClamshell}" <histogram name="Ash.CaptureModeController.EntryPoint.{TabletOrClamshell}"
enum="CaptureModeEntryType" expires_after="2021-09-29"> enum="CaptureModeEntryType" expires_after="2021-09-29">
<owner>chinsenj@chromium.org</owner> <owner>chinsenj@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