Skip to content

Commit

Permalink
update: external chart svg mode
Browse files Browse the repository at this point in the history
  • Loading branch information
minoic committed Jun 6, 2024
1 parent ba2eb5d commit f78d0d3
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 34 deletions.
10 changes: 3 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/gorcon/rcon v1.3.4
github.com/gotify/go-api-client/v2 v2.0.4
github.com/influxdata/influxdb-client-go/v2 v2.12.3
github.com/jellydator/ttlcache/v2 v2.11.1
github.com/matcornic/hermes v1.2.0
github.com/minoic/PterodactylGoApi v0.2.4
github.com/minoic/bt-go-sdk v0.1.17
Expand All @@ -28,6 +29,7 @@ require (
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/soheilhy/cmux v0.1.5
github.com/spf13/cast v1.5.1
github.com/stretchr/testify v1.9.0
github.com/v2fly/v2ray-core/v5 v5.4.1
github.com/xhit/go-simple-mail/v2 v2.16.0
go.mongodb.org/mongo-driver v1.12.1
Expand All @@ -52,7 +54,6 @@ require (
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Masterminds/sprig v2.22.0+incompatible // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/chromedp/cdproto v0.0.0-20231011050154-1d073bb38998 // indirect
Expand All @@ -73,7 +74,6 @@ require (
github.com/goccy/go-json v0.10.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gomodule/redigo v1.8.9 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
Expand All @@ -84,23 +84,20 @@ require (
github.com/huandu/xstrings v1.3.3 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect
github.com/jellydator/ttlcache/v2 v2.11.1 // indirect
github.com/jhump/protoreflect v1.15.1 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/memcachier/mc/v3 v3.0.3 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pborman/uuid v1.2.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pion/dtls/v2 v2.2.7 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/toorop/go-dkim v0.0.0-20201103131630-e1cd1a0a5208 // indirect
Expand All @@ -126,7 +123,6 @@ require (
github.com/docker/docker v24.0.7+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/gin-contrib/cache v1.3.0
github.com/gin-contrib/gzip v1.0.1
github.com/gin-gonic/gin v1.9.1
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb // indirect
Expand Down Expand Up @@ -167,7 +163,7 @@ require (
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a
github.com/yusufpapurcu/wmi v1.2.3 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sync v0.3.0
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
gotest.tools/v3 v3.4.0 // indirect
Expand Down
8 changes: 0 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ github.com/avast/retry-go/v4 v4.5.1 h1:AxIx0HGi4VZ3I02jr78j5lZ3M6x1E0Ivxa6b0pUUh
github.com/avast/retry-go/v4 v4.5.1/go.mod h1:/sipNsvNB3RRuT5iNcb6h73nw3IBmXJ/H3XrCQYSOpc=
github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI=
github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
Expand Down Expand Up @@ -124,8 +122,6 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/cache v1.3.0 h1:wEEw38uvb4rTraQJVpd9ex4ZotXNlc0fSaSUsuPXS/w=
github.com/gin-contrib/cache v1.3.0/go.mod h1:EA63LrWGI5vwSI95TS5fgBrtxZ1tM2NKx+NrEeyEDcU=
github.com/gin-contrib/gzip v1.0.1 h1:HQ8ENHODeLY7a4g1Au/46Z92bdGFl74OhxcZble9WJE=
github.com/gin-contrib/gzip v1.0.1/go.mod h1:njt428fdUNRvjuJf16tZMYZ2Yl+WQB53X5wmhDwXvC4=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
Expand Down Expand Up @@ -369,8 +365,6 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/memcachier/mc/v3 v3.0.3 h1:qii+lDiPKi36O4Xg+HVKwHu6Oq+Gt17b+uEiA0Drwv4=
github.com/memcachier/mc/v3 v3.0.3/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug=
github.com/minoic/PterodactylGoApi v0.2.4 h1:s4uiMuEWaQQCVhvyYwS0hVjbNcJUBOSwtrQlr0IKaZs=
github.com/minoic/PterodactylGoApi v0.2.4/go.mod h1:tzn9Uk2bZgJz3iveGsT3JTESXNGXK3AYclkLIrbiIWg=
github.com/minoic/bt-go-sdk v0.1.17 h1:UY4xc6ovR7x29SmonAYXZDY0H4oA2gq7+ucey1lSRZo=
Expand Down Expand Up @@ -479,8 +473,6 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 h1:pyecQtsPmlkCsMkYhT5iZ+sUXuwee+OvfuJjinEA3ko=
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62/go.mod h1:65XQgovT59RWatovFwnwocoUxiI/eENTnOY5GK3STuY=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rumblefrog/go-a2s v1.0.2 h1:rT/QP/B+h2R9/3PEfmOkWPdHnEKExskOMPTTkeX+vuA=
Expand Down
40 changes: 26 additions & 14 deletions modules/backend/app/web/render/chart_png.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ const (
FileProtocol = "file://"
EchartsInstanceDom = "div[_echarts_instance_]"
CanvasJs = "echarts.getInstanceByDom(document.querySelector('div[_echarts_instance_]'))" +
".getDataURL({type: '%s', pixelRatio: %d, excludeComponents: ['toolbox']})"
".getDataURL({type: '%s', pixelRatio: 1, excludeComponents: ['toolbox']})"
SvgJs = "echarts.getInstanceByDom(document.querySelector('div[_echarts_instance_]')).renderToSVGString()"
)

type SnapshotConfig struct {
// RenderContent the content bytes of charts after rendered
RenderContent []byte
// Quality the generated image quality, aka pixelRatio
Quality int
// KeepHtml whether keep the generated html also, default false
KeepHtml bool
// Timeout the timeout config
Expand All @@ -38,7 +37,6 @@ type SnapshotConfigOption func(config *SnapshotConfig)
func NewSnapshotConfig(content []byte, opts ...SnapshotConfigOption) *SnapshotConfig {
config := &SnapshotConfig{
RenderContent: content,
Quality: 1,
KeepHtml: false,
Timeout: 0,
ExtName: "png",
Expand All @@ -60,9 +58,14 @@ func MakeChartSnapshotJpg(content []byte) ([]byte, error) {
return makeSnapshot(conf)
}

func MakeChartSnapshotSvg(content []byte) ([]byte, error) {
conf := NewSnapshotConfig(content)
conf.ExtName = "svg"
return makeSnapshot(conf)
}

func makeSnapshot(config *SnapshotConfig) ([]byte, error) {
content := config.RenderContent
quality := config.Quality
keepHtml := config.KeepHtml
timeout := config.Timeout

Expand Down Expand Up @@ -95,26 +98,35 @@ func makeSnapshot(config *SnapshotConfig) ([]byte, error) {
return nil, err
}

if quality < 1 {
quality = 1
var executeJS string

switch config.ExtName {
case "jpg":
executeJS = fmt.Sprintf(CanvasJs, config.ExtName)
case "png":
executeJS = fmt.Sprintf(CanvasJs, config.ExtName)
case "svg":
executeJS = SvgJs
}

var base64Data string
executeJS := fmt.Sprintf(CanvasJs, config.ExtName, quality)
var imgData string

err = chromedp.Run(ctx,
chromedp.Navigate(fmt.Sprintf("%s%s", FileProtocol, htmlFullPath)),
chromedp.WaitVisible(EchartsInstanceDom, chromedp.ByQuery),
chromedp.Evaluate(executeJS, &base64Data),
chromedp.Evaluate(executeJS, &imgData),
)
if err != nil {
return nil, err
}

imgContent, err := base64.StdEncoding.DecodeString(strings.Split(base64Data, ",")[1])
if err != nil {
return nil, err
if config.ExtName == "jpg" || config.ExtName == "png" {
imgContent, err := base64.StdEncoding.DecodeString(strings.Split(imgData, ",")[1])
if err != nil {
return nil, err
}
imgData = string(imgContent)
}

return imgContent, nil
return []byte(imgData), nil
}
1 change: 1 addition & 0 deletions modules/backend/app/web/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func ServeWeb(ctx context.Context, lis net.Listener) {
chartsRouter.GET(":id/response-time.html", services.ResponseTimeChart(services.ResponseTimeChartModeHtml))
chartsRouter.GET(":id/response-time.png", services.ResponseTimeChart(services.ResponseTimeChartModePng))
chartsRouter.GET(":id/response-time.jpg", services.ResponseTimeChart(services.ResponseTimeChartModeJpg))
chartsRouter.GET(":id/response-time.svg", services.ResponseTimeChart(services.ResponseTimeChartModeSvg))
}
sentrySingletonRouter := apiRouter.Group("sentry-singleton")
{
Expand Down
41 changes: 36 additions & 5 deletions modules/backend/app/web/services/charts.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const (
ResponseTimeChartModeHtml ResponseTimeChartMode = iota
ResponseTimeChartModePng
ResponseTimeChartModeJpg
ResponseTimeChartModeSvg
)

func ResponseTimeChart(mode ResponseTimeChartMode) gin.HandlerFunc {
Expand All @@ -46,9 +47,15 @@ func ResponseTimeChart(mode ResponseTimeChartMode) gin.HandlerFunc {
return
}

if mode != ResponseTimeChartModeHtml {
req.Animation = false
switch mode {
case ResponseTimeChartModeHtml:
case ResponseTimeChartModeJpg:
fallthrough
case ResponseTimeChartModePng:
req.Renderer = "canvas"
req.Animation = false
case ResponseTimeChartModeSvg:
req.Renderer = "svg"
}

loc, err := time.LoadLocation(req.Timezone)
Expand Down Expand Up @@ -89,11 +96,13 @@ from(bucket: "backend")
var values []opts.LineData
var times []string
var maxValue float64
var lastValue float64
for query.Next() {
f := cast.ToFloat64(query.Record().Value())
lastValue = f
maxValue = math.Max(maxValue, f)
values = append(values, opts.LineData{Value: cast.ToFloat64(query.Record().Value())})
times = append(times, query.Record().Time().In(loc).Format(time.DateTime))
times = append(times, query.Record().Time().In(loc).Format("01/02 15:04:05"))
}
line := charts.NewLine()
line.Animation = opts.Bool(req.Animation)
Expand All @@ -102,15 +111,24 @@ from(bucket: "backend")
PageTitle: fmt.Sprintf("Bellis | Response Time - %s", entity.Name),
Renderer: req.Renderer,
}),
charts.WithLegendOpts(opts.Legend{
Type: "plain",
Show: opts.Bool(true),
Left: "right",
}),
charts.WithTitleOpts(opts.Title{
Title: "Response Time",
Subtitle: "Time taken to obtain the application running status",
Show: opts.Bool(true),
Title: fmt.Sprintf("Response Time - %s (%.2f ms)", entity.Name, lastValue),
Subtitle: fmt.Sprintf("Scheme: %s | CreatedAt: %s %s", entity.Scheme, entity.CreatedAt.In(loc).Format(time.DateTime), loc.String()),
}),
charts.WithTooltipOpts(opts.Tooltip{
Show: opts.Bool(true),
Trigger: "axis",
TriggerOn: "mousemove",
ValueFormatter: string(opts.FuncOpts("(data)=>`${data.toFixed(2)} ms`")),
AxisPointer: &opts.AxisPointer{
Type:"line",
},
}),
charts.WithYAxisOpts(opts.YAxis{
Max: math.Max(maxValue, 100.0),
Expand All @@ -130,6 +148,7 @@ from(bucket: "backend")
case ResponseTimeChartModeHtml:
line.Render(ctx.Writer)
ctx.Status(http.StatusOK)
ctx.Writer.Header().Set("content-type", "text/html; charset=utf-8")
case ResponseTimeChartModePng:
line.BackgroundColor = "#FFFFFF"
bts, err := render.MakeChartSnapshotPng(line.RenderContent())
Expand All @@ -140,6 +159,7 @@ from(bucket: "backend")
}
ctx.Writer.Write(bts)
ctx.Status(http.StatusOK)
ctx.Writer.Header().Set("content-type", "image/png")
case ResponseTimeChartModeJpg:
line.BackgroundColor = "#FFFFFF"
bts, err := render.MakeChartSnapshotJpg(line.RenderContent())
Expand All @@ -150,6 +170,17 @@ from(bucket: "backend")
}
ctx.Writer.Write(bts)
ctx.Status(http.StatusOK)
ctx.Writer.Header().Set("content-type", "image/jpeg")
case ResponseTimeChartModeSvg:
bts, err := render.MakeChartSnapshotSvg(line.RenderContent())
if err != nil {
glgf.Error(err)
ctx.Status(http.StatusInternalServerError)
break
}
ctx.Writer.Write(bts)
ctx.Status(http.StatusOK)
ctx.Writer.Header().Set("content-type", "image/svg+xml")
default:
glgf.Error("invalid chart mode: ", mode)
ctx.Status(http.StatusInternalServerError)
Expand Down

0 comments on commit f78d0d3

Please sign in to comment.