Commit a175853c authored by Nikunj Bhagat's avatar Nikunj Bhagat Committed by Commit Bot

Add chrome://ukm debug ui

BUG=843181

Change-Id: I8b43a72535dd09a175df731a94dc8e216374e7ff
Reviewed-on: https://chromium-review.googlesource.com/c/1306660
Commit-Queue: Nik Bhagat <nikunjb@chromium.org>
Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Reviewed-by: default avatarcalamity <calamity@chromium.org>
Reviewed-by: default avatarSteven Holte <holte@chromium.org>
Reviewed-by: default avatarMikel Astiz <mastiz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606660}
parent 3ec949fd
......@@ -1223,6 +1223,7 @@ if (closure_compile) {
"chrome/browser/resources:closure_compile",
"content/browser/resources:closure_compile",
"ui/webui/resources:closure_compile",
"components/ukm/debug:closure_compile",
]
if (is_chromeos) {
data_deps += [ "ui/file_manager:closure_compile" ]
......
......@@ -69,8 +69,8 @@ public class UkmTest {
public boolean isUkmEnabled(Tab normalTab) throws Exception {
String state = getElementContent(normalTab, "state");
Assert.assertTrue(
"UKM state: " + state, state.equals("\"True\"") || state.equals("\"False\""));
return state.equals("\"True\"");
"UKM state: " + state, state.equals("\"ENABLED\"") || state.equals("\"DISABLED\""));
return state.equals("\"ENABLED\"");
}
public String getUkmClientId(Tab normalTab) throws Exception {
......
......@@ -158,6 +158,7 @@
<include name="IDR_DOWNLOAD_INTERNALS_VISUALS_JS" file="resources\download_internals\download_internals_visuals.js" type="BINDATA" compress="gzip" />
<include name="IDR_UKM_INTERNALS_HTML" file="../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_UKM_INTERNALS_JS" file="../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_UKM_INTERNALS_CSS" file="../../components/ukm/debug/ukm_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
<if expr="not is_android">
<include name="IDR_MD_DOWNLOADS_1X_INCOGNITO_MARKER_PNG" file="resources\md_downloads\1x\incognito_marker.png" type="BINDATA" />
<include name="IDR_MD_DOWNLOADS_2X_INCOGNITO_MARKER_PNG" file="resources\md_downloads\2x\incognito_marker.png" type="BINDATA" />
......
......@@ -29,6 +29,7 @@ content::WebUIDataSource* CreateUkmHTMLSource() {
content::WebUIDataSource::Create(chrome::kChromeUIUkmHost);
source->AddResourcePath("ukm_internals.js", IDR_UKM_INTERNALS_JS);
source->AddResourcePath("ukm_internals.css", IDR_UKM_INTERNALS_CSS);
source->SetDefaultResource(IDR_UKM_INTERNALS_HTML);
source->UseGzip();
return source;
......
// Copyright 2018 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.
module.exports = {
'env': {'browser': true, 'es6': true,},
'rules': {
'no-var': 'error',
},
};
# Copyright 2018 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.
def _CommonChecks(input_api, output_api):
import web_dev_style.presubmit_support
return (
web_dev_style.presubmit_support.CheckStyleESLint(input_api, output_api) +
input_api.canned_checks.CheckPatchFormatted(
input_api, output_api, check_js=True))
def CheckChangeOnUpload(input_api, output_api):
return _CommonChecks(input_api, output_api)
def CheckChangeOnCommit(input_api, output_api):
return _CommonChecks(input_api, output_api)
......@@ -20,6 +20,8 @@ namespace debug {
namespace {
static const uint64_t BIT_FILTER_LAST32 = 0xffffffffULL;
struct SourceData {
UkmSource* source;
std::vector<mojom::UkmEntry*> entries;
......@@ -38,8 +40,8 @@ base::Value ConvertEntryToValue(const ukm::builders::DecodeMap& decode_map,
const auto it = decode_map.find(entry.event_hash);
if (it == decode_map.end()) {
entry_value.SetKey("name",
base::Value(static_cast<double>(entry.event_hash)));
entry_value.SetKey(
"name", UkmDebugDataExtractor::UInt64AsPairOfInt(entry.event_hash));
} else {
entry_value.SetKey("name", base::Value(it->second.name));
......@@ -49,8 +51,8 @@ base::Value ConvertEntryToValue(const ukm::builders::DecodeMap& decode_map,
base::DictionaryValue metric_value;
metric_value.SetKey("name",
base::Value(GetName(it->second, metric.first)));
metric_value.SetKey("value",
base::Value(static_cast<double>(metric.second)));
metric_value.SetKey(
"value", UkmDebugDataExtractor::UInt64AsPairOfInt(metric.second));
metrics_list_storage->push_back(std::move(metric_value));
}
entry_value.SetKey("metrics", std::move(metrics_list));
......@@ -64,6 +66,17 @@ UkmDebugDataExtractor::UkmDebugDataExtractor() = default;
UkmDebugDataExtractor::~UkmDebugDataExtractor() = default;
// static
base::Value UkmDebugDataExtractor::UInt64AsPairOfInt(uint64_t v) {
// Convert int64_t to pair of int. Passing int64_t in base::Value is not
// supported. The pair of int will be passed as a ListValue.
base::Value::ListStorage int_pair;
int_pair.push_back(
base::Value(static_cast<int>((v >> 32) & BIT_FILTER_LAST32)));
int_pair.push_back(base::Value(static_cast<int>(v & BIT_FILTER_LAST32)));
return base::Value(int_pair);
}
// static
base::Value UkmDebugDataExtractor::GetStructuredData(
const UkmService* ukm_service) {
......@@ -72,10 +85,10 @@ base::Value UkmDebugDataExtractor::GetStructuredData(
base::DictionaryValue ukm_data;
ukm_data.SetKey("state", base::Value(ukm_service->recording_enabled_));
ukm_data.SetKey("client_id",
base::Value(static_cast<double>(ukm_service->client_id_)));
ukm_data.SetKey("client_id", UkmDebugDataExtractor::UInt64AsPairOfInt(
ukm_service->client_id_));
ukm_data.SetKey("session_id",
base::Value(static_cast<double>(ukm_service->session_id_)));
base::Value(static_cast<int>(ukm_service->session_id_)));
std::map<SourceId, SourceData> source_data;
for (const auto& kv : ukm_service->recordings_.sources) {
......@@ -93,10 +106,12 @@ base::Value UkmDebugDataExtractor::GetStructuredData(
base::DictionaryValue source_value;
if (src) {
source_value.SetKey("id", base::Value(static_cast<double>(src->id())));
source_value.SetKey("id",
UkmDebugDataExtractor::UInt64AsPairOfInt(src->id()));
source_value.SetKey("url", base::Value(src->url().spec()));
} else {
source_value.SetKey("id", base::Value(static_cast<double>(kv.first)));
source_value.SetKey("id",
UkmDebugDataExtractor::UInt64AsPairOfInt(kv.first));
}
base::ListValue entries_list;
......
......@@ -26,6 +26,13 @@ class UkmDebugDataExtractor {
// Returns UKM data structured in a DictionaryValue.
static base::Value GetStructuredData(const UkmService* ukm_service);
// Convert uint64 to pair of int32 to match the spec of Value. JS doesn't
// support uint64 while most of UKM metrics are 64 bit numbers. So,
// they will be passed as a pair of 32 bit ints. The first item is the
// 32 bit representation of the high 32 bit and the second item is the lower
// 32 bit of the 64 bit number.
static base::Value UInt64AsPairOfInt(uint64_t v);
private:
DISALLOW_COPY_AND_ASSIGN(UkmDebugDataExtractor);
};
......
/* Copyright 2016 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.
*
* This is the stylesheet used by chrome://ukm debug page.
*/
div {
margin: auto;
padding: 2px;
}
div.ukm_collection_status {
background: linear-gradient(0deg, steelblue, lightblue);
padding: 16px;
color: white;
width: auto;
}
div.right_align {
float: right;
width: auto;
}
div.left_align {
display: inline;
}
#sources>div:nth-child(odd) {
background: lightsteelblue;
}
#sources>div:nth-child(even) {
background: lightgrey;
}
span#state, span#clientid {
text-decoration: underline;
font-weight: bold;
}
span.url {
font-weight: bold;
}
span.sourceid {
float: right;
}
div.url_card {
padding: 0px;
}
div.entries {
display: none;
overflow: hidden;
}
div.entry {
width: 470px;
padding: 0px 0px 10px 10px;
display: inline-block;
}
div.collapsible_header {
background-color: #eee;
cursor: pointer;
}
div.collapsible_header:hover {
background-color: #ccc;
}
td {
font-family: "Lucida Console", Monaco, monospace;
font-size: 0.8em;
overflow-wrap: break-word;
border-top: 1px solid black;
}
td.entry_name {
min-width: 320px;
}
td.metric_name {
min-width: 320px;
border-left: 1px solid black;
}
td.metric_value {
text-align: right;
min-width: 120px;
border-left: 1px solid black;
}
table.entry_table {
width: 780px;
border: solid 1px black;
}
select.hex_list {
width: 100px;
font-size: 0.7em;
font-family: "Lucida Console", Monaco, monospace;
height: 22px;
}
div.source_container {
padding: 0px;
}
div.source_container:first-child {
padding-top: 2px;
}
input.text {
width: 480px;
}
input.checkbox {
}
div.labels {
width: 120px;
display: inline-block;
}
......@@ -3,22 +3,52 @@
found in the LICENSE file.-->
<!doctype html>
<html lang="en">
<meta charset="utf-8">
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/promise_resolver.js"></script>
<script src="chrome://resources/js/util.js"></script>
<if expr="is_ios">
<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
<script src="chrome://resources/js/ios/web_ui.js"></script>
</if>
<title>UKM Debug page</title>
<h1>UKM Debug page</h1>
<div>
<p>Is Enabled:<span id="state"></span></p>
<p>Client Id:<span id="clientid"></span></p>
<p>Session Id:<span id="sessionid"></span></p>
<h2>Sources</h2>
<meta charset="utf-8">
<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/promise_resolver.js"></script>
<script src="chrome://resources/js/util.js"></script>
<if expr="is_ios">
<!-- TODO(crbug.com/487000): Remove this once injected by web. -->
<script src="chrome://resources/js/ios/web_ui.js"></script>
</if>
<link rel="stylesheet" type="text/css" href="ukm_internals.css">
<title>UKM Debug page</title>
<div class="ukm_collection_status">
<div>
<div class="left_align"> Metrics Collection is
<span id="state"></span>
(Session: <span id="sessionid"></span>)
</div>
<div class="right_align">ClientId:
<span id="clientid"/>
</div>
</div>
</div>
<div id="warnings"></div>
<div id="sources"></div>
</div>
<script src="ukm_internals.js"></script>
<div>
<div class='labels'> Recorder Ids: </div>
<select id="thread_ids" class="hex_list"></select>
</div>
<div>
<div class='labels'> Metrics Filter: </div>
<input id="metrics_select" type="text" value=".*" class="text" pattern="[A-Za-z0-9\._\*\|\?\+]*" maxlength="256"></input>
</div>
<div>
<div class='labels'> URL Filter: </div>
<input id="url_select" type="text" value=".*" class="text" pattern="[A-Za-z0-9\._\*\|\?\+]*" maxlength="256"></input>
</div>
<div>
<input id="hide_no_metrics" class="checkbox" type="checkbox" checked> Hide Sources With No Metric </input>
</div>
<div>
<input id="hide_no_url" class="checkbox" type="checkbox" checked> Hide Sources With No URL </input>
</div>
<div>
<input id="include_cache" class="checkbox" type="checkbox" checked> Include Cached Sources (since this page load) </input>
</div>
<button id="toggle_expand"></button>
<button id="clear">Clear</button>
<button id="refresh">Refresh</button>
<script src="ukm_internals.js"></script>
</html>
This diff is collapsed.
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