@@ -3,9 +3,17 @@ package influxdb
3
3
import (
4
4
"context"
5
5
"crypto/tls"
6
+ "encoding/json"
7
+ "fmt"
6
8
"net/http"
9
+ "net/url"
10
+ "path"
7
11
"time"
8
12
13
+ "gopkg.in/guregu/null.v3"
14
+
15
+ "golang.org/x/net/context/ctxhttp"
16
+
9
17
"github.com/grafana/grafana/pkg/log"
10
18
"github.com/grafana/grafana/pkg/tsdb"
11
19
)
@@ -43,22 +51,141 @@ func init() {
43
51
}
44
52
}
45
53
46
- func (e * InfluxDBExecutor ) Execute (ctx context.Context , queries tsdb.QuerySlice , context * tsdb.QueryContext ) * tsdb.BatchResult {
47
- result := & tsdb.BatchResult {}
54
+ func (e * InfluxDBExecutor ) getQuery (queries tsdb.QuerySlice , context * tsdb.QueryContext ) (string , error ) {
48
55
for _ , v := range queries {
49
-
50
56
query , err := e .QueryParser .Parse (v .Model )
51
57
if err != nil {
52
- result .Error = err
53
- return result
58
+ return "" , err
54
59
}
55
60
56
- glog .Info ("Influxdb executor" , "query" , query )
61
+ rawQuery , err := e .QueryBuilder .Build (query , context )
62
+ if err != nil {
63
+ return "" , err
64
+ }
65
+
66
+ return rawQuery , nil
67
+ }
68
+
69
+ return "" , fmt .Errorf ("Tsdb request contains no queries" )
70
+ }
71
+
72
+ func (e * InfluxDBExecutor ) Execute (ctx context.Context , queries tsdb.QuerySlice , context * tsdb.QueryContext ) * tsdb.BatchResult {
73
+ result := & tsdb.BatchResult {}
74
+
75
+ query , err := e .getQuery (queries , context )
76
+ if err != nil {
77
+ result .Error = err
78
+ return result
79
+ }
80
+
81
+ glog .Info ("Influxdb" , "query" , query )
82
+
83
+ u , _ := url .Parse (e .Url )
84
+ u .Path = path .Join (u .Path , "query" )
85
+
86
+ req , err := http .NewRequest (http .MethodGet , u .String (), nil )
87
+ if err != nil {
88
+ result .Error = err
89
+ return result
90
+ }
91
+
92
+ params := req .URL .Query ()
93
+ params .Set ("q" , query )
94
+ params .Set ("db" , e .Database )
95
+ params .Set ("epoch" , "s" )
96
+
97
+ req .URL .RawQuery = params .Encode ()
57
98
58
- rawQuery , err := e .QueryBuilder .Build (query )
99
+ req .Header .Set ("Content-Type" , "" )
100
+ req .Header .Set ("User-Agent" , "Grafana" )
101
+ if e .BasicAuth {
102
+ req .SetBasicAuth (e .BasicAuthUser , e .BasicAuthPassword )
103
+ }
104
+
105
+ glog .Info ("influxdb request" , "url" , req .URL .String ())
106
+ resp , err := ctxhttp .Do (ctx , HttpClient , req )
107
+ if err != nil {
108
+ result .Error = err
109
+ return result
110
+ }
111
+
112
+ if resp .StatusCode / 100 != 2 {
113
+ result .Error = fmt .Errorf ("Influxdb returned statuscode %v body %v" , resp .Status )
114
+ return result
115
+ }
116
+
117
+ var response Response
118
+ dec := json .NewDecoder (resp .Body )
119
+ dec .UseNumber ()
120
+ err = dec .Decode (& response )
121
+ if err != nil {
122
+ glog .Error ("Influxdb decode failed" , "err" , err )
123
+ result .Error = err
124
+ return result
125
+ }
126
+
127
+ result .QueryResults = make (map [string ]* tsdb.QueryResult )
128
+ queryRes := tsdb .NewQueryResult ()
129
+
130
+ for _ , v := range response .Results {
131
+ for _ , r := range v .Series {
132
+ serie := tsdb.TimeSeries {Name : r .Name }
133
+ var points tsdb.TimeSeriesPoints
134
+
135
+ for _ , k := range r .Values {
136
+ var value null.Float
137
+ var err error
138
+ num , ok := k [1 ].(json.Number )
139
+ if ! ok {
140
+ value = null .FloatFromPtr (nil )
141
+ } else {
142
+ fvalue , err := num .Float64 ()
143
+ if err == nil {
144
+ value = null .FloatFrom (fvalue )
145
+ }
146
+ }
147
+
148
+ pos0 , ok := k [0 ].(json.Number )
149
+ timestamp , err := pos0 .Float64 ()
150
+ if err == nil && ok {
151
+ points = append (points , tsdb .NewTimePoint (value , timestamp ))
152
+ } else {
153
+ glog .Error ("Failed to convert response" , "err1" , err , "ok" , ok , "timestamp" , timestamp , "value" , value .Float64 )
154
+ }
155
+ serie .Points = points
156
+ }
157
+ queryRes .Series = append (queryRes .Series , & serie )
158
+ }
159
+ }
59
160
60
- glog .Info ("Influxdb" , "error" , err , "rawQuery" , rawQuery )
161
+ for _ , v := range queryRes .Series {
162
+ glog .Info ("result" , "name" , v .Name , "points" , v .Points )
61
163
}
62
164
165
+ result .QueryResults ["A" ] = queryRes
166
+
63
167
return result
64
168
}
169
+
170
+ type Response struct {
171
+ Results []Result
172
+ Err error
173
+ }
174
+
175
+ type Result struct {
176
+ Series []Row
177
+ Messages []* Message
178
+ Err error
179
+ }
180
+
181
+ type Message struct {
182
+ Level string `json:"level,omitempty"`
183
+ Text string `json:"text,omitempty"`
184
+ }
185
+
186
+ type Row struct {
187
+ Name string `json:"name,omitempty"`
188
+ Tags map [string ]string `json:"tags,omitempty"`
189
+ Columns []string `json:"columns,omitempty"`
190
+ Values [][]interface {} `json:"values,omitempty"`
191
+ }
0 commit comments