Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
54f16d55
Commit
54f16d55
authored
Sep 11, 2018
by
Daniel Lee
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
stackdriver: add first test for parsing frontend queries
parent
95a6838f
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
127 additions
and
47 deletions
+127
-47
pkg/tsdb/stackdriver/stackdriver.go
+70
-46
pkg/tsdb/stackdriver/stackdriver_test.go
+47
-0
pkg/tsdb/stackdriver/types.go
+10
-1
No files found.
pkg/tsdb/stackdriver/stackdriver.go
View file @
54f16d55
...
...
@@ -10,7 +10,6 @@ import (
"net/url"
"path"
"regexp"
"strings"
"time"
"golang.org/x/net/context/ctxhttp"
...
...
@@ -27,11 +26,18 @@ import (
)
type
StackdriverExecutor
struct
{
H
ttp
Client
*
http
.
Client
H
TTP
Client
*
http
.
Client
}
func
NewStackdriverExecutor
(
datasource
*
models
.
DataSource
)
(
tsdb
.
TsdbQueryEndpoint
,
error
)
{
return
&
StackdriverExecutor
{},
nil
func
NewStackdriverExecutor
(
dsInfo
*
models
.
DataSource
)
(
tsdb
.
TsdbQueryEndpoint
,
error
)
{
httpClient
,
err
:=
dsInfo
.
GetHttpClient
()
if
err
!=
nil
{
return
nil
,
err
}
return
&
StackdriverExecutor
{
HTTPClient
:
httpClient
,
},
nil
}
var
glog
=
log
.
New
(
"tsdb.stackdriver"
)
...
...
@@ -40,57 +46,35 @@ func init() {
tsdb
.
RegisterTsdbQueryEndpoint
(
"stackdriver"
,
NewStackdriverExecutor
)
}
// Query takes in the frontend queries, parses them into the Stackdriver query format
// executes the queries against the Stackdriver API and parses the response into
// the time series or table format
func
(
e
*
StackdriverExecutor
)
Query
(
ctx
context
.
Context
,
dsInfo
*
models
.
DataSource
,
tsdbQuery
*
tsdb
.
TsdbQuery
)
(
*
tsdb
.
Response
,
error
)
{
result
:=
&
tsdb
.
Response
{
Results
:
make
(
map
[
string
]
*
tsdb
.
QueryResult
),
}
var
target
string
startTime
,
err
:=
tsdbQuery
.
TimeRange
.
ParseFrom
()
if
err
!=
nil
{
return
nil
,
err
}
endTime
,
err
:=
tsdbQuery
.
TimeRange
.
ParseTo
(
)
queries
,
err
:=
e
.
parseQueries
(
tsdbQuery
)
if
err
!=
nil
{
return
nil
,
err
}
logger
.
Info
(
"tsdbQuery"
,
"req.URL.RawQuery"
,
tsdbQuery
.
TimeRange
.
From
)
for
_
,
query
:=
range
tsdbQuery
.
Queries
{
if
fullTarget
,
err
:=
query
.
Model
.
Get
(
"targetFull"
)
.
String
();
err
==
nil
{
target
=
fixIntervalFormat
(
fullTarget
)
}
else
{
target
=
fixIntervalFormat
(
query
.
Model
.
Get
(
"target"
)
.
MustString
())
}
if
setting
.
Env
==
setting
.
DEV
{
glog
.
Debug
(
"Stackdriver request"
,
"params"
)
}
for
_
,
query
:=
range
queries
{
req
,
err
:=
e
.
createRequest
(
ctx
,
dsInfo
)
metricType
:=
query
.
Model
.
Get
(
"metricType"
)
.
MustString
()
q
:=
req
.
URL
.
Query
()
q
.
Add
(
"interval.startTime"
,
startTime
.
UTC
()
.
Format
(
time
.
RFC3339
))
q
.
Add
(
"interval.endTime"
,
endTime
.
UTC
()
.
Format
(
time
.
RFC3339
))
q
.
Add
(
"aggregation.perSeriesAligner"
,
"ALIGN_NONE"
)
q
.
Add
(
"filter"
,
metricType
)
req
.
URL
.
RawQuery
=
q
.
Encode
()
logger
.
Info
(
"tsdbQuery"
,
"req.URL.RawQuery"
,
req
.
URL
.
RawQuery
)
if
err
!=
nil
{
return
nil
,
err
}
req
.
URL
.
RawQuery
=
query
.
Params
.
Encode
()
logger
.
Info
(
"tsdbQuery"
,
"req.URL.RawQuery"
,
req
.
URL
.
RawQuery
)
httpClient
,
err
:=
dsInfo
.
GetHttpClient
()
if
err
!=
nil
{
return
nil
,
err
}
span
,
ctx
:=
opentracing
.
StartSpanFromContext
(
ctx
,
"stackdriver query"
)
span
.
SetTag
(
"target"
,
t
arget
)
span
.
SetTag
(
"target"
,
query
.
T
arget
)
span
.
SetTag
(
"from"
,
tsdbQuery
.
TimeRange
.
From
)
span
.
SetTag
(
"until"
,
tsdbQuery
.
TimeRange
.
To
)
span
.
SetTag
(
"datasource_id"
,
dsInfo
.
Id
)
...
...
@@ -113,13 +97,60 @@ func (e *StackdriverExecutor) Query(ctx context.Context, dsInfo *models.DataSour
return
nil
,
err
}
queryRes
,
err
:=
e
.
parseResponse
(
data
,
query
.
RefId
)
result
.
Results
[
query
.
RefId
]
=
queryRes
queryRes
,
err
:=
e
.
parseResponse
(
data
,
query
.
RefID
)
if
err
!=
nil
{
return
nil
,
err
}
result
.
Results
[
query
.
RefID
]
=
queryRes
}
return
result
,
nil
}
func
(
e
*
StackdriverExecutor
)
parseQueries
(
tsdbQuery
*
tsdb
.
TsdbQuery
)
([]
*
StackdriverQuery
,
error
)
{
stackdriverQueries
:=
[]
*
StackdriverQuery
{}
startTime
,
err
:=
tsdbQuery
.
TimeRange
.
ParseFrom
()
if
err
!=
nil
{
return
nil
,
err
}
endTime
,
err
:=
tsdbQuery
.
TimeRange
.
ParseTo
()
if
err
!=
nil
{
return
nil
,
err
}
for
_
,
query
:=
range
tsdbQuery
.
Queries
{
var
target
string
if
fullTarget
,
err
:=
query
.
Model
.
Get
(
"targetFull"
)
.
String
();
err
==
nil
{
target
=
fixIntervalFormat
(
fullTarget
)
}
else
{
target
=
fixIntervalFormat
(
query
.
Model
.
Get
(
"target"
)
.
MustString
())
}
metricType
:=
query
.
Model
.
Get
(
"metricType"
)
.
MustString
()
params
:=
url
.
Values
{}
params
.
Add
(
"interval.startTime"
,
startTime
.
UTC
()
.
Format
(
time
.
RFC3339
))
params
.
Add
(
"interval.endTime"
,
endTime
.
UTC
()
.
Format
(
time
.
RFC3339
))
params
.
Add
(
"aggregation.perSeriesAligner"
,
"ALIGN_NONE"
)
params
.
Add
(
"filter"
,
metricType
)
if
setting
.
Env
==
setting
.
DEV
{
glog
.
Debug
(
"Stackdriver request"
,
"params"
,
params
)
}
stackdriverQueries
=
append
(
stackdriverQueries
,
&
StackdriverQuery
{
Target
:
target
,
Params
:
params
,
RefID
:
query
.
RefId
,
})
}
return
stackdriverQueries
,
nil
}
func
(
e
*
StackdriverExecutor
)
unmarshalResponse
(
res
*
http
.
Response
)
(
StackDriverResponse
,
error
)
{
body
,
err
:=
ioutil
.
ReadAll
(
res
.
Body
)
defer
res
.
Body
.
Close
()
...
...
@@ -142,9 +173,9 @@ func (e *StackdriverExecutor) unmarshalResponse(res *http.Response) (StackDriver
return
data
,
nil
}
func
(
e
*
StackdriverExecutor
)
parseResponse
(
data
StackDriverResponse
,
queryRefI
d
string
)
(
*
tsdb
.
QueryResult
,
error
)
{
func
(
e
*
StackdriverExecutor
)
parseResponse
(
data
StackDriverResponse
,
queryRefI
D
string
)
(
*
tsdb
.
QueryResult
,
error
)
{
queryRes
:=
tsdb
.
NewQueryResult
()
queryRes
.
RefId
=
queryRefI
d
queryRes
.
RefId
=
queryRefI
D
for
_
,
series
:=
range
data
.
TimeSeries
{
points
:=
make
([]
tsdb
.
TimePoint
,
0
)
...
...
@@ -192,13 +223,6 @@ func (e *StackdriverExecutor) createRequest(ctx context.Context, dsInfo *models.
return
req
,
err
}
func
formatTimeRange
(
input
string
)
string
{
if
input
==
"now"
{
return
input
}
return
strings
.
Replace
(
strings
.
Replace
(
strings
.
Replace
(
input
,
"now"
,
""
,
-
1
),
"m"
,
"min"
,
-
1
),
"M"
,
"mon"
,
-
1
)
}
func
fixIntervalFormat
(
target
string
)
string
{
rMinute
:=
regexp
.
MustCompile
(
`'(\d+)m'`
)
rMin
:=
regexp
.
MustCompile
(
"m"
)
...
...
pkg/tsdb/stackdriver/stackdriver_test.go
0 → 100644
View file @
54f16d55
package
stackdriver
import
(
"fmt"
"testing"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/tsdb"
.
"github.com/smartystreets/goconvey/convey"
)
func
TestStackdriver
(
t
*
testing
.
T
)
{
Convey
(
"Stackdriver"
,
t
,
func
()
{
Convey
(
"Parse query from frontend"
,
func
()
{
executor
:=
&
StackdriverExecutor
{}
fromStart
:=
time
.
Date
(
2018
,
3
,
15
,
13
,
0
,
0
,
0
,
time
.
UTC
)
.
In
(
time
.
Local
)
tsdbQuery
:=
&
tsdb
.
TsdbQuery
{
TimeRange
:
&
tsdb
.
TimeRange
{
From
:
fmt
.
Sprintf
(
"%v"
,
fromStart
.
Unix
()
*
1000
),
To
:
fmt
.
Sprintf
(
"%v"
,
fromStart
.
Add
(
34
*
time
.
Minute
)
.
Unix
()
*
1000
),
},
Queries
:
[]
*
tsdb
.
Query
{
{
Model
:
simplejson
.
NewFromAny
(
map
[
string
]
interface
{}{
"target"
:
"target"
,
"metricType"
:
"time_series"
,
}),
RefId
:
"A"
,
},
},
}
queries
,
err
:=
executor
.
parseQueries
(
tsdbQuery
)
So
(
err
,
ShouldBeNil
)
So
(
len
(
queries
),
ShouldEqual
,
1
)
So
(
queries
[
0
]
.
RefID
,
ShouldEqual
,
"A"
)
So
(
queries
[
0
]
.
Target
,
ShouldEqual
,
"target"
)
So
(
len
(
queries
[
0
]
.
Params
),
ShouldEqual
,
4
)
So
(
queries
[
0
]
.
Params
[
"interval.startTime"
][
0
],
ShouldEqual
,
"2018-03-15T13:00:00Z"
)
So
(
queries
[
0
]
.
Params
[
"interval.endTime"
][
0
],
ShouldEqual
,
"2018-03-15T13:34:00Z"
)
So
(
queries
[
0
]
.
Params
[
"aggregation.perSeriesAligner"
][
0
],
ShouldEqual
,
"ALIGN_NONE"
)
So
(
queries
[
0
]
.
Params
[
"filter"
][
0
],
ShouldEqual
,
"time_series"
)
})
})
}
pkg/tsdb/stackdriver/types.go
View file @
54f16d55
package
stackdriver
import
"time"
import
(
"net/url"
"time"
)
type
StackdriverQuery
struct
{
Target
string
Params
url
.
Values
RefID
string
}
type
StackDriverResponse
struct
{
TimeSeries
[]
struct
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment