mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-12 07:39:00 +08:00
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:
parent
e558dcae3a
commit
2c7deca2ec
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -20,6 +21,14 @@ import (
|
||||
// This time the global variable is unexported.
|
||||
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.
|
||||
func InitDB(dataSourceName string) (*sqlx.DB, error) {
|
||||
var err error
|
||||
@ -264,6 +273,78 @@ func SlugifyTitle(title string) string {
|
||||
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 {
|
||||
var toReturn model.DashboardData
|
||||
toReturn.Title = grafanaJSON.Title
|
||||
@ -350,7 +431,31 @@ func TransformGrafanaJSONToSignoz(grafanaJSON model.GrafanaJSON) model.Dashboard
|
||||
}
|
||||
|
||||
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 {
|
||||
zap.S().Warnf("Skipping panel %d as it has no datasource", idx)
|
||||
continue
|
||||
@ -395,67 +500,8 @@ func TransformGrafanaJSONToSignoz(grafanaJSON model.GrafanaJSON) model.Dashboard
|
||||
},
|
||||
)
|
||||
|
||||
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 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)
|
||||
toReturn.Widgets = append(toReturn.Widgets, *widgetFromPanel(panel, idx, toReturn.Variables))
|
||||
idx++
|
||||
}
|
||||
return toReturn
|
||||
}
|
||||
|
@ -5,54 +5,7 @@ type Datasource struct {
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
|
||||
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 []struct {
|
||||
type Panels struct {
|
||||
Datasource interface{} `json:"datasource"`
|
||||
Description string `json:"description,omitempty"`
|
||||
FieldConfig struct {
|
||||
@ -108,8 +61,57 @@ type GrafanaJSON struct {
|
||||
HideTimeOverride bool `json:"hideTimeOverride,omitempty"`
|
||||
MaxDataPoints int `json:"maxDataPoints,omitempty"`
|
||||
Collapsed bool `json:"collapsed,omitempty"`
|
||||
Panels []interface{} `json:"panels,omitempty"`
|
||||
} `json:"panels"`
|
||||
Panels []Panels `json:"panels,omitempty"`
|
||||
}
|
||||
|
||||
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"`
|
||||
Style string `json:"style"`
|
||||
Tags []string `json:"tags"`
|
||||
|
Loading…
x
Reference in New Issue
Block a user