Commit e61302d7 authored by Liquan(Max) Gu's avatar Liquan(Max) Gu Committed by Commit Bot

[FCP++] Trace event: dump trace when UKM-LCP is fired

We should dump a trace event when the UKM of
Largest Contentful Paint is fired. This trace event can be used in
several ways:
* LCP benchmarks can be built on top of that
* FCP++ viewer can report it
* Loading metrics can report it

Bug:964482

Change-Id: I1492a88f8316d38d64355c5c6d8f723096de35b9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1617687Reviewed-by: default avatarBryan McQuade <bmcquade@chromium.org>
Commit-Queue: Liquan (Max) Gu <maxlg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#663130}
parent 2738b15c
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h" #include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h"
#include "chrome/common/page_load_metrics/page_load_metrics.mojom.h" #include "chrome/common/page_load_metrics/page_load_metrics.mojom.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
...@@ -77,6 +78,28 @@ TimingInfo::TimingInfo( ...@@ -77,6 +78,28 @@ TimingInfo::TimingInfo(
TimingInfo::TimingInfo(const TimingInfo& other) = default; TimingInfo::TimingInfo(const TimingInfo& other) = default;
std::unique_ptr<base::trace_event::TracedValue> TimingInfo::DataAsTraceValue()
const {
std::unique_ptr<base::trace_event::TracedValue> data =
std::make_unique<base::trace_event::TracedValue>();
data->SetInteger("durationInMilliseconds", time_.value().InMilliseconds());
data->SetInteger("size", size_);
data->SetString("type", TypeInString());
return data;
}
std::string TimingInfo::TypeInString() const {
switch (Type()) {
case page_load_metrics::PageLoadMetricsObserver::LargestContentType::kText:
return "text";
case page_load_metrics::PageLoadMetricsObserver::LargestContentType::kImage:
return "image";
default:
NOTREACHED();
return "NOT_REACHED";
}
}
// static // static
void LargestContentfulPaintHandler::SetTestMode(bool enabled) { void LargestContentfulPaintHandler::SetTestMode(bool enabled) {
g_disable_subframe_navigation_start_offset = enabled; g_disable_subframe_navigation_start_offset = enabled;
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <map> #include <map>
#include "base/trace_event/traced_value.h"
#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
#include "chrome/common/page_load_metrics/page_load_metrics.mojom.h" #include "chrome/common/page_load_metrics/page_load_metrics.mojom.h"
#include "chrome/common/page_load_metrics/page_load_timing.h" #include "chrome/common/page_load_metrics/page_load_timing.h"
...@@ -40,12 +41,16 @@ class TimingInfo { ...@@ -40,12 +41,16 @@ class TimingInfo {
return !time_; return !time_;
} }
std::unique_ptr<base::trace_event::TracedValue> DataAsTraceValue() const;
private: private:
TimingInfo() = delete; TimingInfo() = delete;
std::string TypeInString() const;
// This is only for DCHECK. We will never need the inconsistent state. // This is only for DCHECK. We will never need the inconsistent state.
bool HasConsistentTimeAndSize() const { bool HasConsistentTimeAndSize() const {
return (time_ && size_) || (!time_ && !size_); return (time_ && size_) || (!time_ && !size_);
} }
// This uses mainthread navigation start as origin.
base::Optional<base::TimeDelta> time_; base::Optional<base::TimeDelta> time_;
uint64_t size_; uint64_t size_;
page_load_metrics::PageLoadMetricsObserver::LargestContentType type_; page_load_metrics::PageLoadMetricsObserver::LargestContentType type_;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "base/feature_list.h" #include "base/feature_list.h"
#include "base/trace_event/common/trace_event_common.h"
#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process.h"
#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h" #include "chrome/browser/page_load_metrics/observers/largest_contentful_paint_handler.h"
...@@ -306,6 +307,9 @@ void UkmPageLoadMetricsObserver::RecordTimingMetrics( ...@@ -306,6 +307,9 @@ void UkmPageLoadMetricsObserver::RecordTimingMetrics(
largest_contentful_paint_handler_.MergeMainFrameAndSubframes(); largest_contentful_paint_handler_.MergeMainFrameAndSubframes();
if (!paint.IsEmpty() && if (!paint.IsEmpty() &&
WasStartedInForegroundOptionalEventInForeground(paint.Time(), info)) { WasStartedInForegroundOptionalEventInForeground(paint.Time(), info)) {
TRACE_EVENT_INSTANT1(
"loading", "NavStartToLargestContentfulPaint::AllFrames::UKM",
TRACE_EVENT_SCOPE_THREAD, "data", paint.DataAsTraceValue());
builder builder
.SetExperimental_PaintTiming_NavigationToLargestContentPaintAllFrames( .SetExperimental_PaintTiming_NavigationToLargestContentPaintAllFrames(
paint.Time().value().InMilliseconds()); paint.Time().value().InMilliseconds());
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include "base/metrics/metrics_hashes.h" #include "base/metrics/metrics_hashes.h"
#include "base/optional.h" #include "base/optional.h"
#include "base/test/simple_test_clock.h" #include "base/test/simple_test_clock.h"
#include "base/test/trace_event_analyzer.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/trace_event/traced_value.h"
#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" #include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h"
#include "chrome/browser/page_load_metrics/page_load_tracker.h" #include "chrome/browser/page_load_metrics/page_load_tracker.h"
#include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h" #include "chrome/common/page_load_metrics/test/page_load_metrics_test_util.h"
...@@ -413,6 +415,47 @@ TEST_F(UkmPageLoadMetricsObserverTest, LargestTextPaint) { ...@@ -413,6 +415,47 @@ TEST_F(UkmPageLoadMetricsObserverTest, LargestTextPaint) {
} }
} }
TEST_F(UkmPageLoadMetricsObserverTest, LargestContentPaint_Trace) {
using trace_analyzer::Query;
trace_analyzer::Start("*");
{
page_load_metrics::mojom::PageLoadTiming timing;
page_load_metrics::InitPageLoadTimingForTest(&timing);
timing.navigation_start = base::Time::FromDoubleT(1);
timing.paint_timing->largest_text_paint =
base::TimeDelta::FromMilliseconds(600);
timing.paint_timing->largest_text_paint_size = 1000;
PopulateRequiredTimingFields(&timing);
NavigateAndCommit(GURL(kTestUrl1));
SimulateTimingUpdate(timing);
// Simulate closing the tab.
DeleteContents();
}
auto analyzer = trace_analyzer::Stop();
trace_analyzer::TraceEventVector events;
Query q =
Query::EventNameIs("NavStartToLargestContentfulPaint::AllFrames::UKM");
analyzer->FindEvents(q, &events);
EXPECT_EQ(1u, events.size());
EXPECT_EQ("loading", events[0]->category);
EXPECT_TRUE(events[0]->HasArg("data"));
std::unique_ptr<base::Value> arg;
EXPECT_TRUE(events[0]->GetArgAsValue("data", &arg));
base::DictionaryValue* arg_dict;
EXPECT_TRUE(arg->GetAsDictionary(&arg_dict));
int time;
EXPECT_TRUE(arg_dict->GetInteger("durationInMilliseconds", &time));
EXPECT_EQ(600, time);
int size;
EXPECT_TRUE(arg_dict->GetInteger("size", &size));
EXPECT_EQ(1000, size);
std::string type;
EXPECT_TRUE(arg_dict->GetString("type", &type));
EXPECT_EQ("text", type);
}
TEST_F(UkmPageLoadMetricsObserverTest, LargestContentPaint_OnlyText) { TEST_F(UkmPageLoadMetricsObserverTest, LargestContentPaint_OnlyText) {
page_load_metrics::mojom::PageLoadTiming timing; page_load_metrics::mojom::PageLoadTiming timing;
page_load_metrics::InitPageLoadTimingForTest(&timing); page_load_metrics::InitPageLoadTimingForTest(&timing);
......
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