Skip to content

Commit

Permalink
Numeric values are exposed as float64 values, provisioned alerting query
Browse files Browse the repository at this point in the history
  • Loading branch information
retrodaredevil committed Apr 5, 2024
1 parent ca229d7 commit 3454fb9
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 9 deletions.
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,14 @@ The value is provided by the provided variables as seen in the above table.
Notice that while `interval_ms` is provided, we do not use it or define it anywhere in our query.
One thing to keep in mind for your own queries is the type accepted by the GraphQL server for a given variable.
In the case of that specific schema, the type of a `Long` is allowed to be a number or a string.
If your specific schema explicitly asks for a `String`, these variables may not work.
Please [raise and issue](https://github.com/wildmountainfarms/wild-graphql-datasource/issues) if this limitation becomes a roadblock.
If your schema does not have a `Long` type, you may consider changing the declaration of the query to use `Float` or `String`,
which are both types built into GraphQL.

If you run into any issues using the `from` and `to` variables for your specific schema,
please [raise and issue](https://github.com/wildmountainfarms/wild-graphql-datasource/issues).
Alternatively, if you are making a query on the frontend (any query besides alerting queries),
you may consider reading the next section to define your own from and to variables and assigning their values to
[a global variable](https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#__from-and-__to).


#### Grafana variable interpolation
Expand Down Expand Up @@ -263,11 +269,13 @@ This section documents errors that may be common
* `Failed to evaluate queries and expressions: input data must be a wide series but got type long (input refid)`
* This error indicates that the query returns more fields than just the time and the datapoint.
* For alerts, the response from the GraphQL query cannot contain more than the time and datapoint. At this time, you cannot use other attributes from the result to filter the data.
* `Failed to evaluate queries and expressions: failed to execute conditions: input data must be a wide series but got type not (input refid)`
* This may occur if you don't have any numeric data in your response (https://github.com/grafana/grafana/issues/46429)
* This error also occurs when you include labels and your response includes multiple data frames.
* To fix this, don't use labels in alerting queries. Alerting queries support the long data frame format, so it will automatically assume non-numeric fields are labels.
* This has the drawback that if your query returns data across a period of time, you cannot easily partition data by fields AND choose to only use the most recent data.

## Known Issues

* Alerting queries can only use fields provided in the response data.
* Alerting queries and annotation queries can only use fields provided in the response data.
* We plan to mitigate this in the future by allowing custom fields to be added to the response
* When hovering your mouse over a field in the query inside the GraphiQL editor, clicking either the field name or its type will navigate you away from the page, rather than jumping to the reference in the documentation explorer.
* Beware of this issue. If you accidentally let this bug navigate you away from the page, your work will be lost since your last dashboard save.
* Track this issue here: [grafana #85044](https://github.com/grafana/grafana/issues/85044)
10 changes: 9 additions & 1 deletion pkg/plugin/parsing/parsing.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,15 @@ func ParseData(graphQlResponseData *jsonnode.Object, parsingOption querymodel.Pa
row.FieldMap[key] = typedValue.String()
case jsonnode.Boolean:
row.FieldMap[key] = typedValue.Bool()
case jsonnode.Null, jsonnode.Number:
case jsonnode.Number:
parsedValue, err := typedValue.Float64()
if err != nil {
return nil, errors.New(fmt.Sprintf("Could not parse number: %s", typedValue.String())), UNKNOWN_ERROR
}
row.FieldMap[key] = parsedValue
// NOTE: We are allowed to store a jsonnode.Number type directly into the FieldMap (it's part of the contract to support that),
// but we decide not to because alerting queries require float64s to be used
case jsonnode.Null:
row.FieldMap[key] = typedValue
default:
return nil, errors.New(fmt.Sprintf("Unsupported type! type: %v", reflect.TypeOf(typedValue))), UNKNOWN_ERROR
Expand Down
2 changes: 1 addition & 1 deletion pkg/plugin/querymodel/querymodel.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type QueryModel struct {
QueryText string `json:"queryText"`
// The name of the operation, or a blank string to let the GraphQL server infer the operation name
OperationName string `json:"operationName"`
// The variables for the operation. May either be a string or a map[string]interface{}
// The variables for the operation. May either be a string or a map[string]interface{} or nil
Variables interface{} `json:"variables"`
ParsingOptions []ParsingOption `json:"parsingOptions"`
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/plugin/queryvariables/variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"reflect"
)

func AutoPopulateVariables(query backend.DataQuery, variables map[string]interface{}) {
Expand Down Expand Up @@ -59,9 +60,11 @@ func ParseVariables(query backend.DataQuery, rawVariables interface{}) (map[stri
for key, value := range typedRawVariables {
variables[key] = value
}
case nil:
// do nothing
default:
noErrors = false
log.DefaultLogger.Error("Unable to parse variables for ref ID:" + query.RefID)
log.DefaultLogger.Error(fmt.Sprintf("Unable to parse variables for ref ID: %s. Type is %v", query.RefID, reflect.TypeOf(rawVariables)))
}

return variables, noErrors
Expand Down
80 changes: 80 additions & 0 deletions provisioning/alerting/solarthing-alerts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
apiVersion: 1
groups:
- orgId: 1
name: SolarThing Alerts
folder: Alerts
interval: 1m
rules:
- uid: ea5bb5a0-55be-4f37-b9e0-4804b12d7a73
title: Low Battery Voltage
condition: C
data:
- refId: A
relativeTimeRange:
from: 600
to: 0
datasourceUid: fa66cf68-c3d8-4490-a89d-0c3b6a87fff8
model:
datasource:
type: retrodaredevil-wildgraphql-datasource
uid: fa66cf68-c3d8-4490-a89d-0c3b6a87fff8
intervalMs: 1000
maxDataPoints: 43200
parsingOptions:
- dataPath: queryStatusLast.batteryVoltage
labelOptions: []
timeFields:
- timePath: dateMillis
queryText: |
query ($to: Long!) {
queryStatusLast(sourceId: "default", to: $to) {
batteryVoltage {
fragmentIdString
packet {
batteryVoltage
identifier {
representation
}
}
}
}
}
refId: A
- refId: C
relativeTimeRange:
from: 600
to: 0
datasourceUid: __expr__
model:
conditions:
- evaluator:
params:
- 22.4
type: lt
operator:
type: and
query:
params:
- C
reducer:
params: []
type: last
type: query
datasource:
type: __expr__
uid: __expr__
expression: A
intervalMs: 1000
maxDataPoints: 43200
refId: C
type: threshold
noDataState: NoData
execErrState: Error
for: 5m
annotations:
description: Triggers when the battery is below 22.4
runbook_url: ""
summary: Low Battery
labels:
"": ""
isPaused: false

0 comments on commit 3454fb9

Please sign in to comment.