bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/cmd/bosun/sched/chart.go (about)

     1  package sched
     2  
     3  import (
     4  	"image"
     5  	"image/color"
     6  	"image/png"
     7  	"io"
     8  
     9  	"bosun.org/cmd/bosun/expr"
    10  	"github.com/MiniProfiler/go/miniprofiler"
    11  	"github.com/ajstarks/svgo"
    12  	"github.com/bradfitz/slice"
    13  	"github.com/vdobler/chart"
    14  	"github.com/vdobler/chart/imgg"
    15  	"github.com/vdobler/chart/svgg"
    16  )
    17  
    18  var chartColors = []color.Color{
    19  	color.NRGBA{0x37, 0x7e, 0xb8, 0xff},
    20  	color.NRGBA{0x4d, 0xaf, 0x4a, 0xff},
    21  	color.NRGBA{0x98, 0x4e, 0xa3, 0xff},
    22  	color.NRGBA{0xff, 0x7f, 0x00, 0xff},
    23  	color.NRGBA{0xa6, 0x56, 0x28, 0xff},
    24  	color.NRGBA{0xf7, 0x81, 0xbf, 0xff},
    25  	color.NRGBA{0x99, 0x99, 0x99, 0xff},
    26  	color.NRGBA{0xe4, 0x1a, 0x1c, 0xff},
    27  }
    28  
    29  // Autostyle styles a chart series.
    30  func Autostyle(i int) chart.Style {
    31  	c := chartColors[i%len(chartColors)]
    32  	s := chart.Symbol[i%len(chart.Symbol)]
    33  	return chart.Style{
    34  		Symbol:      s,
    35  		SymbolSize:  .5,
    36  		SymbolColor: c,
    37  		LineStyle:   chart.SolidLine,
    38  		LineWidth:   1,
    39  		LineColor:   c,
    40  	}
    41  }
    42  
    43  var white = color.RGBA{0xff, 0xff, 0xff, 0xff}
    44  
    45  func (s *Schedule) ExprSVG(t miniprofiler.Timer, w io.Writer, width, height int, unit string, res []*expr.Result) error {
    46  	ch, err := s.ExprGraph(t, unit, res)
    47  	if err != nil {
    48  		return err
    49  	}
    50  	g := svg.New(w)
    51  	g.StartviewUnit(100, 100, "%", 0, 0, width, height)
    52  	g.Rect(0, 0, width, height, "fill: #ffffff")
    53  	sgr := svgg.AddTo(g, 0, 0, width, height, "", 12, white)
    54  	ch.Plot(sgr)
    55  	g.End()
    56  	return nil
    57  }
    58  
    59  func (s *Schedule) ExprPNG(t miniprofiler.Timer, w io.Writer, width, height int, unit string, res []*expr.Result) error {
    60  	ch, err := s.ExprGraph(t, unit, res)
    61  	if err != nil {
    62  		return err
    63  	}
    64  	g := image.NewRGBA(image.Rectangle{Min: image.ZP, Max: image.Pt(width, height)})
    65  	sgr := imgg.AddTo(g, 0, 0, width, height, white, nil, nil)
    66  	ch.Plot(sgr)
    67  	return png.Encode(w, g)
    68  }
    69  
    70  func (s *Schedule) ExprGraph(t miniprofiler.Timer, unit string, res []*expr.Result) (chart.Chart, error) {
    71  	c := chart.ScatterChart{
    72  		Key:    chart.Key{Pos: "itl"},
    73  		YRange: chart.Range{Label: unit},
    74  	}
    75  	c.XRange.Time = true
    76  	for ri, r := range res {
    77  		rv := r.Value.(expr.Series)
    78  		pts := make([]chart.EPoint, len(rv))
    79  		idx := 0
    80  		for k, v := range rv {
    81  			pts[idx].X = float64(k.Unix())
    82  			pts[idx].Y = v
    83  			idx++
    84  		}
    85  		slice.Sort(pts, func(i, j int) bool {
    86  			return pts[i].X < pts[j].X
    87  		})
    88  		c.AddData(r.Group.String(), pts, chart.PlotStyleLinesPoints, Autostyle(ri))
    89  	}
    90  	return &c, nil
    91  }