// Copyright Epic Games, Inc. All Rights Reserved. "use strict"; import { ZenPage } from "./page.js" import { Fetcher } from "../util/fetcher.js" import { Friendly } from "../util/friendly.js" import { PropTable, Toolbar } from "../util/widgets.js" //////////////////////////////////////////////////////////////////////////////// class TemporalStat { constructor(data, as_bytes) { this._data = data; this._as_bytes = as_bytes; } toString() { const columns = [ /* count */ {}, /* rate */ {}, /* t */ {}, {}, ]; const data = this._data; for (var key in data) { var out = columns[0]; if (key.startsWith("rate_")) out = columns[1]; else if (key.startsWith("t_p")) out = columns[3]; else if (key.startsWith("t_")) out = columns[2]; out[key] = data[key]; } var friendly = this._as_bytes ? Friendly.kib : Friendly.sep; var content = ""; for (var i = 0; i < columns.length; ++i) { const column = columns[i]; for (var key in column) { var value = column[key]; if (i) { value = Friendly.sep(value, 2); key = key.padStart(9); content += key + ": " + value; } else content += friendly(value); content += "\r\n"; } } return content; } tag() { return "pre"; } } //////////////////////////////////////////////////////////////////////////////// export class Page extends ZenPage { async main() { const provider = this.get_param("provider", "z$"); var stats = new Fetcher() .resource("stats", provider) .param("cidstorestats", "true") .param("cachestorestats", "true") .json(); this.set_title("stat - " + provider); const section = this.add_section(provider); var toolbar = section.add_widget(Toolbar); var tb_right = toolbar.right(); tb_right.add("filter:"); tb_right.add("-none-").on_click((x) => this.update_filter("")); for (var preset of ["read.", "write.", ".request", ".bytes"]) tb_right.add(preset).on_click((x) => this.update_filter(x), preset); this._filter_input = tb_right.add("", "label").tag("input"); this._filter_input.on("change", (x) => this.update_filter(x.inner().value), this._filter_input); this._table = section.add_widget(PropTable); this._stats = stats = await stats; this._condense(stats); var first = undefined; for (var name in stats) { first = first || name; toolbar.left().add(name).on_click((x) => this.view_category(x), name); } var filter = this.get_param("filter"); first = this.get_param("view", first); this.view_category(first); if (filter) this.update_filter(filter); } view_category(name) { const friendly = (this.get_param("raw") == undefined); this._table.clear(); this._table.add_object(this._stats[name], friendly, 3); this.set_param("view", name); this.update_filter(""); } update_filter(needle) { this._filter_input.attr("value", needle); this.set_param("filter", needle); if (!needle) return this._table.filter(); var needles = needle.split(" "); this._table.filter(...needles); } _condense(stats) { const impl = function(node) { for (var name in node) { const candidate = node[name]; if (!(candidate instanceof Object)) continue; if (candidate["rate_mean"] != undefined) { const as_bytes = (name.indexOf("bytes") >= 0); node[name] = new TemporalStat(candidate, as_bytes); continue; } impl(candidate); } } for (var name in stats) impl(stats[name]); } }