Skip to content

Commit

Permalink
Merge pull request #7 from fiskaly/feature/4_metric_rate_group_by
Browse files Browse the repository at this point in the history
Metric Grouping
  • Loading branch information
ppaulweber authored Feb 4, 2024
2 parents 8ec91ef + 95f2560 commit 763e2d1
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 17 deletions.
118 changes: 110 additions & 8 deletions etc/provisioning/dashboards/Default/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"overrides": []
},
"gridPos": {
"h": 5,
"h": 9,
"w": 12,
"x": 0,
"y": 0
Expand Down Expand Up @@ -128,7 +128,7 @@
"overrides": []
},
"gridPos": {
"h": 13,
"h": 9,
"w": 12,
"x": 12,
"y": 0
Expand Down Expand Up @@ -229,10 +229,10 @@
"overrides": []
},
"gridPos": {
"h": 8,
"h": 10,
"w": 12,
"x": 0,
"y": 5
"y": 9
},
"id": 3,
"options": {
Expand Down Expand Up @@ -324,17 +324,119 @@
"overrides": []
},
"gridPos": {
"h": 15,
"h": 10,
"w": 12,
"x": 12,
"y": 9
},
"id": 5,
"options": {
"legend": {
"calcs": [],
"displayMode": "list",
"placement": "right",
"showLegend": true
},
"tooltip": {
"mode": "single",
"sort": "none"
}
},
"targets": [
{
"datasource": {
"type": "fiskaly-surrealdb-datasource",
"uid": "fiskaly-surrealdb-datasource"
},
"group": true,
"groupBy": "level",
"mode": "metric",
"rate": true,
"rateFunctions": [
"count"
],
"rateInterval": "10s",
"rateZero": true,
"refId": "A",
"requery": true,
"surql": "select * from timeseries:[$from]..[$to]"
}
],
"title": "Timeseries Rate Grouped By Level",
"type": "timeseries"
},
{
"datasource": {
"type": "fiskaly-surrealdb-datasource",
"uid": "fiskaly-surrealdb-datasource"
},
"description": "",
"fieldConfig": {
"defaults": {
"color": {
"mode": "palette-classic"
},
"custom": {
"axisBorderShow": false,
"axisCenteredZero": false,
"axisColorMode": "text",
"axisLabel": "",
"axisPlacement": "auto",
"barAlignment": 0,
"drawStyle": "line",
"fillOpacity": 0,
"gradientMode": "none",
"hideFrom": {
"legend": false,
"tooltip": false,
"viz": false
},
"insertNulls": false,
"lineInterpolation": "linear",
"lineWidth": 1,
"pointSize": 5,
"scaleDistribution": {
"type": "linear"
},
"showPoints": "auto",
"spanNulls": false,
"stacking": {
"group": "A",
"mode": "none"
},
"thresholdsStyle": {
"mode": "off"
}
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": []
},
"gridPos": {
"h": 9,
"w": 24,
"x": 0,
"y": 13
"y": 19
},
"id": 4,
"interval": "10s",
"options": {
"legend": {
"calcs": [],
"displayMode": "table",
"displayMode": "list",
"placement": "right",
"showLegend": true
},
Expand Down Expand Up @@ -377,7 +479,7 @@
"type": "timeseries"
}
],
"refresh": false,
"refresh": "",
"schemaVersion": 38,
"tags": [],
"templating": {
Expand Down
101 changes: 92 additions & 9 deletions pkg/plugin/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ type queryRequestData struct {
Timestamp string `json:"timestamp"`
LogMessage string `json:"logMessage"`
MetricData string `json:"metricData"`
Group bool `json:"group"`
GroupBy string `json:"groupBy"`
Rate bool `json:"rate"`
RateZero bool `json:"rateZero"`
RateInterval string `json:"rateInterval"`
Expand Down Expand Up @@ -249,6 +251,10 @@ func (r *Datasource) queryData(ctx context.Context, pCtx backend.PluginContext,
queryRequest.MetricData = "value"
}

if queryRequest.GroupBy == "" {
queryRequest.GroupBy = "group"
}

surql = strings.Replace(surql, "$interval", queryInterval.String(), -1)
surql = strings.Replace(surql, "$now", "'"+queryTimeNow.Format(time.RFC3339Nano)+"'", -1)
surql = strings.Replace(surql, "$from", "'"+queryTimeFrom.Format(time.RFC3339Nano)+"'", -1)
Expand Down Expand Up @@ -329,15 +335,27 @@ func (r *Datasource) queryData(ctx context.Context, pCtx backend.PluginContext,
)
}

if query.request.Rate {
err = r.metricRate(&query, &dataResponse)
if query.request.Group {
err = r.metricGroup(&query, &dataResponse)
if err != nil {
return backend.ErrDataResponse(
backend.StatusBadRequest,
fmt.Sprintf("Rate failed: %v", err.Error()),
fmt.Sprintf("Group failed: %v", err.Error()),
)
}
}

if query.request.Rate {
for _, frame := range dataResponse.Frames {
err = r.metricRate(&query, frame)
if err != nil {
return backend.ErrDataResponse(
backend.StatusBadRequest,
fmt.Sprintf("Rate failed: %v", err.Error()),
)
}
}
}
}

return dataResponse
Expand Down Expand Up @@ -614,16 +632,17 @@ func (r *Datasource) query(query string) (queryResponseData, error) {

func (r *Datasource) metric(query *queryData, dataResponse *backend.DataResponse) error {
frames := dataResponse.Frames

var timeField *data.Field
var dataField *data.Field

if len(frames) != 1 {
return fmt.Errorf("multiple frames are not supported yet")
}

var timeField *data.Field
var dataField *data.Field
var groupByField *data.Field

timeFieldName := query.request.Timestamp
dataFieldName := query.request.MetricData
groupByFieldName := query.request.GroupBy
suggestions := ""

frame := frames[0]
Expand All @@ -643,6 +662,10 @@ func (r *Datasource) metric(query *queryData, dataResponse *backend.DataResponse
dataField = field
continue
}
if fieldName == groupByFieldName {
groupByField = field
continue
}
}

if len(frame.Fields) == 0 {
Expand All @@ -664,20 +687,80 @@ func (r *Datasource) metric(query *queryData, dataResponse *backend.DataResponse
suggestions,
)
}
if groupByField == nil && query.request.Group {
return fmt.Errorf(
"group by '%s' not found in data frame, available are: %v",
groupByFieldName,
suggestions,
)
}

frame.Fields = []*data.Field{timeField, dataField}

if query.request.Group {
frame.Fields = append(frame.Fields, groupByField)
}

return nil
}

func (r *Datasource) metricRate(query *queryData, dataResponse *backend.DataResponse) error {
func (r *Datasource) metricGroup(query *queryData, dataResponse *backend.DataResponse) error {
frames := dataResponse.Frames

if len(frames) != 1 {
return fmt.Errorf("multiple frames are not supported yet")
}

frame := frames[0]

timeField := frame.Fields[0] // see 'metric()'
dataField := frame.Fields[1] // see 'metric()'
groupByField := frame.Fields[2] // see 'metric()'

groups := map[string]struct{}{}
groupTimeMap := map[string][]*time.Time{}
groupDataMap := map[string][]*float64{}

index := 0
for index < groupByField.Len() {
key := fmt.Sprintf("%s", groupByField.At(index))
groups[key] = struct{}{}

groupTime := timeField.At(index).(*time.Time)
groupData := dataField.At(index).(*float64)

_, groupTimeExists := groupTimeMap[key]
if groupTimeExists == false {
groupTimeMap[key] = []*time.Time{}
}
groupTimeMap[key] = append(groupTimeMap[key], groupTime)

_, groupDataExists := groupDataMap[key]
if groupDataExists == false {
groupDataMap[key] = []*float64{}
}
groupDataMap[key] = append(groupDataMap[key], groupData)

index++
}

dataResponse.Frames = []*data.Frame{}

for key, _ := range groups {
groupFrame := data.NewFrame(key)

groupTimeField := data.NewField(timeField.Name, nil, groupTimeMap[key])
groupFrame.Fields = append(groupFrame.Fields, groupTimeField)

groupDataField := data.NewField(dataField.Name, nil, groupDataMap[key])
groupFrame.Fields = append(groupFrame.Fields, groupDataField)

dataResponse.Frames = append(dataResponse.Frames, groupFrame)
}

return nil
}

func (r *Datasource) metricRate(query *queryData, frame *data.Frame) error {
timeField := frame.Fields[0] // see 'metric()'
dataField := frame.Fields[1] // see 'metric()'

Expand Down
Loading

0 comments on commit 763e2d1

Please sign in to comment.