fix: include inner panels support and map job,instance correctly (#1718)

* fix: include inner panels support and map job,instance correctly

* chore: remove debug and tidy up bit
This commit is contained in:
Srikanth Chekuri 2022-11-15 18:23:20 +05:30 committed by GitHub
parent e558dcae3a
commit 2c7deca2ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 169 additions and 121 deletions

View File

@ -5,6 +5,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"reflect" "reflect"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -20,6 +21,14 @@ import (
// This time the global variable is unexported. // This time the global variable is unexported.
var db *sqlx.DB var db *sqlx.DB
// User for mapping job,instance from grafana
var instanceEQRE = regexp.MustCompile("instance(?s)=(?s)\\\"{{.instance}}\\\"")
var nodeEQRE = regexp.MustCompile("instance(?s)=(?s)\\\"{{.node}}\\\"")
var jobEQRE = regexp.MustCompile("job(?s)=(?s)\\\"{{.job}}\\\"")
var instanceRERE = regexp.MustCompile("instance(?s)=~(?s)\\\"{{.instance}}\\\"")
var nodeRERE = regexp.MustCompile("instance(?s)=~(?s)\\\"{{.node}}\\\"")
var jobRERE = regexp.MustCompile("job(?s)=~(?s)\\\"{{.job}}\\\"")
// InitDB sets up setting up the connection pool global variable. // InitDB sets up setting up the connection pool global variable.
func InitDB(dataSourceName string) (*sqlx.DB, error) { func InitDB(dataSourceName string) (*sqlx.DB, error) {
var err error var err error
@ -264,6 +273,78 @@ func SlugifyTitle(title string) string {
return s return s
} }
func widgetFromPanel(panel model.Panels, idx int, variables map[string]model.Variable) *model.Widget {
widget := model.Widget{
Description: panel.Description,
ID: strconv.Itoa(idx),
IsStacked: false,
NullZeroValues: "zero",
Opacity: "1",
PanelTypes: "TIME_SERIES", // TODO: Need to figure out how to get this
Query: model.Query{
ClickHouse: []model.ClickHouseQueryDashboard{
{
Disabled: false,
Legend: "",
Name: "A",
Query: "",
},
},
MetricsBuilder: model.MetricsBuilder{
Formulas: []string{},
QueryBuilder: []model.QueryBuilder{
{
AggregateOperator: 1,
Disabled: false,
GroupBy: []string{},
Legend: "",
MetricName: "",
Name: "A",
ReduceTo: 1,
},
},
},
PromQL: []model.PromQueryDashboard{},
QueryType: int(model.PROM),
},
QueryData: model.QueryDataDashboard{
Data: model.Data{
QueryData: []interface{}{},
},
},
Title: panel.Title,
YAxisUnit: panel.FieldConfig.Defaults.Unit,
QueryType: int(model.PROM), // TODO: Supprot for multiple query types
}
for _, target := range panel.Targets {
if target.Expr != "" {
for name := range variables {
target.Expr = strings.ReplaceAll(target.Expr, "$"+name, "{{"+"."+name+"}}")
target.Expr = strings.ReplaceAll(target.Expr, "$"+"__rate_interval", "5m")
}
// prometheus receiver in collector maps job,instance as service_name,service_instance_id
target.Expr = instanceEQRE.ReplaceAllString(target.Expr, "service_instance_id=\"{{.instance}}\"")
target.Expr = nodeEQRE.ReplaceAllString(target.Expr, "service_instance_id=\"{{.node}}\"")
target.Expr = jobEQRE.ReplaceAllString(target.Expr, "service_name=\"{{.job}}\"")
target.Expr = instanceRERE.ReplaceAllString(target.Expr, "service_instance_id=~\"{{.instance}}\"")
target.Expr = nodeRERE.ReplaceAllString(target.Expr, "service_instance_id=~\"{{.node}}\"")
target.Expr = jobRERE.ReplaceAllString(target.Expr, "service_name=~\"{{.job}}\"")
widget.Query.PromQL = append(
widget.Query.PromQL,
model.PromQueryDashboard{
Disabled: false,
Legend: target.LegendFormat,
Name: target.RefID,
Query: target.Expr,
},
)
}
}
return &widget
}
func TransformGrafanaJSONToSignoz(grafanaJSON model.GrafanaJSON) model.DashboardData { func TransformGrafanaJSONToSignoz(grafanaJSON model.GrafanaJSON) model.DashboardData {
var toReturn model.DashboardData var toReturn model.DashboardData
toReturn.Title = grafanaJSON.Title toReturn.Title = grafanaJSON.Title
@ -350,7 +431,31 @@ func TransformGrafanaJSONToSignoz(grafanaJSON model.GrafanaJSON) model.Dashboard
} }
row := 0 row := 0
for idx, panel := range grafanaJSON.Panels { idx := 0
for _, panel := range grafanaJSON.Panels {
if panel.Type == "row" {
if panel.Panels != nil && len(panel.Panels) > 0 {
for _, innerPanel := range panel.Panels {
if idx%3 == 0 {
row++
}
toReturn.Layout = append(
toReturn.Layout,
model.Layout{
X: idx % 3 * 4,
Y: row * 3,
W: 4,
H: 3,
I: strconv.Itoa(idx),
},
)
toReturn.Widgets = append(toReturn.Widgets, *widgetFromPanel(innerPanel, idx, toReturn.Variables))
idx++
}
}
continue
}
if panel.Datasource == nil { if panel.Datasource == nil {
zap.S().Warnf("Skipping panel %d as it has no datasource", idx) zap.S().Warnf("Skipping panel %d as it has no datasource", idx)
continue continue
@ -395,67 +500,8 @@ func TransformGrafanaJSONToSignoz(grafanaJSON model.GrafanaJSON) model.Dashboard
}, },
) )
widget := model.Widget{ toReturn.Widgets = append(toReturn.Widgets, *widgetFromPanel(panel, idx, toReturn.Variables))
Description: panel.Description, idx++
ID: strconv.Itoa(idx),
IsStacked: false,
NullZeroValues: "zero",
Opacity: "1",
PanelTypes: "TIME_SERIES", // TODO: Need to figure out how to get this
Query: model.Query{
ClickHouse: []model.ClickHouseQueryDashboard{
{
Disabled: false,
Legend: "",
Name: "A",
Query: "",
},
},
MetricsBuilder: model.MetricsBuilder{
Formulas: []string{},
QueryBuilder: []model.QueryBuilder{
{
AggregateOperator: 1,
Disabled: false,
GroupBy: []string{},
Legend: "",
MetricName: "",
Name: "A",
ReduceTo: 1,
},
},
},
PromQL: []model.PromQueryDashboard{},
QueryType: int(model.PROM),
},
QueryData: model.QueryDataDashboard{
Data: model.Data{
QueryData: []interface{}{},
},
},
Title: panel.Title,
YAxisUnit: panel.FieldConfig.Defaults.Unit,
QueryType: int(model.PROM), // TODO: Supprot for multiple query types
}
for _, target := range panel.Targets {
if target.Expr != "" {
for name := range toReturn.Variables {
target.Expr = strings.ReplaceAll(target.Expr, "$"+name, "{{"+"."+name+"}}")
target.Expr = strings.ReplaceAll(target.Expr, "$"+"__rate_interval", "5m")
}
widget.Query.PromQL = append(
widget.Query.PromQL,
model.PromQueryDashboard{
Disabled: false,
Legend: target.LegendFormat,
Name: target.RefID,
Query: target.Expr,
},
)
}
}
toReturn.Widgets = append(toReturn.Widgets, widget)
} }
return toReturn return toReturn
} }

View File

@ -5,6 +5,65 @@ type Datasource struct {
UID string `json:"uid"` UID string `json:"uid"`
} }
type Panels struct {
Datasource interface{} `json:"datasource"`
Description string `json:"description,omitempty"`
FieldConfig struct {
Defaults struct {
Color struct {
Mode string `json:"mode"`
} `json:"color"`
Max float64 `json:"max"`
Min float64 `json:"min"`
Thresholds struct {
Mode string `json:"mode"`
Steps []struct {
Color string `json:"color"`
Value interface{} `json:"value"`
} `json:"steps"`
} `json:"thresholds"`
Unit string `json:"unit"`
} `json:"defaults"`
Overrides []interface{} `json:"overrides"`
} `json:"fieldConfig,omitempty"`
GridPos struct {
H int `json:"h"`
W int `json:"w"`
X int `json:"x"`
Y int `json:"y"`
} `json:"gridPos"`
ID int `json:"id"`
Links []interface{} `json:"links,omitempty"`
Options struct {
Orientation string `json:"orientation"`
ReduceOptions struct {
Calcs []string `json:"calcs"`
Fields string `json:"fields"`
Values bool `json:"values"`
} `json:"reduceOptions"`
ShowThresholdLabels bool `json:"showThresholdLabels"`
ShowThresholdMarkers bool `json:"showThresholdMarkers"`
} `json:"options,omitempty"`
PluginVersion string `json:"pluginVersion,omitempty"`
Targets []struct {
Datasource interface{} `json:"datasource"`
EditorMode string `json:"editorMode"`
Expr string `json:"expr"`
Hide bool `json:"hide"`
IntervalFactor int `json:"intervalFactor"`
LegendFormat string `json:"legendFormat"`
Range bool `json:"range"`
RefID string `json:"refId"`
Step int `json:"step"`
} `json:"targets"`
Title string `json:"title"`
Type string `json:"type"`
HideTimeOverride bool `json:"hideTimeOverride,omitempty"`
MaxDataPoints int `json:"maxDataPoints,omitempty"`
Collapsed bool `json:"collapsed,omitempty"`
Panels []Panels `json:"panels,omitempty"`
}
type GrafanaJSON struct { type GrafanaJSON struct {
Inputs []struct { Inputs []struct {
Name string `json:"name"` Name string `json:"name"`
@ -51,65 +110,8 @@ type GrafanaJSON struct {
Type string `json:"type"` Type string `json:"type"`
URL string `json:"url"` URL string `json:"url"`
} `json:"links"` } `json:"links"`
LiveNow bool `json:"liveNow"` LiveNow bool `json:"liveNow"`
Panels []struct { Panels []Panels `json:"panels"`
Datasource interface{} `json:"datasource"`
Description string `json:"description,omitempty"`
FieldConfig struct {
Defaults struct {
Color struct {
Mode string `json:"mode"`
} `json:"color"`
Max float64 `json:"max"`
Min float64 `json:"min"`
Thresholds struct {
Mode string `json:"mode"`
Steps []struct {
Color string `json:"color"`
Value interface{} `json:"value"`
} `json:"steps"`
} `json:"thresholds"`
Unit string `json:"unit"`
} `json:"defaults"`
Overrides []interface{} `json:"overrides"`
} `json:"fieldConfig,omitempty"`
GridPos struct {
H int `json:"h"`
W int `json:"w"`
X int `json:"x"`
Y int `json:"y"`
} `json:"gridPos"`
ID int `json:"id"`
Links []interface{} `json:"links,omitempty"`
Options struct {
Orientation string `json:"orientation"`
ReduceOptions struct {
Calcs []string `json:"calcs"`
Fields string `json:"fields"`
Values bool `json:"values"`
} `json:"reduceOptions"`
ShowThresholdLabels bool `json:"showThresholdLabels"`
ShowThresholdMarkers bool `json:"showThresholdMarkers"`
} `json:"options,omitempty"`
PluginVersion string `json:"pluginVersion,omitempty"`
Targets []struct {
Datasource interface{} `json:"datasource"`
EditorMode string `json:"editorMode"`
Expr string `json:"expr"`
Hide bool `json:"hide"`
IntervalFactor int `json:"intervalFactor"`
LegendFormat string `json:"legendFormat"`
Range bool `json:"range"`
RefID string `json:"refId"`
Step int `json:"step"`
} `json:"targets"`
Title string `json:"title"`
Type string `json:"type"`
HideTimeOverride bool `json:"hideTimeOverride,omitempty"`
MaxDataPoints int `json:"maxDataPoints,omitempty"`
Collapsed bool `json:"collapsed,omitempty"`
Panels []interface{} `json:"panels,omitempty"`
} `json:"panels"`
SchemaVersion int `json:"schemaVersion"` SchemaVersion int `json:"schemaVersion"`
Style string `json:"style"` Style string `json:"style"`
Tags []string `json:"tags"` Tags []string `json:"tags"`