blob: 1bc33a5f3c3d5e231ebdc42195e47f3b30f8dc4d [file] [log] [blame]
// Copyright (c) 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 "components/ukm/debug_page/debug_page.h"
#include <inttypes.h>
#include "base/memory/ref_counted_memory.h"
#include "base/strings/stringprintf.h"
#include "components/ukm/ukm_service.h"
#include "components/ukm/ukm_source.h"
#include "services/metrics/public/cpp/ukm_decode.h"
#include "url/gurl.h"
namespace ukm {
namespace debug {
namespace {
struct SourceData {
UkmSource* source;
std::vector<mojom::UkmEntry*> entries;
};
std::string GetName(ukm::builders::DecodeMap& decode_map, uint64_t hash) {
if (decode_map.count(hash))
return decode_map[hash];
return base::StringPrintf("Unknown %" PRIu64, hash);
}
} // namespace
DebugPage::DebugPage(ServiceGetter service_getter)
: service_getter_(service_getter) {}
DebugPage::~DebugPage() {}
std::string DebugPage::GetSource() const {
return "ukm";
}
std::string DebugPage::GetMimeType(const std::string& path) const {
return "text/html";
}
void DebugPage::StartDataRequest(
const std::string& path,
const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
const content::URLDataSource::GotDataCallback& callback) {
std::string data;
data.append(R"""(<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Security-Policy"
content="object-src 'none'; script-src 'none'">
<title>UKM Debug</title>
</head>
<body>
<h1>UKM Debug page</h1>
)""");
UkmService* ukm_service = service_getter_.Run();
if (ukm_service) {
data.append(
// 'id' attribute set so tests can extract this element.
base::StringPrintf("<p>IsEnabled:<span id='state'>%s</span></p>",
ukm_service->recording_enabled_ ? "True" : "False"));
data.append(base::StringPrintf("<p>ClientId:%" PRIu64 "</p>",
ukm_service->client_id_));
data.append(
base::StringPrintf("<p>SessionId:%d</p>", ukm_service->session_id_));
auto decode_map = ::ukm::builders::CreateDecodeMap();
std::map<SourceId, SourceData> source_data;
for (const auto& kv : ukm_service->sources_) {
source_data[kv.first].source = kv.second.get();
}
for (const auto& v : ukm_service->entries_) {
source_data[v.get()->source_id].entries.push_back(v.get());
}
data.append("<h2>Sources</h2>");
for (const auto& kv : source_data) {
const auto* src = kv.second.source;
if (src) {
data.append(base::StringPrintf("<h3>Id:%" PRId64 " Url:%s</h3>",
src->id(), src->url().spec().c_str()));
} else {
data.append(base::StringPrintf("<h3>Id:%" PRId64 "</h3>", kv.first));
}
for (auto* entry : kv.second.entries) {
data.append(
base::StringPrintf("<h4>Entry:%s</h4>",
GetName(decode_map, entry->event_hash).c_str()));
for (const auto& metric : entry->metrics) {
data.append(base::StringPrintf(
"<h5>Metric:%s Value:%" PRId64 "</h5>",
GetName(decode_map, metric->metric_hash).c_str(), metric->value));
}
}
}
}
data.append(R"""(
</body>
</html>
)""");
callback.Run(base::RefCountedString::TakeString(&data));
}
bool DebugPage::AllowCaching() const {
return false;
}
} // namespace debug
} // namespace ukm