diff --git a/observability-lib/grafana/builder.go b/observability-lib/grafana/builder.go index 426d5cd5c..70a728172 100644 --- a/observability-lib/grafana/builder.go +++ b/observability-lib/grafana/builder.go @@ -20,13 +20,14 @@ type Builder struct { } type BuilderOptions struct { - Name string - Tags []string - Refresh string - TimeFrom string - TimeTo string - TimeZone string - AlertsTags map[string]string + Name string + Tags []string + Refresh string + TimeFrom string + TimeTo string + TimeZone string + GraphTooltip dashboard.DashboardCursorSync + AlertsTags map[string]string } func NewBuilder(options *BuilderOptions) *Builder { @@ -46,7 +47,9 @@ func NewBuilder(options *BuilderOptions) *Builder { if options.TimeZone == "" { options.TimeZone = common.TimeZoneBrowser } - builder.dashboardBuilder.Timezone(options.TimeZone) + builder.dashboardBuilder. + Timezone(options.TimeZone). + Tooltip(options.GraphTooltip) } if options.AlertsTags != nil { @@ -93,6 +96,9 @@ func (b *Builder) AddPanel(panel ...*Panel) { } else if item.heatmapBuilder != nil { item.heatmapBuilder.Id(panelID) b.dashboardBuilder.WithPanel(item.heatmapBuilder) + } else if item.textPanelBuilder != nil { + item.textPanelBuilder.Id(panelID) + b.dashboardBuilder.WithPanel(item.textPanelBuilder) } if item.alertBuilders != nil && len(item.alertBuilders) > 0 { b.AddAlert(item.alertBuilders...) diff --git a/observability-lib/grafana/builder_test.go b/observability-lib/grafana/builder_test.go index 2c4f56253..7c4c21386 100644 --- a/observability-lib/grafana/builder_test.go +++ b/observability-lib/grafana/builder_test.go @@ -179,7 +179,7 @@ func TestBuilder_AddPanel(t *testing.T) { panel := grafana.NewStatPanel(&grafana.StatPanelOptions{ PanelOptions: &grafana.PanelOptions{ - Title: "Panel Title", + Title: grafana.Pointer("Panel Title"), }, }) diff --git a/observability-lib/grafana/dashboard_test.go b/observability-lib/grafana/dashboard_test.go index ecac1d04a..704a73c65 100644 --- a/observability-lib/grafana/dashboard_test.go +++ b/observability-lib/grafana/dashboard_test.go @@ -21,10 +21,10 @@ func TestGenerateJSON(t *testing.T) { builder.AddPanel(grafana.NewTimeSeriesPanel(&grafana.TimeSeriesPanelOptions{ PanelOptions: &grafana.PanelOptions{ Datasource: "datasource-name", - Title: "ETH Balance", + Title: grafana.Pointer("ETH Balance"), Span: 12, Height: 6, - Decimals: 2, + Decimals: grafana.Pointer(2.0), Query: []grafana.Query{ { Expr: `eth_balance`, diff --git a/observability-lib/grafana/panels.go b/observability-lib/grafana/panels.go index 2e4b20c6a..7f1750a93 100644 --- a/observability-lib/grafana/panels.go +++ b/observability-lib/grafana/panels.go @@ -10,6 +10,7 @@ import ( "github.com/grafana/grafana-foundation-sdk/go/prometheus" "github.com/grafana/grafana-foundation-sdk/go/stat" "github.com/grafana/grafana-foundation-sdk/go/table" + "github.com/grafana/grafana-foundation-sdk/go/text" "github.com/grafana/grafana-foundation-sdk/go/timeseries" ) @@ -121,11 +122,12 @@ func newToolTip(options *ToolTipOptions) *common.VizTooltipOptionsBuilder { type PanelOptions struct { Datasource string - Title string + Title *string Description string + Transparent bool Span uint32 Height uint32 - Decimals float64 + Decimals *float64 Unit string NoValue string Min *float64 @@ -144,6 +146,7 @@ type Panel struct { tablePanelBuilder *table.PanelBuilder logPanelBuilder *logs.PanelBuilder heatmapBuilder *heatmap.PanelBuilder + textPanelBuilder *text.PanelBuilder alertBuilders []*alerting.RuleBuilder } @@ -152,8 +155,8 @@ func setDefaults(options *PanelOptions) { if options.Datasource == "" { options.Datasource = "Prometheus" } - if options.Title == "" { - options.Title = "Panel Title" + if options.Title == nil { + options.Title = Pointer("Panel Title") } if options.Span == 0 { options.Span = 24 @@ -199,11 +202,11 @@ func NewStatPanel(options *StatPanelOptions) *Panel { newPanel := stat.NewPanelBuilder(). Datasource(datasourceRef(options.Datasource)). - Title(options.Title). + Title(*options.Title). Description(options.Description). + Transparent(options.Transparent). Span(options.Span). Height(options.Height). - Decimals(options.Decimals). Unit(options.Unit). NoValue(options.NoValue). Text(common.NewVizTextDisplayOptionsBuilder().TitleSize(10).ValueSize(18)). @@ -215,6 +218,10 @@ func NewStatPanel(options *StatPanelOptions) *Panel { Mappings(options.Mappings). ReduceOptions(common.NewReduceDataOptionsBuilder().Calcs([]string{"last"})) + if options.Decimals != nil { + newPanel.Decimals(*options.Decimals) + } + if options.MaxDataPoints != nil { newPanel.MaxDataPoints(*options.MaxDataPoints) } @@ -263,11 +270,13 @@ func NewStatPanel(options *StatPanelOptions) *Panel { type TimeSeriesPanelOptions struct { *PanelOptions AlertsOptions []AlertOptions + LineWidth *float64 FillOpacity float64 ScaleDistribution common.ScaleDistribution LegendOptions *LegendOptions ToolTipOptions *ToolTipOptions ThresholdStyle common.GraphThresholdsStyleMode + DrawStyle common.GraphDrawStyle } func NewTimeSeriesPanel(options *TimeSeriesPanelOptions) *Panel { @@ -277,6 +286,10 @@ func NewTimeSeriesPanel(options *TimeSeriesPanelOptions) *Panel { options.ScaleDistribution = common.ScaleDistributionLinear } + if options.LineWidth == nil { + options.LineWidth = Pointer[float64](1) + } + if options.LegendOptions == nil { options.LegendOptions = &LegendOptions{} } @@ -287,13 +300,14 @@ func NewTimeSeriesPanel(options *TimeSeriesPanelOptions) *Panel { newPanel := timeseries.NewPanelBuilder(). Datasource(datasourceRef(options.Datasource)). - Title(options.Title). + Title(*options.Title). Description(options.Description). + Transparent(options.Transparent). Span(options.Span). Height(options.Height). - Decimals(options.Decimals). Unit(options.Unit). NoValue(options.NoValue). + LineWidth(*options.LineWidth). FillOpacity(options.FillOpacity). Legend(newLegend(options.LegendOptions)). ScaleDistribution(common.NewScaleDistributionConfigBuilder(). @@ -301,6 +315,10 @@ func NewTimeSeriesPanel(options *TimeSeriesPanelOptions) *Panel { ). Tooltip(newToolTip(options.ToolTipOptions)) + if options.Decimals != nil { + newPanel.Decimals(*options.Decimals) + } + if options.MaxDataPoints != nil { newPanel.MaxDataPoints(*options.MaxDataPoints) } @@ -325,6 +343,10 @@ func NewTimeSeriesPanel(options *TimeSeriesPanelOptions) *Panel { } } + if options.DrawStyle != "" { + newPanel.DrawStyle(options.DrawStyle) + } + if options.Transform != nil { newPanel.WithTransformation(newTransform(options.Transform)) } @@ -337,10 +359,10 @@ func NewTimeSeriesPanel(options *TimeSeriesPanelOptions) *Panel { if options.AlertsOptions != nil && len(options.AlertsOptions) > 0 { for _, alert := range options.AlertsOptions { // this is used as an internal mechanism to set the panel title in the alert to associate panelId with alert - alert.PanelTitle = options.Title + alert.PanelTitle = *options.Title // if name is provided use it, otherwise use panel title if alert.Title == "" { - alert.Title = options.Title + alert.Title = *options.Title } alertBuilders = append(alertBuilders, NewAlertRule(&alert)) } @@ -361,17 +383,21 @@ func NewGaugePanel(options *GaugePanelOptions) *Panel { newPanel := gauge.NewPanelBuilder(). Datasource(datasourceRef(options.Datasource)). - Title(options.Title). + Title(*options.Title). Description(options.Description). + Transparent(options.Transparent). Span(options.Span). Height(options.Height). - Decimals(options.Decimals). Unit(options.Unit). ReduceOptions( common.NewReduceDataOptionsBuilder(). Calcs([]string{"lastNotNull"}).Values(false), ) + if options.Decimals != nil { + newPanel.Decimals(*options.Decimals) + } + if options.MaxDataPoints != nil { newPanel.MaxDataPoints(*options.MaxDataPoints) } @@ -410,14 +436,18 @@ func NewTablePanel(options *TablePanelOptions) *Panel { newPanel := table.NewPanelBuilder(). Datasource(datasourceRef(options.Datasource)). - Title(options.Title). + Title(*options.Title). Description(options.Description). + Transparent(options.Transparent). Span(options.Span). Height(options.Height). - Decimals(options.Decimals). Unit(options.Unit). NoValue(options.NoValue) + if options.Decimals != nil { + newPanel.Decimals(*options.Decimals) + } + if options.MaxDataPoints != nil { newPanel.MaxDataPoints(*options.MaxDataPoints) } @@ -453,20 +483,45 @@ func NewTablePanel(options *TablePanelOptions) *Panel { type LogPanelOptions struct { *PanelOptions - PrettifyJSON bool + ShowTime bool + PrettifyJSON bool + EnableLogDetails *bool + DedupStrategy common.LogsDedupStrategy + SortOrder common.LogsSortOrder } func NewLogPanel(options *LogPanelOptions) *Panel { setDefaults(options.PanelOptions) + if options.EnableLogDetails == nil { + options.EnableLogDetails = Pointer[bool](true) + } + + if options.DedupStrategy == "" { + options.DedupStrategy = common.LogsDedupStrategyNone + } + + if options.SortOrder == "" { + options.SortOrder = common.LogsSortOrderDescending // Newest First + } + newPanel := logs.NewPanelBuilder(). Datasource(datasourceRef(options.Datasource)). - Title(options.Title). + Title(*options.Title). Description(options.Description). + Transparent(options.Transparent). Span(options.Span). Height(options.Height). NoValue(options.NoValue). - PrettifyLogMessage(options.PrettifyJSON) + ShowTime(options.ShowTime). + PrettifyLogMessage(options.PrettifyJSON). + EnableLogDetails(*options.EnableLogDetails). + DedupStrategy(options.DedupStrategy). + SortOrder(options.SortOrder) + + if options.Decimals != nil { + newPanel.Decimals(*options.Decimals) + } if options.MaxDataPoints != nil { newPanel.MaxDataPoints(*options.MaxDataPoints) @@ -510,14 +565,18 @@ func NewHeatmapPanel(options *HeatmapPanelOptions) *Panel { newPanel := heatmap.NewPanelBuilder(). Datasource(datasourceRef(options.Datasource)). - Title(options.Title). + Title(*options.Title). Description(options.Description). + Transparent(options.Transparent). Span(options.Span). Height(options.Height). - Decimals(options.Decimals). Unit(options.Unit). NoValue(options.NoValue) + if options.Decimals != nil { + newPanel.Decimals(*options.Decimals) + } + if options.Min != nil { newPanel.Min(*options.Min) } @@ -547,3 +606,30 @@ func NewHeatmapPanel(options *HeatmapPanelOptions) *Panel { heatmapBuilder: newPanel, } } + +type TextPanelOptions struct { + *PanelOptions + Mode text.TextMode + Content string +} + +func NewTextPanel(options *TextPanelOptions) *Panel { + setDefaults(options.PanelOptions) + + if options.Mode == "" { + options.Mode = text.TextModeMarkdown + } + + newPanel := text.NewPanelBuilder(). + Title(*options.Title). + Description(options.Description). + Transparent(options.Transparent). + Span(options.Span). + Height(options.Height). + Mode(options.Mode). + Content(options.Content) + + return &Panel{ + textPanelBuilder: newPanel, + } +} diff --git a/observability-lib/grafana/variables.go b/observability-lib/grafana/variables.go index 445a071cb..3d74e48b7 100644 --- a/observability-lib/grafana/variables.go +++ b/observability-lib/grafana/variables.go @@ -14,6 +14,7 @@ type VariableOption struct { Name string Label string Description string + Hide dashboard.VariableHide CurrentText string CurrentValue string } @@ -31,6 +32,7 @@ func NewCustomVariable(options *CustomVariableOptions) *dashboard.CustomVariable variable := dashboard.NewCustomVariableBuilder(options.Name). Label(options.Label). + Hide(options.Hide). Description(options.Description). Current(dashboard.VariableOption{ Selected: cog.ToPtr[bool](true),