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
7cac393d
Unverified
Commit
7cac393d
authored
Jul 18, 2019
by
Kyle Brandt
Committed by
GitHub
Jul 18, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
datasource: testdata - add predicatable csv wave scenario (#18183)
parent
e47546d5
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
154 additions
and
37 deletions
+154
-37
pkg/components/null/float.go
+14
-0
pkg/tsdb/testdata/scenarios.go
+101
-37
public/app/plugins/datasource/testdata/partials/query.editor.html
+28
-0
public/app/plugins/datasource/testdata/query_ctrl.ts
+11
-0
No files found.
pkg/components/null/float.go
View file @
7cac393d
...
...
@@ -42,6 +42,20 @@ func FloatFromPtr(f *float64) Float {
return
NewFloat
(
*
f
,
true
)
}
// FloatFromString creates a new Float from string f.
// If the string is equal to the value of nullString then the Float will be null.
// An empty string f will return an error.
func
FloatFromString
(
f
string
,
nullString
string
)
(
Float
,
error
)
{
if
f
==
nullString
{
return
FloatFromPtr
(
nil
),
nil
}
fV
,
err
:=
strconv
.
ParseFloat
(
f
,
64
)
if
err
!=
nil
{
return
Float
{},
err
}
return
FloatFrom
(
fV
),
nil
}
// UnmarshalJSON implements json.Unmarshaler.
// It supports number and null input.
// 0 will not be considered a null Float.
...
...
pkg/tsdb/testdata/scenarios.go
View file @
7cac393d
...
...
@@ -114,6 +114,14 @@ func init() {
})
registerScenario
(
&
Scenario
{
Id
:
"predictable_csv_wave"
,
Name
:
"Predictable CSV Wave"
,
Handler
:
func
(
query
*
tsdb
.
Query
,
context
*
tsdb
.
TsdbQuery
)
*
tsdb
.
QueryResult
{
return
getPredictableCSVWave
(
query
,
context
)
},
})
registerScenario
(
&
Scenario
{
Id
:
"random_walk_table"
,
Name
:
"Random Walk Table"
,
...
...
@@ -385,27 +393,6 @@ func getPredictablePulse(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.Query
return
queryRes
}
fromStringOrNumber
:=
func
(
val
*
simplejson
.
Json
)
(
null
.
Float
,
error
)
{
switch
v
:=
val
.
Interface
()
.
(
type
)
{
case
json
.
Number
:
fV
,
err
:=
v
.
Float64
()
if
err
!=
nil
{
return
null
.
Float
{},
err
}
return
null
.
FloatFrom
(
fV
),
nil
case
string
:
if
v
==
"null"
{
return
null
.
FloatFromPtr
(
nil
),
nil
}
fV
,
err
:=
strconv
.
ParseFloat
(
v
,
64
)
if
err
!=
nil
{
return
null
.
Float
{},
err
}
return
null
.
FloatFrom
(
fV
),
nil
default
:
return
null
.
Float
{},
fmt
.
Errorf
(
"failed to extract value"
)
}
}
onValue
,
err
=
fromStringOrNumber
(
options
.
Get
(
"onValue"
))
if
err
!=
nil
{
queryRes
.
Error
=
fmt
.
Errorf
(
"failed to parse onValue value '%v' into float: %v"
,
options
.
Get
(
"onValue"
),
err
)
...
...
@@ -417,37 +404,99 @@ func getPredictablePulse(query *tsdb.Query, context *tsdb.TsdbQuery) *tsdb.Query
return
queryRes
}
from
:=
context
.
TimeRange
.
GetFromAsMsEpoch
()
to
:=
context
.
TimeRange
.
GetToAsMsEpoch
()
timeStep
=
timeStep
*
1000
// Seconds to Milliseconds
onFor
:=
func
(
mod
int64
)
(
null
.
Float
,
error
)
{
// How many items in the cycle should get the on value
var
i
int64
for
i
=
0
;
i
<
onCount
;
i
++
{
if
mod
==
i
*
timeStep
{
return
onValue
,
nil
}
}
return
offValue
,
nil
}
points
,
err
:=
predictableSeries
(
context
.
TimeRange
,
timeStep
,
onCount
+
offCount
,
onFor
)
if
err
!=
nil
{
queryRes
.
Error
=
err
return
queryRes
}
series
:=
newSeriesForQuery
(
query
)
points
:=
make
(
tsdb
.
TimeSeriesPoints
,
0
)
series
.
Points
=
*
points
queryRes
.
Series
=
append
(
queryRes
.
Series
,
series
)
return
queryRes
}
timeStep
=
timeStep
*
1000
// Seconds to Milliseconds
timeCursor
:=
from
-
(
from
%
timeStep
)
// Truncate Start
wavePeriod
:=
timeStep
*
(
onCount
+
offCount
)
maxPoints
:=
10000
// Don't return too many points
func
getPredictableCSVWave
(
query
*
tsdb
.
Query
,
context
*
tsdb
.
TsdbQuery
)
*
tsdb
.
QueryResult
{
queryRes
:=
tsdb
.
NewQueryResult
()
// Process Input
var
timeStep
int64
options
:=
query
.
Model
.
Get
(
"csvWave"
)
var
err
error
if
timeStep
,
err
=
options
.
Get
(
"timeStep"
)
.
Int64
();
err
!=
nil
{
queryRes
.
Error
=
fmt
.
Errorf
(
"failed to parse timeStep value '%v' into integer: %v"
,
options
.
Get
(
"timeStep"
),
err
)
return
queryRes
}
rawValues
:=
options
.
Get
(
"valuesCSV"
)
.
MustString
()
rawValues
=
strings
.
TrimRight
(
strings
.
TrimSpace
(
rawValues
),
","
)
// Strip Trailing Comma
rawValesCSV
:=
strings
.
Split
(
rawValues
,
","
)
values
:=
make
([]
null
.
Float
,
len
(
rawValesCSV
))
for
i
,
rawValue
:=
range
rawValesCSV
{
val
,
err
:=
null
.
FloatFromString
(
strings
.
TrimSpace
(
rawValue
),
"null"
)
if
err
!=
nil
{
queryRes
.
Error
=
fmt
.
Errorf
(
"failed to parse value '%v' into nullable float: err"
,
rawValue
,
err
)
return
queryRes
}
values
[
i
]
=
val
}
onFor
:=
func
(
mod
int64
)
null
.
Float
{
// How many items in the cycle should get the on value
timeStep
=
timeStep
*
1000
// Seconds to Milliseconds
valuesLen
:=
int64
(
len
(
values
))
getValue
:=
func
(
mod
int64
)
(
null
.
Float
,
error
)
{
var
i
int64
for
i
=
0
;
i
<
onCount
;
i
++
{
for
i
=
0
;
i
<
valuesLen
;
i
++
{
if
mod
==
i
*
timeStep
{
return
onValue
return
values
[
i
],
nil
}
}
return
offValue
return
null
.
Float
{},
fmt
.
Errorf
(
"did not get value at point in waveform - should not be here"
)
}
for
i
:=
0
;
i
<
maxPoints
&&
timeCursor
<
to
;
i
++
{
point
:=
tsdb
.
NewTimePoint
(
onFor
(
timeCursor
%
wavePeriod
),
float64
(
timeCursor
))
points
=
append
(
points
,
point
)
timeCursor
+=
timeStep
points
,
err
:=
predictableSeries
(
context
.
TimeRange
,
timeStep
,
valuesLen
,
getValue
)
if
err
!=
nil
{
queryRes
.
Error
=
err
return
queryRes
}
series
.
Points
=
points
series
:=
newSeriesForQuery
(
query
)
series
.
Points
=
*
points
queryRes
.
Series
=
append
(
queryRes
.
Series
,
series
)
return
queryRes
}
func
predictableSeries
(
timeRange
*
tsdb
.
TimeRange
,
timeStep
,
length
int64
,
getValue
func
(
mod
int64
)
(
null
.
Float
,
error
))
(
*
tsdb
.
TimeSeriesPoints
,
error
)
{
points
:=
make
(
tsdb
.
TimeSeriesPoints
,
0
)
from
:=
timeRange
.
GetFromAsMsEpoch
()
to
:=
timeRange
.
GetToAsMsEpoch
()
timeCursor
:=
from
-
(
from
%
timeStep
)
// Truncate Start
wavePeriod
:=
timeStep
*
length
maxPoints
:=
10000
// Don't return too many points
for
i
:=
0
;
i
<
maxPoints
&&
timeCursor
<
to
;
i
++
{
val
,
err
:=
getValue
(
timeCursor
%
wavePeriod
)
if
err
!=
nil
{
return
&
points
,
err
}
point
:=
tsdb
.
NewTimePoint
(
val
,
float64
(
timeCursor
))
points
=
append
(
points
,
point
)
timeCursor
+=
timeStep
}
return
&
points
,
nil
}
func
getRandomWalk
(
query
*
tsdb
.
Query
,
tsdbQuery
*
tsdb
.
TsdbQuery
)
*
tsdb
.
QueryResult
{
timeWalkerMs
:=
tsdbQuery
.
TimeRange
.
GetFromAsMsEpoch
()
to
:=
tsdbQuery
.
TimeRange
.
GetToAsMsEpoch
()
...
...
@@ -541,3 +590,18 @@ func newSeriesForQuery(query *tsdb.Query) *tsdb.TimeSeries {
return
&
tsdb
.
TimeSeries
{
Name
:
alias
}
}
func
fromStringOrNumber
(
val
*
simplejson
.
Json
)
(
null
.
Float
,
error
)
{
switch
v
:=
val
.
Interface
()
.
(
type
)
{
case
json
.
Number
:
fV
,
err
:=
v
.
Float64
()
if
err
!=
nil
{
return
null
.
Float
{},
err
}
return
null
.
FloatFrom
(
fV
),
nil
case
string
:
return
null
.
FloatFromString
(
v
,
"null"
)
default
:
return
null
.
Float
{},
fmt
.
Errorf
(
"failed to extract value"
)
}
}
public/app/plugins/datasource/testdata/partials/query.editor.html
View file @
7cac393d
...
...
@@ -180,4 +180,32 @@
ng-model-onblur
/>
</div>
</div>
<!-- Predictable CSV Wave Scenario Options Form -->
<div
class=
"gf-form-inline"
ng-if=
"ctrl.scenario.id === 'predictable_csv_wave'"
>
<div
class=
"gf-form"
>
<label
class=
"gf-form-label query-keyword width-7"
>
Step
<info-popover
mode=
"right-normal"
>
The number of seconds between datapoints.
</info-popover>
</label>
<input
type=
"number"
class=
"gf-form-input width-5"
placeholder=
"60"
ng-model=
"ctrl.target.csvWave.timeStep"
ng-change=
"ctrl.refresh()"
ng-model-onblur
/>
</div>
<div
class=
"gf-form gf-form--grow"
>
<label
class=
"gf-form-label query-keyword width-10"
>
CSV Values
<info-popover
mode=
"right-normal"
>
Comma separated values. Each value may be an int, float, or null and must not be empty. Whitespace and trailing commas are removed.
</info-popover>
</label>
<input
type=
"string"
class=
"gf-form-input gf-form-label--grow"
placeholder=
"1,2,3,2"
ng-model=
"ctrl.target.csvWave.valuesCSV"
ng-change=
"ctrl.refresh()"
ng-model-onblur
/>
</div>
</div>
</query-editor-row>
public/app/plugins/datasource/testdata/query_ctrl.ts
View file @
7cac393d
...
...
@@ -13,6 +13,11 @@ export const defaultPulse: any = {
offValue
:
1
,
};
export
const
defaultCSVWave
:
any
=
{
timeStep
:
60
,
valuesCSV
:
'0,0,2,2,1,1'
,
};
export
class
TestDataQueryCtrl
extends
QueryCtrl
{
static
templateUrl
=
'partials/query.editor.html'
;
...
...
@@ -89,6 +94,12 @@ export class TestDataQueryCtrl extends QueryCtrl {
delete
this
.
target
.
pulseWave
;
}
if
(
this
.
target
.
scenarioId
===
'predictable_csv_wave'
)
{
this
.
target
.
csvWave
=
_
.
defaults
(
this
.
target
.
csvWave
||
{},
defaultCSVWave
);
}
else
{
delete
this
.
target
.
csvWave
;
}
this
.
refresh
();
}
...
...
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