Commit ed06f3d2 authored by Steven Holte's avatar Steven Holte Committed by Commit Bot

Codegen'd UKM builders.

TBR=bmcquade

Change-Id: Id0933c23c20b818dc322ca7f487d1a242df61b4b
Reviewed-on: https://chromium-review.googlesource.com/530095
Commit-Queue: Steven Holte <holte@chromium.org>
Reviewed-by: default avatarRobert Kaplow <rkaplow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488462}
parent 8780d036
......@@ -1671,6 +1671,7 @@ split_static_library("browser") {
"//services/data_decoder/public/cpp",
"//services/device/public/cpp:device_features",
"//services/identity:lib",
"//services/metrics/public/cpp:ukm_builders",
"//services/preferences/public/cpp",
"//services/preferences/public/cpp:service_main",
"//services/preferences/public/cpp/tracked",
......
......@@ -9,6 +9,7 @@
#include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/web_contents.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_entry_builder.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
......@@ -123,18 +124,16 @@ void UkmPageLoadMetricsObserver::OnFailedProvisionalLoad(
RecordPageLoadExtraInfoMetrics(
extra_info, base::TimeTicks() /* no app_background_time */);
ukm::UkmRecorder* ukm_recorder = g_browser_process->ukm_recorder();
std::unique_ptr<ukm::UkmEntryBuilder> builder = ukm_recorder->GetEntryBuilder(
extra_info.source_id, internal::kUkmPageLoadEventName);
// Error codes have negative values, however we log net error code enum values
// for UMA histograms using the equivalent positive value. For consistency in
// UKM, we convert to a positive value here.
int64_t net_error_code = static_cast<int64_t>(failed_load_info.error) * -1;
DCHECK_GE(net_error_code, 0);
builder->AddMetric(internal::kUkmNetErrorCode, net_error_code);
builder->AddMetric(
internal::kUkmFailedProvisionaLoadName,
failed_load_info.time_to_failed_provisional_load.InMilliseconds());
ukm::builders::PageLoad(extra_info.source_id)
.SetNet_ErrorCode_OnFailedProvisionalLoad(net_error_code)
.SetPageTiming_NavigationToFailedProvisionalLoad(
failed_load_info.time_to_failed_provisional_load.InMilliseconds())
.Record(g_browser_process->ukm_recorder());
}
void UkmPageLoadMetricsObserver::OnComplete(
......@@ -148,40 +147,33 @@ void UkmPageLoadMetricsObserver::OnComplete(
void UkmPageLoadMetricsObserver::RecordTimingMetrics(
const page_load_metrics::mojom::PageLoadTiming& timing,
ukm::SourceId source_id) {
ukm::UkmRecorder* ukm_recorder = g_browser_process->ukm_recorder();
std::unique_ptr<ukm::UkmEntryBuilder> builder =
ukm_recorder->GetEntryBuilder(source_id, internal::kUkmPageLoadEventName);
ukm::builders::PageLoad builder(source_id);
if (timing.parse_timing->parse_start) {
builder->AddMetric(
internal::kUkmParseStartName,
builder.SetParseTiming_NavigationToParseStart(
timing.parse_timing->parse_start.value().InMilliseconds());
}
if (timing.document_timing->dom_content_loaded_event_start) {
builder->AddMetric(
internal::kUkmDomContentLoadedName,
builder.SetDocumentTiming_NavigationToDOMContentLoadedEventFired(
timing.document_timing->dom_content_loaded_event_start.value()
.InMilliseconds());
}
if (timing.document_timing->load_event_start) {
builder->AddMetric(
internal::kUkmLoadEventName,
builder.SetDocumentTiming_NavigationToLoadEventFired(
timing.document_timing->load_event_start.value().InMilliseconds());
}
if (timing.paint_timing->first_paint) {
builder->AddMetric(
internal::kUkmFirstPaintName,
builder.SetPaintTiming_NavigationToFirstPaint(
timing.paint_timing->first_paint.value().InMilliseconds());
}
if (timing.paint_timing->first_contentful_paint) {
builder->AddMetric(
internal::kUkmFirstContentfulPaintName,
builder.SetPaintTiming_NavigationToFirstContentfulPaint(
timing.paint_timing->first_contentful_paint.value().InMilliseconds());
}
if (timing.paint_timing->first_meaningful_paint) {
builder->AddMetric(
internal::kUkmFirstMeaningfulPaintName,
builder.SetExperimental_PaintTiming_NavigationToFirstMeaningfulPaint(
timing.paint_timing->first_meaningful_paint.value().InMilliseconds());
}
builder.Record(g_browser_process->ukm_recorder());
}
void UkmPageLoadMetricsObserver::RecordPageLoadExtraInfoMetrics(
......
......@@ -112,6 +112,7 @@ source_set("unit_tests") {
"//components/sync:test_support_driver",
"//components/variations",
"//net:test_support",
"//services/metrics/public/cpp:ukm_builders",
"//testing/gtest",
"//third_party/zlib/google:compression_utils",
"//url",
......
......@@ -22,6 +22,7 @@
#include "components/ukm/ukm_pref_names.h"
#include "components/ukm/ukm_source.h"
#include "components/variations/variations_associated_data.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_entry_builder.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/zlib/google/compression_utils.h"
......@@ -292,10 +293,7 @@ TEST_F(UkmServiceTest, AddEntryWithEmptyMetrics) {
ukm::SourceId id = UkmRecorder::GetNewSourceID();
recorder.UpdateSourceURL(id, GURL("https://google.com/foobar"));
{
std::unique_ptr<UkmEntryBuilder> builder =
service.GetEntryBuilder(id, "PageLoad");
}
{ ::ukm::builders::PageLoad(id).Record(&service); }
service.Flush();
EXPECT_EQ(1, GetPersistedLogCount());
Report proto_report = GetPersistedReport();
......@@ -322,9 +320,9 @@ TEST_F(UkmServiceTest, MetricsProviderTest) {
ukm::SourceId id = UkmRecorder::GetNewSourceID();
recorder.UpdateSourceURL(id, GURL("https://google.com/foobar"));
{
std::unique_ptr<UkmEntryBuilder> builder =
service.GetEntryBuilder(id, "PageLoad");
builder->AddMetric("FirstContentfulPaint", 300);
::ukm::builders::PageLoad(id)
.SetPaintTiming_NavigationToFirstContentfulPaint(300)
.Record(&service);
}
service.Flush();
EXPECT_EQ(GetPersistedLogCount(), 1);
......
......@@ -11,6 +11,8 @@ component("metrics_cpp") {
"mojo_ukm_recorder.h",
"ukm_entry_builder.cc",
"ukm_entry_builder.h",
"ukm_entry_builder_base.cc",
"ukm_entry_builder_base.h",
"ukm_recorder.cc",
"ukm_recorder.h",
]
......@@ -27,3 +29,35 @@ component("metrics_cpp") {
"//mojo/public/cpp/bindings",
]
}
action("gen_ukm_builders") {
script = "//tools/metrics/ukm/gen_builders.py"
sources = [
"//tools/metrics/ukm/ukm.xml",
]
outdir = "$target_gen_dir"
outputs = [
outdir + "/ukm_builders.cc",
outdir + "/ukm_builders.h",
]
args = [
"--input",
rebase_path(sources[0], root_build_dir),
"--output",
rebase_path(outdir, root_build_dir),
]
}
static_library("ukm_builders") {
sources = get_target_outputs(":gen_ukm_builders")
deps = [
":gen_ukm_builders",
":metrics_cpp",
"//base",
]
}
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/metrics/public/cpp/ukm_entry_builder_base.h"
#include <memory>
#include "services/metrics/public/interfaces/ukm_interface.mojom.h"
namespace ukm {
namespace internal {
UkmEntryBuilderBase::UkmEntryBuilderBase(ukm::SourceId source_id,
uint64_t event_hash)
: entry_(mojom::UkmEntry::New()) {
entry_->source_id = source_id;
entry_->event_hash = event_hash;
}
UkmEntryBuilderBase::~UkmEntryBuilderBase() = default;
void UkmEntryBuilderBase::AddMetric(uint64_t metric_hash, int64_t value) {
entry_->metrics.emplace_back(mojom::UkmMetric::New(metric_hash, value));
}
void UkmEntryBuilderBase::Record(UkmRecorder* recorder) {
recorder->AddEntry(std::move(entry_));
}
} // namespace internal
} // namespace ukm
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_BASE_H
#define SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_BASE_H
#include <string>
#include "base/macros.h"
#include "services/metrics/public/cpp/metrics_export.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/interfaces/ukm_interface.mojom.h"
namespace ukm {
namespace internal {
// A base class for generated UkmEntry builder objects.
// This class should not be used directly.
class METRICS_EXPORT UkmEntryBuilderBase {
public:
virtual ~UkmEntryBuilderBase();
void Record(UkmRecorder* recorder);
protected:
UkmEntryBuilderBase(ukm::SourceId source_id, uint64_t event_hash);
// Add metric to the entry. A metric contains a metric hash and value.
void AddMetric(uint64_t metric_hash, int64_t value);
private:
mojom::UkmEntryPtr entry_;
DISALLOW_COPY_AND_ASSIGN(UkmEntryBuilderBase);
};
} // namespace internal
} // namespace ukm
#endif // SERVICES_METRICS_PUBLIC_CPP_UKM_ENTRY_BUILDER_BASE_H
......@@ -66,6 +66,10 @@ class UkmEntryBuilder;
class UkmInterface;
class TestRecordingHelper;
namespace internal {
class UkmEntryBuilderBase;
}
// This feature controls whether UkmService should be created.
METRICS_EXPORT extern const base::Feature kUkmFeature;
......@@ -118,6 +122,7 @@ class METRICS_EXPORT UkmRecorder {
friend previews::PreviewsUKMObserver;
friend resource_coordinator::CoordinationUnitManager;
friend MediaEngagementContentsObserver;
friend internal::UkmEntryBuilderBase;
FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, AddEntryWithEmptyMetrics);
FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, EntryBuilderAndSerialization);
FRIEND_TEST_ALL_PREFIXES(UkmServiceTest,
......
#!/usr/bin/env python
# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A utility for generating builder classes for UKM entries.
It takes as input a ukm.xml file describing all of the entries and metrics,
and produces a c++ header and implementation file exposing builders for those
entries and metrics.
"""
import argparse
import logging
import os
import re
import sys
import model
HEADER = """
// Generated from gen_builders.py. DO NOT EDIT!
// source: ukm.xml
#ifndef SERVICES_METRICS_PUBLIC_CPP_UKM_BUILDERS_H
#define SERVICES_METRICS_PUBLIC_CPP_UKM_BUILDERS_H
#include "services/metrics/public/cpp/ukm_entry_builder_base.h"
namespace ukm {{
namespace builders {{
{decls}
}} // namespace builders
}} // namespace ukm
#endif // SERVICES_METRICS_PUBLIC_CPP_UKM_BUILDERS_H
"""
BODY = """
// Generated from gen_builders.py. DO NOT EDIT!
// source: ukm.xml
#include "services/metrics/public/cpp/ukm_builders.h"
#include "base/metrics/metrics_hashes.h"
namespace ukm {{
namespace builders {{
{impls}
}} // namespace builders
}} // namespace ukm
"""
BUILDER_DECL = """
class {name} : public ::ukm::internal::UkmEntryBuilderBase {{
public:
{name}(ukm::SourceId source_id);
~{name}() override;
{setters}
}};
"""
SETTER_DECL = """
{name}& Set{metric}(int64_t value);
"""
BUILDER_IMPL = """
{name}::{name}(ukm::SourceId source_id) :
::ukm::internal::UkmEntryBuilderBase(
source_id,
base::HashMetricName("{raw}")) {{
}}
{name}::~{name}() = default;
{setters}
"""
SETTER_IMPL = """
{name}& {name}::Set{metric}(int64_t value) {{
AddMetric(base::HashMetricName("{raw}"), value);
return *this;
}}
"""
parser = argparse.ArgumentParser(description='Generate UKM entry builders')
parser.add_argument('--input', help='Path to ukm.xml')
parser.add_argument('--output', help='Path to generated directory')
def sanitize_name(name):
s = re.sub('[^0-9a-zA-Z_]', '_', name)
return s
def GetSetterDecl(builder_name, metric):
metric_name = sanitize_name(metric['name'])
return SETTER_DECL.format(name=builder_name, metric=metric_name)
def GetBuilderDecl(event):
builder_name = sanitize_name(event['name'])
setters = "".join(GetSetterDecl(builder_name, metric)
for metric in event['metrics'])
return BUILDER_DECL.format(name=builder_name, setters=setters)
def GetHeader(data):
decls = "\n".join(GetBuilderDecl(event) for event in data['events'])
return HEADER.format(decls=decls)
def WriteHeader(outdir, data):
output = open(os.path.join(outdir, "ukm_builders.h"), 'w')
output.write(GetHeader(data))
def GetSetterImpl(builder_name, metric):
metric_name = sanitize_name(metric['name'])
return SETTER_IMPL.format(name=builder_name, metric=metric_name,
raw=metric['name'])
def GetBuilderImpl(event):
builder_name = sanitize_name(event['name'])
setters = "\n".join(GetSetterImpl(builder_name, metric)
for metric in event['metrics'])
return BUILDER_IMPL.format(name=builder_name, raw=event['name'],
setters=setters)
def GetBody(data):
impls = "\n".join(GetBuilderImpl(event) for event in data['events'])
return BODY.format(impls=impls)
def WriteBody(outdir, data):
output = open(os.path.join(outdir, "ukm_builders.cc"), 'w')
output.write(GetBody(data))
def main(argv):
args = parser.parse_args()
data = model.UKM_XML_TYPE.Parse(open(args.input).read())
WriteHeader(args.output, data)
WriteBody(args.output, data)
return 0
if '__main__' == __name__:
sys.exit(main(sys.argv))
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