mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
improve trace-visualizer UX
This commit is contained in:
parent
f203ef3536
commit
1d9bcb5993
@ -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;
|
||||
```
|
||||
|
||||
|
@ -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">×</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++) {
|
||||
|
3
utils/trace-visualizer/js/d3-gantt.js
vendored
3
utils/trace-visualizer/js/d3-gantt.js
vendored
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user