forked from octu0/dstat-graph
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlinechart.go
119 lines (112 loc) · 2.83 KB
/
linechart.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package graph
import(
"io"
"os"
"time"
"fmt"
"github.com/wcharczuk/go-chart"
)
type LineChart struct {
filterColumns []string
graph chart.Chart
width int
height int
}
func NewLineChart(columns []string, width, height int) *LineChart {
c := new(LineChart)
c.filterColumns = columns
c.width = width
c.height = height
return c
}
func (c *LineChart) interval(values []time.Time, interval int) []chart.GridLine {
t := make([]chart.GridLine, 0)
freq := len(values) / interval
for i := 0; i < len(values); i += freq {
t = append(t, chart.GridLine{
Value: float64(values[i].UnixNano()),
})
}
return t
}
func (c *LineChart) Read(r io.Reader) error {
columns, rows, err := Parse(r)
if err != nil {
return err
}
targetColumns := c.filterColumns
if len(c.filterColumns) < 1 {
targetColumns = columns
}
columnExists := make(map[string]bool)
for _, k := range columns {
columnExists[k] = true
}
filterCols := make([]string, 0)
for _, k := range targetColumns {
if columnExists[k] {
filterCols = append(filterCols, k)
}
}
xvalues := make([]time.Time, 0, len(rows))
for _, row := range rows {
xvalues = append(xvalues, row.Time)
}
series := make([]chart.Series, 0, len(filterCols))
for i, col := range filterCols {
yvalues := make([]float64, 0, len(rows))
for _, row := range rows {
if value, ok := row.Values[col]; ok == true {
yvalues = append(yvalues, value)
}
}
idx := i % len(chart.DefaultAlternateColors)
color := chart.DefaultAlternateColors[idx]
series = append(series, chart.TimeSeries{
Name: col,
Style: chart.Style{
StrokeColor: color,
FillColor: color.WithAlpha(15),
},
XValues: xvalues,
YValues: yvalues,
})
}
c.graph = chart.Chart{
Width: c.width,
Height: c.height,
Background: chart.Style{
Padding: chart.Box {
Top: 50,
},
},
YAxis: chart.YAxis{
ValueFormatter: func(v interface{}) string {
return fmt.Sprintf("%3.2f", v.(float64))
},
},
XAxis: chart.XAxis{
ValueFormatter: func(v interface{}) string {
format := "01-02 03:04:05"
if t, isTime := v.(time.Time); isTime {
return t.Format(format)
}
if t, isFloat := v.(float64); isFloat {
return time.Unix(0, int64(t)).Format(format)
}
return fmt.Sprintf("<unknown_axis>: %#v", v)
},
GridMajorStyle: chart.Style{
StrokeColor: chart.ColorAlternateGray,
StrokeWidth: 2.0,
},
GridLines: c.interval(xvalues, 10),
},
Series: series,
}
return nil
}
func (c *LineChart) RenderToFile(f *os.File) error {
c.graph.Elements = []chart.Renderable{chart.LegendThin(&c.graph)}
return c.graph.Render(chart.PNG, f)
}