Files
fission-src/test/benchmark/picasso.go
T

250 lines
4.7 KiB
Go

package main
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"
"github.com/wcharczuk/go-chart"
)
var (
title *string
file *string
outputFile *string
outputFormat *string
)
const (
PNG = "png"
SVG = "svg"
)
type (
Tags struct {
Group string `json:"group"`
Iter string `json:"iter"`
Method string `json:"method"`
Name string `json:"name"`
Proto string `json:"proto"`
Status string `json:"status"`
URL string `json:"url"`
Vu string `json:"vu"`
}
Data struct {
Time time.Time `json:"time"`
Value float64 `json:"value"`
Tags Tags `json:"tags"`
}
MetricPoint struct {
Type string `json:"type"`
Data Data `json:"data"`
Metric string `json:"metric"`
}
)
func init() {
title = flag.String("title", "Fission Benchmark", "Chart title")
file = flag.String("file", "", "Metric json file")
outputFile = flag.String("o", "chart.png", "Output file name")
outputFormat = flag.String("format", PNG, "Format of output file (png or svg)")
flag.Parse()
}
func generateContinuousSeries(file string) chart.Series {
f, err := os.OpenFile(file, os.O_RDONLY, 0644)
if err != nil {
fmt.Printf("Failed to open file metric point: %v", err)
return nil
}
defer f.Close()
reader := bufio.NewReader(f)
var points []*MetricPoint
var xVals []float64
var yVals []float64
var initTime *time.Time
for {
l, _, err := reader.ReadLine()
if err == io.EOF {
break
}
point := &MetricPoint{}
err = json.Unmarshal(l, point)
if err != nil {
fmt.Printf("Failed to parse metric point: %v -> %v", err, string(l))
return nil
}
if point.Type != "Point" || point.Metric != "http_req_duration" {
continue
}
points = append(points, point)
if initTime == nil {
initTime = &point.Data.Time
}
timeSinceStart := point.Data.Time.Sub(*initTime).Seconds()
xVals = append(xVals, timeSinceStart)
yVals = append(yVals, point.Data.Value)
}
return chart.ContinuousSeries{
Style: chart.Style{
Show: true,
StrokeColor: chart.GetDefaultColor(0).WithAlpha(64),
FillColor: chart.GetDefaultColor(0).WithAlpha(64),
},
XValues: xVals,
YValues: yVals,
}
}
func generateChart(title string, file string, format chart.RendererProvider, series []chart.Series) error {
if series == nil {
return errors.New("Series cannot be nil")
}
cs := chart.ConcatSeries(series)
graph := chart.Chart{
Title: title,
TitleStyle: chart.StyleShow(),
Background: chart.Style{
Padding: chart.Box{
Top: 50,
Left: 25,
Right: 25,
Bottom: 10,
},
},
XAxis: chart.XAxis{
Name: "Time (s)",
NameStyle: chart.StyleShow(),
Style: chart.StyleShow(),
Range: &chart.ContinuousRange{
Min: 0,
},
ValueFormatter: func(v interface{}) string {
return fmt.Sprintf("%.2f s", v.(float64))
},
},
YAxis: chart.YAxis{
Name: "Response Time (ms)",
NameStyle: chart.StyleShow(),
Style: chart.StyleShow(),
Range: &chart.ContinuousRange{
Min: 0,
},
ValueFormatter: func(v interface{}) string {
return fmt.Sprintf("%d ms", int(v.(float64)))
},
},
Series: cs,
}
buffer := bytes.NewBuffer([]byte{})
err := graph.Render(format, buffer)
if err != nil {
return err
}
err = ioutil.WriteFile(file, buffer.Bytes(), 0644)
if err != nil {
return err
}
return nil
}
func listJsonFiles(path string) ([]string, error) {
fi, err := os.Stat(*file)
if err != nil {
return nil, err
}
if fi.Mode().IsRegular() {
return []string{path}, nil
}
var files []string
err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if strings.HasSuffix(path, ".json") && !info.IsDir() {
files = append(files, path)
return nil
}
return nil
})
return files, nil
}
func main() {
if file == nil || len(*file) == 0 {
fmt.Println("Please provide metric json file name")
return
}
var format chart.RendererProvider
if outputFormat == nil {
format = chart.PNG
} else {
switch strings.ToLower(*outputFormat) {
case PNG:
format = chart.PNG
case SVG:
format = chart.SVG
default:
fmt.Println("Unknown format, use png as output format")
*outputFormat = PNG
}
}
if len(*outputFile) == 0 {
fmt.Println("Please output chart png file name")
return
}
var series []chart.Series
files, err := listJsonFiles(*file)
if err != nil {
fmt.Printf("Failed to get file information: %v", err)
return
}
for _, f := range files {
series = append(series, generateContinuousSeries(f))
}
err = generateChart(*title, *outputFile, format, series)
if err != nil {
fmt.Printf("Failed to generate chart: %v\n", err)
}
}