Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support graph override series #94

Merged
merged 3 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions dashboard/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"testing"

"github.com/K-Phoen/grabana/variable/datasource"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -155,6 +156,14 @@ func TestDashboardCanHaveVariablesAsQuery(t *testing.T) {
req.Len(panel.board.Templating.List, 1)
}

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

panel := New("", VariableAsDatasource("source", datasource.Type("prometheus")))

req.Len(panel.board.Templating.List, 1)
}

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

Expand Down
8 changes: 4 additions & 4 deletions decoder/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,7 @@ variables:
"query": "10m,12h,1h,1m,30m,30s,5m,6h",
"regex": "",
"current": {
"text": "30s",
"text": ["30s"],
"value": "30s"
},
"label": "Interval",
Expand All @@ -494,7 +494,7 @@ variables:
"query": "label_values(prometheus_http_requests_total, code)",
"regex": "",
"current": {
"text": "All",
"text": ["All"],
"value": "$__all"
},
"label": "HTTP status",
Expand All @@ -521,7 +521,7 @@ variables:
"query": "50",
"regex": "",
"current": {
"text": "50th",
"text": ["50th"],
"value": "50"
},
"label": "Percentile",
Expand All @@ -548,7 +548,7 @@ variables:
"query": "v1",
"regex": "",
"current": {
"text": "v1",
"text": ["v1"],
"value": "v1"
},
"label": "vX",
Expand Down
43 changes: 41 additions & 2 deletions decoder/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/K-Phoen/grabana/alert"
"github.com/K-Phoen/grabana/axis"
"github.com/K-Phoen/grabana/graph"
"github.com/K-Phoen/grabana/graph/series"
"github.com/K-Phoen/grabana/row"
)

Expand Down Expand Up @@ -86,9 +87,43 @@ func (graphPanel DashboardGraph) toOption() (row.Option, error) {
return row.WithGraph(graphPanel.Title, opts...), nil
}

type GraphSeriesOverride struct {
Alias string
Color string `yaml:",omitempty"`
Dashes *bool `yaml:",omitempty"`
Lines *bool `yaml:",omitempty"`
Fill *int `yaml:",omitempty"`
LineWidth *int `yaml:"line_width,omitempty"`
}

func (override *GraphSeriesOverride) toOption() graph.Option {
overrideOpts := []series.OverrideOption{
series.Alias(override.Alias),
}

if override.Color != "" {
overrideOpts = append(overrideOpts, series.Color(override.Color))
}
if override.Dashes != nil {
overrideOpts = append(overrideOpts, series.Dashes(*override.Dashes))
}
if override.Lines != nil {
overrideOpts = append(overrideOpts, series.Dashes(*override.Lines))
}
if override.Fill != nil {
overrideOpts = append(overrideOpts, series.Fill(*override.Fill))
}
if override.LineWidth != nil {
overrideOpts = append(overrideOpts, series.LineWidth(*override.LineWidth))
}

return graph.SeriesOverride(overrideOpts...)
}

type GraphVisualization struct {
NullValue string `yaml:",omitempty"`
Staircase bool `yaml:",omitempty"`
NullValue string `yaml:",omitempty"`
Staircase bool `yaml:",omitempty"`
Overrides []GraphSeriesOverride `yaml:"overrides,omitempty"`
}

func (graphViz *GraphVisualization) toOptions() []graph.Option {
Expand All @@ -115,6 +150,10 @@ func (graphViz *GraphVisualization) toOptions() []graph.Option {
opts = append(opts, graph.Staircase())
}

for _, override := range graphViz.Overrides {
opts = append(opts, override.toOption())
}

return opts
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.13

require (
github.com/gosimple/slug v1.9.0 // indirect
github.com/grafana-tools/sdk v0.0.0-20210301100910-d23004341fc8
github.com/grafana-tools/sdk v0.0.0-20210402150123-f7c763c3738c
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.4.0
gopkg.in/yaml.v2 v2.4.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ github.com/gosimple/slug v1.1.1 h1:fRu/digW+NMwBIP+RmviTK97Ho/bEj/C9swrCspN3D4=
github.com/gosimple/slug v1.1.1/go.mod h1:ER78kgg1Mv0NQGlXiDe57DpCyfbNywXXZ9mIorhxAf0=
github.com/gosimple/slug v1.9.0 h1:r5vDcYrFz9BmfIAMC829un9hq7hKM4cHUrsv36LbEqs=
github.com/gosimple/slug v1.9.0/go.mod h1:AMZ+sOVe65uByN3kgEyf9WEBKBCSS+dJjMX9x4vDJbg=
github.com/grafana-tools/sdk v0.0.0-20210301100910-d23004341fc8 h1:f9VavpwL1aGRC9/Ka3DIYaad6y7SXRpShytH1MAcYYE=
github.com/grafana-tools/sdk v0.0.0-20210301100910-d23004341fc8/go.mod h1:uby+6hPUCRVNG/iAZKCOlaq5YhyK0oKMRke+FDesZdw=
github.com/grafana-tools/sdk v0.0.0-20210402150123-f7c763c3738c h1:PxbQpT+CoC6wo0Nc8z7KAzeDu455FfLnqsZXRBpFWOA=
github.com/grafana-tools/sdk v0.0.0-20210402150123-f7c763c3738c/go.mod h1:uby+6hPUCRVNG/iAZKCOlaq5YhyK0oKMRke+FDesZdw=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
Expand Down
15 changes: 15 additions & 0 deletions graph/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package graph
import (
"github.com/K-Phoen/grabana/alert"
"github.com/K-Phoen/grabana/axis"
"github.com/K-Phoen/grabana/graph/series"
"github.com/K-Phoen/grabana/target/graphite"
"github.com/K-Phoen/grabana/target/influxdb"
"github.com/K-Phoen/grabana/target/prometheus"
Expand Down Expand Up @@ -274,6 +275,20 @@ func Null(mode NullValue) Option {
}
}

// SeriesOverride configures how null values are displayed.
// See https://grafana.com/docs/grafana/latest/panels/field-options/
func SeriesOverride(opts ...series.OverrideOption) Option {
return func(graph *Graph) {
override := sdk.SeriesOverride{}

for _, opt := range opts {
opt(&override)
}

graph.Builder.GraphPanel.SeriesOverrides = append(graph.Builder.GraphPanel.SeriesOverrides, override)
}
}

// Legend defines what should be shown in the legend.
func Legend(opts ...LegendOption) Option {
return func(graph *Graph) {
Expand Down
10 changes: 10 additions & 0 deletions graph/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package graph
import (
"testing"

"github.com/K-Phoen/grabana/graph/series"

"github.com/K-Phoen/grabana/axis"
"github.com/K-Phoen/grabana/target/stackdriver"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -260,3 +262,11 @@ func TestLegendCanHideNullSeries(t *testing.T) {

req.True(panel.Builder.GraphPanel.Legend.HideEmpty)
}

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

panel := New("", SeriesOverride(series.Alias("series"), series.Color("red")))

req.Len(panel.Builder.GraphPanel.SeriesOverrides, 1)
}
48 changes: 48 additions & 0 deletions graph/series/override.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package series

import (
"github.com/grafana-tools/sdk"
)

// OverrideOption represents an option that can be used alter a graph panel series.
type OverrideOption func(series *sdk.SeriesOverride)

// Alis defines an alias/regex used to identify the series to override.
func Alias(alias string) OverrideOption {
return func(series *sdk.SeriesOverride) {
series.Alias = alias
}
}

// Color overrides the color for the matched series.
func Color(color string) OverrideOption {
return func(series *sdk.SeriesOverride) {
series.Color = &color
}
}

// Dashes enables/disables display of the series using dashes instead of lines.
func Dashes(enabled bool) OverrideOption {
return func(series *sdk.SeriesOverride) {
series.Dashes = &enabled
}
}

// Lines enables/disables display of the series using dashes instead of dashes.
func Lines(enabled bool) OverrideOption {
return func(series *sdk.SeriesOverride) {
series.Lines = &enabled
}
}

func Fill(opacity int) OverrideOption {
return func(series *sdk.SeriesOverride) {
series.Fill = &opacity
}
}

func LineWidth(width int) OverrideOption {
return func(series *sdk.SeriesOverride) {
series.LineWidth = &width
}
}
67 changes: 67 additions & 0 deletions graph/series/override_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package series

import (
"testing"

"github.com/grafana-tools/sdk"
"github.com/stretchr/testify/require"
)

func TestAliasCanBeDefined(t *testing.T) {
req := require.New(t)
series := &sdk.SeriesOverride{}

Alias("Error - .*")(series)

req.Equal("Error - .*", series.Alias)
}

func TestColorCanBeDefined(t *testing.T) {
req := require.New(t)
series := &sdk.SeriesOverride{}

Color("#65c5db")(series)

req.NotNil(series.Color)
req.Equal("#65c5db", *series.Color)
}

func TestDashesCanBeEnabled(t *testing.T) {
req := require.New(t)
series := &sdk.SeriesOverride{}

Dashes(true)(series)

req.NotNil(series.Dashes)
req.True(*series.Dashes)
}

func TestLinesCanBeEnabled(t *testing.T) {
req := require.New(t)
series := &sdk.SeriesOverride{}

Lines(true)(series)

req.NotNil(series.Lines)
req.True(*series.Lines)
}

func TestFillOpacityCanBeDefined(t *testing.T) {
req := require.New(t)
series := &sdk.SeriesOverride{}

Fill(2)(series)

req.NotNil(*series.Fill)
req.Equal(2, *series.Fill)
}

func TestLineWidthCanBeDefined(t *testing.T) {
req := require.New(t)
series := &sdk.SeriesOverride{}

LineWidth(3)(series)

req.NotNil(*series.LineWidth)
req.Equal(3, *series.LineWidth)
}
6 changes: 3 additions & 3 deletions variable/constant/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func (values ValuesMap) asQuery() string {
return strings.Join(valuesList, ",")
}

func (values ValuesMap) labelFor(value string) string {
func (values ValuesMap) labelFor(value string) *sdk.StringSliceString {
for label, val := range values {
if val == value {
return label
return &sdk.StringSliceString{Value: []string{label}, Valid: true}
}
}

return value
return &sdk.StringSliceString{Value: []string{value}, Valid: true}
}

// Constant represents a "constant" templated variable.
Expand Down
2 changes: 1 addition & 1 deletion variable/constant/constant_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func TestDefaultValueCanBeSet(t *testing.T) {

panel := New("const", Default("99th"))

req.Equal("99th", panel.Builder.Current.Text)
req.Equal([]string{"99th"}, panel.Builder.Current.Text.Value)
req.Equal("99th", panel.Builder.Current.Value)
}

Expand Down
6 changes: 3 additions & 3 deletions variable/custom/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func (values ValuesMap) asQuery() string {
return strings.Join(valuesList, ",")
}

func (values ValuesMap) labelFor(value string) string {
func (values ValuesMap) labelFor(value string) *sdk.StringSliceString {
for label, val := range values {
if val == value {
return label
return &sdk.StringSliceString{Value: []string{label}, Valid: true}
}
}

return value
return &sdk.StringSliceString{Value: []string{value}, Valid: true}
}

// Custom represents a "custom" templated variable.
Expand Down
2 changes: 1 addition & 1 deletion variable/custom/custom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestDefaultValueCanBeSet(t *testing.T) {

panel := New("", Default("99"))

req.Equal("99", panel.Builder.Current.Text)
req.Equal([]string{"99"}, panel.Builder.Current.Text.Value)
}

func TestLabelCanBeHidden(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion variable/interval/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func Values(values ValuesList) Option {
func Default(value string) Option {
return func(interval *Interval) {
interval.Builder.Current = sdk.Current{
Text: value,
Text: &sdk.StringSliceString{Value: []string{value}, Valid: true},
Value: value,
}
}
Expand Down
2 changes: 1 addition & 1 deletion variable/interval/interval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func TestDefaultValueCanBeSet(t *testing.T) {

panel := New("", Default("99"))

req.Equal("99", panel.Builder.Current.Text)
req.Equal([]string{"99"}, panel.Builder.Current.Text.Value)
}

func TestLabelCanBeHidden(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion variable/query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func IncludeAll() Option {
// DefaultAll selects "All" values by default.
func DefaultAll() Option {
return func(query *Query) {
query.Builder.Current = sdk.Current{Text: "All", Value: "$__all"}
query.Builder.Current = sdk.Current{Text: &sdk.StringSliceString{Value: []string{"All"}, Valid: true}, Value: "$__all"}
}
}

Expand Down
Loading