Skip to content

Commit

Permalink
Add business variable panel
Browse files Browse the repository at this point in the history
  • Loading branch information
leeyikjiun committed Feb 18, 2025
1 parent f365e2b commit f7cc20c
Show file tree
Hide file tree
Showing 4 changed files with 290 additions and 9 deletions.
8 changes: 8 additions & 0 deletions observability-lib/grafana/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import (

"github.com/grafana/grafana-foundation-sdk/go/alerting"
"github.com/grafana/grafana-foundation-sdk/go/cog"
"github.com/grafana/grafana-foundation-sdk/go/cog/plugins"
"github.com/grafana/grafana-foundation-sdk/go/common"
"github.com/grafana/grafana-foundation-sdk/go/dashboard"
"github.com/smartcontractkit/chainlink-common/observability-lib/grafana/businessvariable"
)

type Builder struct {
Expand All @@ -31,6 +33,9 @@ type BuilderOptions struct {
}

func NewBuilder(options *BuilderOptions) *Builder {
plugins.RegisterDefaultPlugins()
cog.NewRuntime().RegisterPanelcfgVariant(businessvariable.VariantConfig())

builder := &Builder{}

if options.Name != "" {
Expand Down Expand Up @@ -102,6 +107,9 @@ func (b *Builder) AddPanel(panel ...*Panel) {
} else if item.textPanelBuilder != nil {
item.textPanelBuilder.Id(panelID)
b.dashboardBuilder.WithPanel(item.textPanelBuilder)
} else if item.businessVariablePanelBuilder != nil {
item.businessVariablePanelBuilder.Id(panelID)
b.dashboardBuilder.WithPanel(item.businessVariablePanelBuilder)
}
if item.alertBuilders != nil && len(item.alertBuilders) > 0 {
b.AddAlert(item.alertBuilders...)
Expand Down
205 changes: 205 additions & 0 deletions observability-lib/grafana/businessvariable/panel_builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package businessvariable

import (
"errors"

"github.com/grafana/grafana-foundation-sdk/go/cog"
"github.com/grafana/grafana-foundation-sdk/go/dashboard"
)

var _ cog.Builder[dashboard.Panel] = (*PanelBuilder)(nil)

type PanelBuilder struct {
internal *dashboard.Panel
errors map[string]cog.BuildErrors
}

func NewPanelBuilder() *PanelBuilder {
resource := &dashboard.Panel{}
builder := &PanelBuilder{
internal: resource,
errors: make(map[string]cog.BuildErrors),
}

builder.applyDefaults()
builder.internal.Type = "volkovlabs-variable-panel"

return builder
}

func (builder *PanelBuilder) Build() (dashboard.Panel, error) {
var errs cog.BuildErrors

for _, err := range builder.errors {
errs = append(errs, cog.MakeBuildErrors("Panel", err)...)
}

if len(errs) != 0 {
return dashboard.Panel{}, errs
}

return *builder.internal, nil
}

// The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs.
func (builder *PanelBuilder) PluginVersion(pluginVersion string) *PanelBuilder {
builder.internal.PluginVersion = &pluginVersion

return builder
}

// Unique identifier of the panel. Generated by Grafana when creating a new panel. It must be unique within a dashboard, but not globally.
func (builder *PanelBuilder) Id(id uint32) *PanelBuilder {
builder.internal.Id = &id

return builder
}

// Panel title.
func (builder *PanelBuilder) Title(title string) *PanelBuilder {
builder.internal.Title = &title

return builder
}

// Panel description.
func (builder *PanelBuilder) Description(description string) *PanelBuilder {
builder.internal.Description = &description

return builder
}

// Whether to display the panel without a background.
func (builder *PanelBuilder) Transparent(transparent bool) *PanelBuilder {
builder.internal.Transparent = &transparent

return builder
}

// The datasource used in all targets.
func (builder *PanelBuilder) Datasource(datasource dashboard.DataSourceRef) *PanelBuilder {
builder.internal.Datasource = &datasource

return builder
}

// Grid position.
func (builder *PanelBuilder) GridPos(gridPos dashboard.GridPos) *PanelBuilder {
builder.internal.GridPos = &gridPos

return builder
}

// Panel height. The height is the number of rows from the top edge of the panel.
func (builder *PanelBuilder) Height(h uint32) *PanelBuilder {
if !(h > 0) {
builder.errors["h"] = cog.MakeBuildErrors("h", errors.New("h must be > 0"))
return builder
}
if builder.internal.GridPos == nil {
builder.internal.GridPos = &dashboard.GridPos{}
}
builder.internal.GridPos.H = h

return builder
}

// Panel width. The width is the number of columns from the left edge of the panel.
func (builder *PanelBuilder) Span(w uint32) *PanelBuilder {
if !(w > 0) {
builder.errors["w"] = cog.MakeBuildErrors("w", errors.New("w must be > 0"))
return builder
}
if !(w <= 24) {
builder.errors["w"] = cog.MakeBuildErrors("w", errors.New("w must be <= 24"))
return builder
}
if builder.internal.GridPos == nil {
builder.internal.GridPos = &dashboard.GridPos{}
}
builder.internal.GridPos.W = w

return builder
}

// Panel links.
func (builder *PanelBuilder) Links(links []cog.Builder[dashboard.DashboardLink]) *PanelBuilder {
linksResources := make([]dashboard.DashboardLink, 0, len(links))
for _, r1 := range links {
linksDepth1, err := r1.Build()
if err != nil {
builder.errors["links"] = err.(cog.BuildErrors)
return builder
}
linksResources = append(linksResources, linksDepth1)
}
builder.internal.Links = linksResources

return builder
}

// Name of template variable to repeat for.
func (builder *PanelBuilder) Repeat(repeat string) *PanelBuilder {
builder.internal.Repeat = &repeat

return builder
}

// Direction to repeat in if 'repeat' is set.
// `h` for horizontal, `v` for vertical.
func (builder *PanelBuilder) RepeatDirection(repeatDirection dashboard.PanelRepeatDirection) *PanelBuilder {
builder.internal.RepeatDirection = &repeatDirection

return builder
}

// Option for repeated panels that controls max items per row
// Only relevant for horizontally repeated panels
func (builder *PanelBuilder) MaxPerRow(maxPerRow float64) *PanelBuilder {
builder.internal.MaxPerRow = &maxPerRow

return builder
}

func (builder *PanelBuilder) DisplayMode(displayMode DisplayMode) *PanelBuilder {
if builder.internal.Options == nil {
builder.internal.Options = &Options{}
}
builder.internal.Options.(*Options).DisplayMode = displayMode

return builder
}

func (builder *PanelBuilder) Padding(padding int) *PanelBuilder {
if builder.internal.Options == nil {
builder.internal.Options = &Options{}
}
builder.internal.Options.(*Options).Padding = padding

return builder
}

func (builder *PanelBuilder) ShowLabel(showLabel bool) *PanelBuilder {
if builder.internal.Options == nil {
builder.internal.Options = &Options{}
}
builder.internal.Options.(*Options).ShowLabel = showLabel

return builder
}

func (builder *PanelBuilder) Variable(variable string) *PanelBuilder {
if builder.internal.Options == nil {
builder.internal.Options = &Options{}
}
builder.internal.Options.(*Options).Variable = variable

return builder
}

func (builder *PanelBuilder) applyDefaults() {
builder.PluginVersion("3.7.0")
builder.Height(8)
builder.Span(12)
builder.DisplayMode(DisplayModeTable)
}
36 changes: 36 additions & 0 deletions observability-lib/grafana/businessvariable/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package businessvariable

import (
"encoding/json"

"github.com/grafana/grafana-foundation-sdk/go/cog/variants"
)

type DisplayMode string

const (
DisplayModeTable DisplayMode = "table"
DisplayModeMinimize DisplayMode = "minimize"
)

type Options struct {
DisplayMode DisplayMode `json:"displayMode"`
Padding int `json:"padding"`
ShowLabel bool `json:"showLabel"`
Variable string `json:"variable"`
}

func VariantConfig() variants.PanelcfgConfig {
return variants.PanelcfgConfig{
Identifier: "volkovlabs-variable-panel",
OptionsUnmarshaler: func(raw []byte) (any, error) {
options := Options{}

if err := json.Unmarshal(raw, &options); err != nil {
return nil, err
}

return options, nil
},
}
}
50 changes: 41 additions & 9 deletions observability-lib/grafana/panels.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana-foundation-sdk/go/table"
"github.com/grafana/grafana-foundation-sdk/go/text"
"github.com/grafana/grafana-foundation-sdk/go/timeseries"
"github.com/smartcontractkit/chainlink-common/observability-lib/grafana/businessvariable"
)

type Query struct {
Expand Down Expand Up @@ -142,15 +143,16 @@ type PanelOptions struct {
}

type Panel struct {
statPanelBuilder *stat.PanelBuilder
timeSeriesPanelBuilder *timeseries.PanelBuilder
gaugePanelBuilder *gauge.PanelBuilder
barGaugePanelBuilder *bargauge.PanelBuilder
tablePanelBuilder *table.PanelBuilder
logPanelBuilder *logs.PanelBuilder
heatmapBuilder *heatmap.PanelBuilder
textPanelBuilder *text.PanelBuilder
alertBuilders []*alerting.RuleBuilder
statPanelBuilder *stat.PanelBuilder
timeSeriesPanelBuilder *timeseries.PanelBuilder
gaugePanelBuilder *gauge.PanelBuilder
barGaugePanelBuilder *bargauge.PanelBuilder
tablePanelBuilder *table.PanelBuilder
logPanelBuilder *logs.PanelBuilder
heatmapBuilder *heatmap.PanelBuilder
textPanelBuilder *text.PanelBuilder
businessVariablePanelBuilder *businessvariable.PanelBuilder
alertBuilders []*alerting.RuleBuilder
}

// panel defaults
Expand Down Expand Up @@ -740,3 +742,33 @@ func NewTextPanel(options *TextPanelOptions) *Panel {
textPanelBuilder: newPanel,
}
}

type BusinessVariablePanelOptions struct {
*PanelOptions
DisplayMode businessvariable.DisplayMode
Padding *int
ShowLabel bool
Variable string
}

func NewBusinessVariablePanel(options *BusinessVariablePanelOptions) *Panel {
setDefaults(options.PanelOptions)

newPanel := businessvariable.NewPanelBuilder().
Title(*options.Title).
Description(options.Description).
Transparent(options.Transparent).
Span(options.Span).
Height(options.Height).
DisplayMode(options.DisplayMode).
ShowLabel(options.ShowLabel).
Variable(options.Variable)

if options.Padding != nil {
newPanel.Padding(*options.Padding)
}

return &Panel{
businessVariablePanelBuilder: newPanel,
}
}

0 comments on commit f7cc20c

Please sign in to comment.