blob: 9a61aa19510aedeea00e87d9837266e394d21dca [file] [edit]
<!DOCTYPE html>
<!--
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.
-->
<link rel="import" href="/tracing/value/histogram.html">
<script>
'use strict';
tr.exportTo('tr.v', function() {
/*
* HistogramGrouping objects are registered named functions that map from
* Histogram objects to strings.
*
* They are used to group Histograms by
* tr.v.HistogramSet.groupHistogramsRecursively()
*
* The tr-ui-b-grouping-table-groupby-picker module within the
* tr-v-ui-histogram-set-controls module allows users to select and reorder
* groupings.
*/
class HistogramGrouping {
/**
* @param {string} key
* @param {!function(!tr.v.Histogram):string} callback
*/
constructor(key, callback) {
this.key_ = key;
this.callback_ = callback;
HistogramGrouping.BY_KEY.set(key, this);
}
get key() {
return this.key_;
}
get callback() {
return this.callback_;
}
get label() {
return this.key;
}
/**
* @param {!Set.<string>} tags
* @param {string} diagnosticName
* @return {!Array.<!HistogramGrouping>}
*/
static buildFromTags(tags, diagnosticName) {
const booleanTags = new Set();
const keyValueTags = new Set();
for (const tag of tags) {
if (tag.includes(':')) {
const key = tag.split(':')[0];
if (booleanTags.has(key)) {
throw new Error(
`Tag "${key}" cannot be both boolean and key-value`);
}
keyValueTags.add(key);
} else {
if (keyValueTags.has(tag)) {
throw new Error(
`Tag "${tag}" cannot be both boolean and key-value`);
}
booleanTags.add(tag);
}
}
const groupings = [];
for (const tag of booleanTags) {
groupings.push(HistogramGrouping.buildBooleanTagGrouping_(
tag, diagnosticName));
}
for (const tag of keyValueTags) {
groupings.push(HistogramGrouping.buildKeyValueTagGrouping_(
tag, diagnosticName));
}
return groupings;
}
static buildBooleanTagGrouping_(tag, diagnosticName) {
return new HistogramGrouping(`${tag}Tag`, h => {
const tags = h.diagnostics.get(diagnosticName);
if (tags === undefined || !tags.has(tag)) return `~${tag}`;
return tag;
});
}
static buildKeyValueTagGrouping_(tag, diagnosticName) {
return new HistogramGrouping(`${tag}Tag`, h => {
const tags = h.diagnostics.get(diagnosticName);
if (tags === undefined) return `~${tag}`;
const values = new Set();
for (const value of tags) {
const kvp = value.split(':');
if (kvp.length < 2 || kvp[0] !== tag) continue;
values.add(kvp[1]);
}
if (values.size === 0) return `~${tag}`;
const sortedValues = Array.from(values);
sortedValues.sort();
return sortedValues.join(',');
}, `${tag} tag`);
}
}
HistogramGrouping.BY_KEY = new Map();
HistogramGrouping.HISTOGRAM_NAME = new HistogramGrouping('name', h => h.name);
HistogramGrouping.DISPLAY_LABEL = new HistogramGrouping(
'displayLabel', hist => {
const labels = hist.diagnostics.get(tr.v.d.RESERVED_NAMES.LABELS);
if (labels !== undefined && labels.size > 0) {
return Array.from(labels).join(',');
}
const benchmarks = hist.diagnostics.get(
tr.v.d.RESERVED_NAMES.BENCHMARKS);
const start = hist.diagnostics.get(
tr.v.d.RESERVED_NAMES.BENCHMARK_START);
if (benchmarks === undefined) {
if (start === undefined) return 'Value';
return start.toString();
}
const benchmarksStr = Array.from(benchmarks).join('\n');
if (start === undefined) return benchmarksStr;
return benchmarksStr + '\n' + start.toString();
});
class GenericSetGrouping extends HistogramGrouping {
constructor(name) {
super(name, undefined);
this.callback_ = this.compute_.bind(this);
}
compute_(hist) {
const diag = hist.diagnostics.get(this.key);
if (diag === undefined) return '';
const parts = Array.from(diag);
parts.sort();
return parts.join(',');
}
}
GenericSetGrouping.NAMES = [
tr.v.d.RESERVED_NAMES.ARCHITECTURES,
tr.v.d.RESERVED_NAMES.BENCHMARKS,
tr.v.d.RESERVED_NAMES.BOTS,
tr.v.d.RESERVED_NAMES.BUILDS,
tr.v.d.RESERVED_NAMES.DEVICE_IDS,
tr.v.d.RESERVED_NAMES.MASTERS,
tr.v.d.RESERVED_NAMES.MEMORY_AMOUNTS,
tr.v.d.RESERVED_NAMES.OS_NAMES,
tr.v.d.RESERVED_NAMES.OS_VERSIONS,
tr.v.d.RESERVED_NAMES.PRODUCT_VERSIONS,
tr.v.d.RESERVED_NAMES.STORIES,
tr.v.d.RESERVED_NAMES.STORYSET_REPEATS,
tr.v.d.RESERVED_NAMES.STORY_TAGS,
tr.v.d.RESERVED_NAMES.TEST_PATH,
];
for (const name of GenericSetGrouping.NAMES) {
// Instantiating a HistogramGrouping adds it to BY_KEY.
new GenericSetGrouping(name);
}
class DateRangeGrouping extends HistogramGrouping {
constructor(name) {
super(name, undefined);
this.callback_ = this.compute_.bind(this);
}
compute_(hist) {
const diag = hist.diagnostics.get(this.key);
if (diag === undefined) return '';
return diag.toString();
}
}
DateRangeGrouping.NAMES = [
tr.v.d.RESERVED_NAMES.BENCHMARK_START,
tr.v.d.RESERVED_NAMES.TRACE_START,
];
for (const name of DateRangeGrouping.NAMES) {
new DateRangeGrouping(name);
}
return {
HistogramGrouping,
GenericSetGrouping,
DateRangeGrouping,
};
});
</script>