Skip to content
This repository has been archived by the owner on Oct 9, 2024. It is now read-only.

Add histogram graph query handler using go echarts library #58

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,16 @@ For example, save the CSV to a file, upload it to from Google Spreadsheets, and

![Execution Chart](./images/flat-chart.png)

### Retrieve an interactive chart

Execute the `histogram_graph` query to retrieve an HTML page powered by the `go-echarts` library:

```
$ tctl --namespace benchtest workflow query --query_type histogram_graph --workflow_id 2 | tail -n +2 | sed 's/^\["//' | sed 's/"\]$//' | sed 's/\\n/\n/g' | sed 's/\\u003c/</g' | sed 's/\\u003e/>/g' | sed 's/\\"/"/g' > benchmark.html
```

The resulting HTML can be opened directly in a browser and shows the benchmark run statistics.

## Retrieve the metrics

If you have Prometheus installed and configured, you can pass its URL via `PROMETHEUS_URL` environment variable (default: `http://prometheus-server`),
Expand Down
78 changes: 78 additions & 0 deletions worker/bench/graph.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package bench

import (
"bytes"
"fmt"
"strconv"

"github.com/go-echarts/go-echarts/v2/charts"
"github.com/go-echarts/go-echarts/v2/components"
"github.com/go-echarts/go-echarts/v2/opts"
)

func printHistogramGraph(request benchWorkflowRequest, values []histogramValue) string {
chart := charts.NewLine()
chart.SetGlobalOptions(
charts.WithTitleOpts(opts.Title{
Title: fmt.Sprintf("Benchmark: %s", request.Workflow.Name),
//Subtitle: fmt.Sprintf("Steps:\n%+v", request.Steps),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop

}),
charts.WithLegendOpts(opts.Legend{Show: true}),
charts.WithTooltipOpts(opts.Tooltip{Show: true, Trigger: "axis"}),
charts.WithXAxisOpts(opts.XAxis{Name: "Time (s)"}),
charts.WithInitializationOpts(opts.Initialization{
Width: "1440px",
Height: "900px",
}),
)

interval := request.Report.IntervalInSeconds
times := make([]string, len(values))
workflowsStartedRate := make([]float32, len(values))
workflowsExecutionRate := make([]float32, len(values))
workflowsClosedRate := make([]float32, len(values))
backlog := make([]float32, len(values))
for i, v := range values {
times[i] = strconv.Itoa((i + 1) * interval)
workflowsStartedRate[i] = float32(v.Started) / float32(interval)
workflowsExecutionRate[i] = float32(v.Execution) / float32(interval)
workflowsClosedRate[i] = float32(v.Closed) / float32(interval)
backlog[i] = float32(v.Backlog)
}

seriesOpts := []charts.SeriesOpts{
charts.WithLabelOpts(opts.Label{Show: true, Position: "top"}),
charts.WithLineChartOpts(opts.LineChart{Smooth: true}),
}

chart.SetXAxis(times).
AddSeries("Workflows Started Rate", generateLineData(workflowsStartedRate), seriesOpts...).
AddSeries("Workflows Execution Rate", generateLineData(workflowsExecutionRate), seriesOpts...).
AddSeries("Workflows Closed Rate", generateLineData(workflowsClosedRate), seriesOpts...).
AddSeries("Backlog", generateLineData(backlog), seriesOpts...)

// TODO:
// 1. Add raw data as a table (collapsed if possible)
// 2. Multiple charts / page?
// 3. Add the remaining data in a second chart: workflows started (v.Started),
// workflow executions (v.Execution), workflows closed (v.Closed)
// 4. Example used: https://github.com/go-echarts/examples/blob/master/examples/line.go
Comment on lines +54 to +59
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed.


page := components.NewPage()
page.AddCharts(chart)

var b bytes.Buffer
if err := page.Render(&b); err != nil {
return err.Error()
}

return b.String()
}

func generateLineData(data []float32) []opts.LineData {
items := make([]opts.LineData, 0)
for i := 0; i < len(data); i++ {
items = append(items, opts.LineData{Value: data[i]})
}
return items
}
68 changes: 68 additions & 0 deletions worker/bench/graph_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package bench

import (
"os"
"testing"
)

// TODO: make this a runnable example?
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a test, it generates the same output as the query and saves that as a file in order to iterate on the graph settings.

func Test_printHistogramGraph(t *testing.T) {
type args struct {
request benchWorkflowRequest
values []histogramValue
}
tests := []struct {
name string
args args
}{
{
name: "Benchmark const 500",
args: args{
request: benchWorkflowRequest{
Workflow: benchWorkflowRequestWorkflow{
Name: "basic-workflow",
Args: struct {
SequenceCount int `json:"sequenceCount"`
ParallelCount int `json:"parallelCount"`
ActivityDurationMilliseconds int `json:"activityDurationMilliseconds"`
Payload string `json:"payload"`
ResultPayload string `json:"resultPayload"`
}{
SequenceCount: 3,
},
},
Steps: []benchWorkflowRequestStep{
{
Count: 500,
RatePerSecond: 50,
Concurrency: 5,
},
},
Report: benchWorkflowRequestReporting{IntervalInSeconds: 5},
},
values: []histogramValue{
{Started: 64, Execution: 64, Closed: 11, Backlog: 53},
{Started: 35, Execution: 35, Closed: 63, Backlog: 25},
{Started: 16, Execution: 16, Closed: 88, Backlog: 53},
{Started: 10, Execution: 10, Closed: 99, Backlog: 53},
{Started: 23, Execution: 23, Closed: 87, Backlog: 78},
{Started: 11, Execution: 11, Closed: 93, Backlog: 96},
{Started: 41, Execution: 41, Closed: 99, Backlog: 50},
{Started: 10, Execution: 10, Closed: 60, Backlog: 0},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := printHistogramGraph(tt.args.request, tt.args.values)
f, err := os.Create("test.html")
if err != nil {
t.Fatal(err)
}
if _, err := f.WriteString(got); err != nil {
t.Fatal(err)
}
})
}
}
6 changes: 6 additions & 0 deletions worker/bench/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,12 @@ func (w *benchWorkflow) setupQueries(res []histogramValue, startTime time.Time)
return err
}

if err := workflow.SetQueryHandler(w.ctx, "histogram_graph", func(input []byte) (string, error) {
return printHistogramGraph(w.request, res), nil
}); err != nil {
return err
}

return nil
}

Expand Down
1 change: 1 addition & 0 deletions worker/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/temporalio/maru
go 1.18

require (
github.com/go-echarts/go-echarts/v2 v2.2.4
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.11.0
github.com/prometheus/common v0.26.0
Expand Down
3 changes: 3 additions & 0 deletions worker/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw=
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-echarts/go-echarts/v2 v2.2.4 h1:SKJpdyNIyD65XjbUZjzg6SwccTNXEgmh+PlaO23g2H0=
github.com/go-echarts/go-echarts/v2 v2.2.4/go.mod h1:6TOomEztzGDVDkOSCFBq3ed7xOYfbOqhaBzD0YV771A=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Expand Down Expand Up @@ -508,6 +510,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
Expand Down