improve trace-visualizer UX

This commit is contained in:
Sergei Trifonov 2022-06-17 09:30:08 +02:00
parent f203ef3536
commit 1d9bcb5993
3 changed files with 56 additions and 18 deletions

View File

@ -1,17 +1,12 @@
Trace visualizer is a tool for representation of a tracing data as a Gantt diagram.
# Quick start
For now this tool is not integrated into ClickHouse and requires a lot of manual adjustments.
```bash
cd utils/trace-visualizer
python3 -m http.server
```
Open [localhost](http://localhost:8000). It will show an example of data. To show your tracing data you have to put it in JSON format near `index.html` and change call to `fetchData()` function at the bottom of `index.html`. (Do not forget to disable browser caching while changing it).
For now this tool is not integrated into ClickHouse and requires manual actions. Open `trace-visualizer/index.html` in your browser. It will show an example of data. To visualize your data click `Load` button and select your trace data JSON file.
# Visualizing query trace
First of all [opentelemetry_span_log](https://clickhouse.com/docs/en/operations/opentelemetry/) system table must be enabled to save query traces. Then run a query you want to trace with a setting:
```sql
set opentelemetry_start_trace_probability=1;
SET opentelemetry_start_trace_probability=1;
SELECT 1;
```
@ -22,10 +17,9 @@ SELECT DISTINCT trace_id FROM system.opentelemetry_span_log ORDER BY query_start
To obtain JSON data suitable for visualizing run:
```sql
SELECT tuple (parent_span_id, attribute['clickhouse.thread_id'] || attribute['thread_number'] as thread_id)::Tuple(parent_span_id UInt64, thread_id String) as group, operation_name, start_time_us, finish_time_us, sipHash64(operation_name) as color, attribute
from system.opentelemetry_span_log
SELECT tuple (leftPad(attribute['clickhouse.thread_id'] || attribute['thread_number'], 10, '0') as thread_id, parent_span_id)::Tuple(thread_id String, parent_span_id UInt64) as group, operation_name, start_time_us, finish_time_us, sipHash64(operation_name) as color, attribute
FROM system.opentelemetry_span_log
WHERE trace_id = 'your-trace-id'
ORDER BY group ASC
FORMAT JSON SETTINGS output_format_json_named_tuples_as_objects = 1;
```

View File

@ -14,7 +14,30 @@
<script language="javascript" type="text/javascript" src="js/d3.v4.min.js"></script>
<script language="javascript" type="text/javascript" src="js/d3-tip-0.8.0-alpha.1.js"></script>
<script language="javascript" type="text/javascript" src="js/d3-gantt.js"></script>
<div class="container-fluid" id="toolbar" style="margin:20px;margin-right:50px">
<div class="pull-right">
<button type="button" class="btn btn-primary" id="toolbar-load" data-toggle="modal" data-target="#loadModal">Load</button>
</div>
</div>
<div id="placeholder" class="chart-placeholder"></div>
<div class="modal fade" id="loadModal" tabindex="-1" role="dialog" aria-labelledby="loadModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="loadModalLabel">Load Trace JSON</h4>
</div>
<div class="modal-body">
<input type="file" id="loadFiles" value="Load" /><br />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" id="btnDoLoad">Load</button>
</div>
</div>
</div>
</div>
</body>
</html>
@ -27,13 +50,16 @@
{ t1: 500, t2: 800, band: "band2", color: "#f8f", text: "test\nif\nnew\nline\nworks\nhere?" }
];
var chart = d3.gantt()
.height(window.innerHeight - $("#placeholder")[0].getBoundingClientRect().y - window.scrollY)
.selector("#placeholder");
let chart_height = window.innerHeight - $("#placeholder")[0].getBoundingClientRect().y - 80;
var data = null;
var chart = null;
function renderChart(parsed) {
data = parsed;
chart = d3.gantt().height(chart_height).selector("#placeholder");
chart(data);
}
// Error message popup
$("<div id='errmsg'></div>").css({
position: "absolute",
display: "none",
@ -46,8 +72,7 @@
function fetchData(dataurl, parser = x => x) {
function onDataReceived(json, textStatus, xhr) {
$("#errmsg").hide();
data = parser(json);
chart(data);
renderChart(parser(json));
}
function onDataError(xhr, error) {
@ -70,6 +95,22 @@
}
}
$("#btnDoLoad").click(function(){
let element = document.getElementById('loadFiles');
let files = element.files;
if (files.length <= 0) {
return false;
}
let fr = new FileReader();
fr.onload = function(e) {
$("#errmsg").hide();
renderChart(parseClickHouseTrace(JSON.parse(e.target.result)));
}
fr.readAsText(files.item(0));
element.value = '';
$('#loadModal').modal('hide');
});
function parseClickHouseTrace(json) {
let min_time_us = Number.MAX_VALUE;
for (let i = 0; i < json.data.length; i++) {
@ -114,5 +155,5 @@
}
fetchData(); // do not fetch, just draw example_json w/o parsing
//fetchData("your-traces.json" , parseClickHouseTrace);
//fetchData("your-traces.json", parseClickHouseTrace);
</script>

View File

@ -8,6 +8,9 @@
initAxis();
// clear previous chart (if any)
d3.select(selector).selectAll("svg").remove();
// create svg element
svg = d3.select(selector)
.append("svg")