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,54 +5,7 @@ type Datasource struct {
UID string `json:"uid"` UID string `json:"uid"`
} }
type GrafanaJSON struct { type Panels struct {
Inputs []struct {
Name string `json:"name"`
Label string `json:"label"`
Description string `json:"description"`
Type string `json:"type"`
PluginID string `json:"pluginId"`
PluginName string `json:"pluginName"`
} `json:"__inputs"`
Requires []struct {
Type string `json:"type"`
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
} `json:"__requires"`
Annotations struct {
List []struct {
HashKey string `json:"$$hashKey"`
BuiltIn int `json:"builtIn"`
Datasource interface{} `json:"datasource"`
Enable bool `json:"enable"`
Hide bool `json:"hide"`
IconColor string `json:"iconColor"`
Name string `json:"name"`
Target struct {
Limit int `json:"limit"`
MatchAny bool `json:"matchAny"`
Tags []interface{} `json:"tags"`
Type string `json:"type"`
} `json:"target"`
Type string `json:"type"`
} `json:"list"`
} `json:"annotations"`
Editable bool `json:"editable"`
FiscalYearStartMonth int `json:"fiscalYearStartMonth"`
GnetID int `json:"gnetId"`
GraphTooltip int `json:"graphTooltip"`
ID interface{} `json:"id"`
Links []struct {
Icon string `json:"icon"`
Tags []interface{} `json:"tags"`
TargetBlank bool `json:"targetBlank"`
Title string `json:"title"`
Type string `json:"type"`
URL string `json:"url"`
} `json:"links"`
LiveNow bool `json:"liveNow"`
Panels []struct {
Datasource interface{} `json:"datasource"` Datasource interface{} `json:"datasource"`
Description string `json:"description,omitempty"` Description string `json:"description,omitempty"`
FieldConfig struct { FieldConfig struct {
@ -108,8 +61,57 @@ type GrafanaJSON struct {
HideTimeOverride bool `json:"hideTimeOverride,omitempty"` HideTimeOverride bool `json:"hideTimeOverride,omitempty"`
MaxDataPoints int `json:"maxDataPoints,omitempty"` MaxDataPoints int `json:"maxDataPoints,omitempty"`
Collapsed bool `json:"collapsed,omitempty"` Collapsed bool `json:"collapsed,omitempty"`
Panels []interface{} `json:"panels,omitempty"` Panels []Panels `json:"panels,omitempty"`
} `json:"panels"` }
type GrafanaJSON struct {
Inputs []struct {
Name string `json:"name"`
Label string `json:"label"`
Description string `json:"description"`
Type string `json:"type"`
PluginID string `json:"pluginId"`
PluginName string `json:"pluginName"`
} `json:"__inputs"`
Requires []struct {
Type string `json:"type"`
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
} `json:"__requires"`
Annotations struct {
List []struct {
HashKey string `json:"$$hashKey"`
BuiltIn int `json:"builtIn"`
Datasource interface{} `json:"datasource"`
Enable bool `json:"enable"`
Hide bool `json:"hide"`
IconColor string `json:"iconColor"`
Name string `json:"name"`
Target struct {
Limit int `json:"limit"`
MatchAny bool `json:"matchAny"`
Tags []interface{} `json:"tags"`
Type string `json:"type"`
} `json:"target"`
Type string `json:"type"`
} `json:"list"`
} `json:"annotations"`
Editable bool `json:"editable"`
FiscalYearStartMonth int `json:"fiscalYearStartMonth"`
GnetID int `json:"gnetId"`
GraphTooltip int `json:"graphTooltip"`
ID interface{} `json:"id"`
Links []struct {
Icon string `json:"icon"`
Tags []interface{} `json:"tags"`
TargetBlank bool `json:"targetBlank"`
Title string `json:"title"`
Type string `json:"type"`
URL string `json:"url"`
} `json:"links"`
LiveNow bool `json:"liveNow"`
Panels []Panels `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"`