Bug 1678373 - Add a telemetry probe for understanding how media content with audio content is played back. r=alwu data-review=chutten

Differential Revision: https://phabricator.services.mozilla.com/D125089
This commit is contained in:
Paul Adenot 2021-10-07 15:44:54 +00:00
Родитель 82125c0639
Коммит 410e29319c
3 изменённых файлов: 67 добавлений и 4 удалений

Просмотреть файл

@ -322,6 +322,10 @@ bool TelemetryProbesReporter::HasOwnerHadValidVideo() const {
(info.mImage.height > 0 && info.mImage.width > 0); (info.mImage.height > 0 && info.mImage.width > 0);
} }
bool TelemetryProbesReporter::HasOwnerHadValidMedia() const {
return mMediaContent != MediaContent::MEDIA_HAS_NOTHING;
}
void TelemetryProbesReporter::AssertOnMainThreadAndNotShutdown() const { void TelemetryProbesReporter::AssertOnMainThreadAndNotShutdown() const {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mOwner, "Already shutdown?"); MOZ_ASSERT(mOwner, "Already shutdown?");
@ -329,8 +333,10 @@ void TelemetryProbesReporter::AssertOnMainThreadAndNotShutdown() const {
void TelemetryProbesReporter::ReportTelemetry() { void TelemetryProbesReporter::ReportTelemetry() {
AssertOnMainThreadAndNotShutdown(); AssertOnMainThreadAndNotShutdown();
ReportResultForVideo(); // ReportResultForAudio needs to be called first, because it can use the video
// play time, that is reset in ReportResultForVideo.
ReportResultForAudio(); ReportResultForAudio();
ReportResultForVideo();
mOwner->DispatchAsyncTestingEvent(u"mozreportedtelemetry"_ns); mOwner->DispatchAsyncTestingEvent(u"mozreportedtelemetry"_ns);
} }
@ -431,6 +437,15 @@ void TelemetryProbesReporter::ReportResultForVideo() {
} }
void TelemetryProbesReporter::ReportResultForAudio() { void TelemetryProbesReporter::ReportResultForAudio() {
// Don't record telemetry for a media that didn't have a valid audio or video
// to play, or hasn't played.
if (!HasOwnerHadValidMedia() ||
(mTotalAudioPlayTime.PeekTotal() == 0.0 &&
mTotalVideoPlayTime.PeekTotal() == 0.0)) {
return;
}
nsCString key;
const double totalAudioPlayTimeS = mTotalAudioPlayTime.GetAndClearTotal(); const double totalAudioPlayTimeS = mTotalAudioPlayTime.GetAndClearTotal();
const double inaudiblePlayTimeS = mInaudibleAudioPlayTime.GetAndClearTotal(); const double inaudiblePlayTimeS = mInaudibleAudioPlayTime.GetAndClearTotal();
const double mutedPlayTimeS = mMutedAudioPlayTime.GetAndClearTotal(); const double mutedPlayTimeS = mMutedAudioPlayTime.GetAndClearTotal();
@ -440,12 +455,46 @@ void TelemetryProbesReporter::ReportResultForAudio() {
lround(audiblePlayTimeS / totalAudioPlayTimeS * 100.0); lround(audiblePlayTimeS / totalAudioPlayTimeS * 100.0);
const uint32_t unmutedPercentage = const uint32_t unmutedPercentage =
lround(unmutedPlayTimeS / totalAudioPlayTimeS * 100.0); lround(unmutedPlayTimeS / totalAudioPlayTimeS * 100.0);
const double totalVideoPlayTimeS = mTotalVideoPlayTime.PeekTotal();
// Key semantics:
// - AV: Audible audio + video
// - IV: Inaudible audio + video
// - MV: Muted audio + video
// - A: Audible audio-only
// - I: Inaudible audio-only
// - M: Muted audio-only
// - V: Video-only
if (mMediaContent & MediaContent::MEDIA_HAS_AUDIO) {
if (audiblePercentage == 0) {
// Media element had an audio track, but it was inaudible throughout
key.AppendASCII("I");
} else if (unmutedPercentage == 0) {
// Media element had an audio track, but it was muted throughout
key.AppendASCII("M");
} else {
// Media element had an audible audio track
key.AppendASCII("A");
}
}
if (mMediaContent & MediaContent::MEDIA_HAS_VIDEO) {
key.AppendASCII("V");
}
LOG("Key: %s", key.get());
if (mMediaContent & MediaContent::MEDIA_HAS_AUDIO) { if (mMediaContent & MediaContent::MEDIA_HAS_AUDIO) {
LOG("## Audio:\ntotal: %lf\naudible: %lf\ninaudible: %lf\nmuted: %lf\npercentage audible: " LOG("Audio:\ntotal: %lf\naudible: %lf\ninaudible: %lf\nmuted: "
"%lf\npercentage audible: "
"%u\npercentage unmuted: %u\n", "%u\npercentage unmuted: %u\n",
totalAudioPlayTimeS, audiblePlayTimeS, inaudiblePlayTimeS, mutedPlayTimeS totalAudioPlayTimeS, audiblePlayTimeS, inaudiblePlayTimeS,
audiblePercentage, unmutedPercentage); mutedPlayTimeS, audiblePercentage, unmutedPercentage);
Telemetry::Accumulate(Telemetry::MEDIA_PLAY_TIME_MS, key,
SECONDS_TO_MS(totalAudioPlayTimeS));
} else {
MOZ_ASSERT(mMediaContent & MediaContent::MEDIA_HAS_VIDEO);
Telemetry::Accumulate(Telemetry::MEDIA_PLAY_TIME_MS, key,
SECONDS_TO_MS(totalVideoPlayTimeS));
} }
} }

Просмотреть файл

@ -81,6 +81,7 @@ class TelemetryProbesReporter final {
void StartMutedAudioTimeAccumulator(); void StartMutedAudioTimeAccumulator();
void PauseMutedAudioTimeAccumulator(); void PauseMutedAudioTimeAccumulator();
bool HasOwnerHadValidVideo() const; bool HasOwnerHadValidVideo() const;
bool HasOwnerHadValidMedia() const;
void AssertOnMainThreadAndNotShutdown() const; void AssertOnMainThreadAndNotShutdown() const;
void ReportTelemetry(); void ReportTelemetry();

Просмотреть файл

@ -13309,6 +13309,19 @@
"bug_numbers": [1261955, 1127646, 1570634, 1567604, 1685399], "bug_numbers": [1261955, 1127646, 1570634, 1567604, 1685399],
"releaseChannelCollection": "opt-out" "releaseChannelCollection": "opt-out"
}, },
"MEDIA_PLAY_TIME_MS": {
"record_in_processes": ["main", "content"],
"products": ["firefox"],
"alert_emails": ["alwu@mozilla.com", "padenot@mozilla.com"],
"expires_in_version": "never",
"description": "Total time spent playing media in milliseconds, keyed by its content (Audio and video, audio only, video only, audio and video but audio inaudible, audio and video but audio muted). This reports the total play time for a video element whenever the decoder stops. (eg. pausing media, encountering an error, changing to a new resource, page goes to the bf-cached or page gets discarded)",
"keyed": true,
"kind": "exponential",
"high": 7200000,
"n_buckets": 100,
"bug_numbers": [1678373],
"releaseChannelCollection": "opt-out"
},
"VIDEO_VISIBLE_PLAY_TIME_MS" : { "VIDEO_VISIBLE_PLAY_TIME_MS" : {
"record_in_processes": ["main", "content"], "record_in_processes": ["main", "content"],
"products": ["firefox"], "products": ["firefox"],