Skip to content

Commit

Permalink
Merge pull request #176 from K-Phoen/gauge-panel
Browse files Browse the repository at this point in the history
Support "gauge" panels
  • Loading branch information
K-Phoen authored Aug 14, 2022
2 parents 0848f21 + ed60536 commit fba78ff
Show file tree
Hide file tree
Showing 16 changed files with 920 additions and 26 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ docker-push-manager: ## Push docker image with the manager.
--platform linux/arm64,linux/arm/v7,linux/arm/v8,linux/amd64 \
--push \
-f build/Dockerfile-controller \
-t ${CONTROLLER_IMAGE}:latest \
-t ${CONTROLLER_IMAGE}:${VERSION} .

.PHONY: docker-push-converter
Expand All @@ -166,6 +167,7 @@ docker-push-converter: ## Push docker image with the converter.
--platform linux/arm64,linux/arm/v7,linux/arm/v8,linux/amd64 \
--push \
-f build/Dockerfile-converter \
-t ${CONVERTER_IMAGE}:latest \
-t ${CONVERTER_IMAGE}:${VERSION} .

.PHONY: docker-push
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module github.com/K-Phoen/dark
go 1.17

require (
github.com/K-Phoen/grabana v0.21.11
github.com/K-Phoen/sdk v0.11.1
github.com/K-Phoen/grabana v0.21.12
github.com/K-Phoen/sdk v0.12.0
github.com/go-logr/logr v1.2.2
github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.17.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/K-Phoen/grabana v0.21.11 h1:eEuHM3ce4x2lrKH7ivu5p/NI2i4LcQFBSx6LcXgP2Js=
github.com/K-Phoen/grabana v0.21.11/go.mod h1:6uqhrx00CKcGuD26aJMA1vvfytyworzLcVLmVnHltrg=
github.com/K-Phoen/sdk v0.11.1 h1:kzuOW7AzDLdI2rghGyqTiv01czadrzeL4m96TQrRC2A=
github.com/K-Phoen/sdk v0.11.1/go.mod h1:wp7qXARaIhCYktmoOjRZ+TDMlek5nbayC+waN7vigxI=
github.com/K-Phoen/grabana v0.21.12 h1:BZ9s7n/jD8gzoPeC7v7RFrnl1UB31l7G5h6mJmxckrw=
github.com/K-Phoen/grabana v0.21.12/go.mod h1:kL0drTF9oZu0r24fYoiGYJrxP+jBJKIcbR66TE5gKEU=
github.com/K-Phoen/sdk v0.12.0 h1:+0QqHoDZbO6zetFMggM3zKF48GKRu744Ycc9w4oyY0E=
github.com/K-Phoen/sdk v0.12.0/go.mod h1:wp7qXARaIhCYktmoOjRZ+TDMlek5nbayC+waN7vigxI=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
Expand Down
131 changes: 131 additions & 0 deletions internal/pkg/converter/gauge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package converter

import (
grabana "github.com/K-Phoen/grabana/decoder"
"github.com/K-Phoen/sdk"
"go.uber.org/zap"
)

func (converter *JSON) convertGauge(panel sdk.Panel) grabana.DashboardPanel {
gauge := &grabana.DashboardGauge{
Title: panel.Title,
Span: panelSpan(panel),
Unit: panel.GaugePanel.FieldConfig.Defaults.Unit,
Decimals: panel.GaugePanel.FieldConfig.Defaults.Decimals,
Transparent: panel.Transparent,
Orientation: converter.convertGaugeOrientation(panel),
ValueType: converter.convertGaugeValueType(panel),
ThresholdMode: converter.convertGaugeThresholdMode(panel),
Thresholds: converter.convertGaugeThresholds(panel),
}

if panel.GaugePanel.Options.Text != nil {
gauge.ValueFontSize = panel.GaugePanel.Options.Text.ValueSize
gauge.TitleFontSize = panel.GaugePanel.Options.Text.TitleSize
}

if panel.Description != nil {
gauge.Description = *panel.Description
}
if panel.Repeat != nil {
gauge.Repeat = *panel.Repeat
}
if panel.Height != nil {
gauge.Height = *(panel.Height).(*string)
}
if panel.Datasource != nil {
gauge.Datasource = panel.Datasource.LegacyName
}
if len(panel.Links) != 0 {
gauge.Links = converter.convertPanelLinks(panel.Links)
}

for _, target := range panel.GaugePanel.Targets {
graphTarget := converter.convertTarget(target)
if graphTarget == nil {
continue
}

gauge.Targets = append(gauge.Targets, *graphTarget)
}

return grabana.DashboardPanel{Gauge: gauge}
}

func (converter *JSON) convertGaugeValueType(panel sdk.Panel) string {
if len(panel.GaugePanel.Options.ReduceOptions.Calcs) != 1 {
return "last_non_null"
}

valueType := panel.GaugePanel.Options.ReduceOptions.Calcs[0]

switch valueType {
case "first":
return "first"
case "firstNotNull":
return "first_non_null"
case "last":
return "last"
case "lastNotNull":
return "last_non_null"

case "min":
return "min"
case "max":
return "max"
case "mean":
return "avg"

case "count":
return "count"
case "sum":
return "total"
case "range":
return "range"

default:
converter.logger.Warn("unknown value type", zap.String("value type", valueType))
return "last_non_null"
}
}

func (converter *JSON) convertGaugeOrientation(panel sdk.Panel) string {
switch panel.GaugePanel.Options.Orientation {
case "":
return "auto"
case "horizontal":
return "horizontal"
case "vertical":
return "vertical"
default:
converter.logger.Warn("unknown orientation", zap.String("orientation", panel.StatPanel.Options.Orientation))
return "auto"
}
}

func (converter *JSON) convertGaugeThresholdMode(panel sdk.Panel) string {
switch panel.GaugePanel.FieldConfig.Defaults.Thresholds.Mode {
case "":
return "absolute"
case "absolute":
return "absolute"
case "percentage":
return "relative"
default:
converter.logger.Warn("unknown threshold mode", zap.String("mode", panel.GaugePanel.FieldConfig.Defaults.Thresholds.Mode))
return "absolute"
}
}

func (converter *JSON) convertGaugeThresholds(panel sdk.Panel) []grabana.GaugeThresholdStep {
steps := make([]grabana.GaugeThresholdStep, 0, len(panel.GaugePanel.FieldConfig.Defaults.Thresholds.Steps))

for _, step := range panel.GaugePanel.FieldConfig.Defaults.Thresholds.Steps {
steps = append(steps, grabana.GaugeThresholdStep{
Color: step.Color,
Value: step.Value,
})
}

return steps
}
85 changes: 85 additions & 0 deletions internal/pkg/converter/gauge_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package converter

import (
"testing"

"github.com/K-Phoen/sdk"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
)

func TestConvertGaugePanel(t *testing.T) {
req := require.New(t)

converter := NewJSON(zap.NewNop())
height := "200px"
datasource := "prometheus"

gaugePanel := sdk.Panel{
CommonPanel: sdk.CommonPanel{
Title: "Gauge panel",
Description: strPtr("panel desc"),
Type: "gauge",
Transparent: true,
Height: &height,
Datasource: &sdk.DatasourceRef{LegacyName: datasource},
},
GaugePanel: &sdk.GaugePanel{
Targets: []sdk.Target{
{
Expr: "sum(kube_pod_info{}) / sum(kube_node_status_allocatable{resource=\"pods\"})",
},
},
Options: sdk.StatOptions{
Orientation: "horizontal",
ReduceOptions: sdk.ReduceOptions{
Calcs: []string{"last"},
},
Text: &sdk.TextOptions{
ValueSize: 10,
TitleSize: 20,
},
},
FieldConfig: sdk.FieldConfig{
Defaults: sdk.FieldConfigDefaults{
Unit: "none",
Thresholds: sdk.Thresholds{},
},
},
},
}

converted, ok := converter.convertDataPanel(gaugePanel)

req.True(ok)
req.True(converted.Gauge.Transparent)
req.Equal("Gauge panel", converted.Gauge.Title)
req.Equal("panel desc", converted.Gauge.Description)
req.Equal("none", converted.Gauge.Unit)
req.Equal("last", converted.Gauge.ValueType)
req.Equal("horizontal", converted.Gauge.Orientation)
req.Equal(10, converted.Gauge.ValueFontSize)
req.Equal(20, converted.Gauge.TitleFontSize)
req.Equal(height, converted.Gauge.Height)
req.Equal(datasource, converted.Gauge.Datasource)
}

func TestConvertGaugeLinks(t *testing.T) {
req := require.New(t)

converter := NewJSON(zap.NewNop())
sdkPanel := sdk.NewGauge("")
sdkPanel.Links = []sdk.Link{
{Title: "stat title", URL: strPtr("stat url")},
}

converted, ok := converter.convertDataPanel(*sdkPanel)

req.True(ok)
req.NotNil(converted.Gauge)

panel := converted.Gauge
req.Len(panel.Links, 1)
req.Equal("stat title", panel.Links[0].Title)
req.Equal("stat url", panel.Links[0].URL)
}
2 changes: 2 additions & 0 deletions internal/pkg/converter/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ func (converter *JSON) convertDataPanel(panel sdk.Panel) (grabana.DashboardPanel
return converter.convertText(panel), true
case "timeseries":
return converter.convertTimeSeries(panel), true
case "gauge":
return converter.convertGauge(panel), true
default:
converter.logger.Warn("unhandled panel type: skipped", zap.String("type", panel.Type), zap.String("title", panel.Title))
}
Expand Down
9 changes: 7 additions & 2 deletions internal/pkg/converter/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ func (converter *JSON) convertStat(panel sdk.Panel) grabana.DashboardPanel {
Unit: panel.StatPanel.FieldConfig.Defaults.Unit,
Decimals: panel.StatPanel.FieldConfig.Defaults.Decimals,
Transparent: panel.Transparent,
ValueFontSize: panel.StatPanel.Options.Text.ValueSize,
TitleFontSize: panel.StatPanel.Options.Text.TitleSize,
Orientation: converter.convertStatOrientation(panel),
Text: converter.convertStatTextMode(panel),
ValueType: converter.convertStatValueType(panel),
Expand All @@ -23,6 +21,11 @@ func (converter *JSON) convertStat(panel sdk.Panel) grabana.DashboardPanel {
Thresholds: converter.convertStatThresholds(panel),
}

if panel.StatPanel.Options.Text != nil {
stat.ValueFontSize = panel.StatPanel.Options.Text.ValueSize
stat.TitleFontSize = panel.StatPanel.Options.Text.TitleSize
}

if panel.Description != nil {
stat.Description = *panel.Description
}
Expand Down Expand Up @@ -129,6 +132,8 @@ func (converter *JSON) convertStatColorMode(panel sdk.Panel) string {
return "background"
case "value":
return "value"
case "none":
return "none"
default:
converter.logger.Warn("unknown color mode", zap.String("color_mode", panel.StatPanel.Options.ColorMode))
return "value"
Expand Down
7 changes: 6 additions & 1 deletion internal/pkg/converter/variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,12 @@ func (converter *JSON) convertQueryVar(variable sdk.TemplateVar, dashboard *grab
}

if variable.Query != nil {
query.Request = variable.Query.(string)
if request, ok := variable.Query.(string); ok {
query.Request = request
}
if request, ok := variable.Query.(map[string]interface{}); ok {
query.Request = request["query"].(string)
}
}

dashboard.Variables = append(dashboard.Variables, grabana.DashboardVariable{Query: query})
Expand Down
4 changes: 4 additions & 0 deletions vendor/github.com/K-Phoen/grabana/decoder/dashboard.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fba78ff

Please sign in to comment.