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
da833cbc
Commit
da833cbc
authored
Mar 25, 2015
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Small progress on influxdb 0.9 query editor, #1525
parent
9268ecf3
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
216 additions
and
348 deletions
+216
-348
src/app/directives/graphiteSegment.js
+3
-1
src/app/plugins/datasource/graphite/queryCtrl.js
+9
-10
src/app/plugins/datasource/influxdb/datasource.js
+26
-48
src/app/plugins/datasource/influxdb/partials/query.editor.html
+62
-224
src/app/plugins/datasource/influxdb/queryCtrl.js
+116
-65
No files found.
src/app/directives/graphiteSegment.js
View file @
da833cbc
...
@@ -37,12 +37,14 @@ function (angular, app, _, $) {
...
@@ -37,12 +37,14 @@ function (angular, app, _, $) {
if
(
selected
)
{
if
(
selected
)
{
segment
.
value
=
selected
.
value
;
segment
.
value
=
selected
.
value
;
segment
.
html
=
selected
.
html
;
segment
.
html
=
selected
.
html
;
segment
.
fake
=
false
;
segment
.
expandable
=
selected
.
expandable
;
segment
.
expandable
=
selected
.
expandable
;
}
}
else
{
else
{
segment
.
value
=
value
;
segment
.
value
=
value
;
segment
.
html
=
$sce
.
trustAsHtml
(
value
);
segment
.
html
=
$sce
.
trustAsHtml
(
value
);
segment
.
expandable
=
true
;
segment
.
expandable
=
true
;
segment
.
fake
=
false
;
}
}
$scope
.
segmentValueChanged
(
segment
,
$scope
.
$index
);
$scope
.
segmentValueChanged
(
segment
,
$scope
.
$index
);
});
});
...
@@ -71,7 +73,7 @@ function (angular, app, _, $) {
...
@@ -71,7 +73,7 @@ function (angular, app, _, $) {
options
=
_
.
map
(
$scope
.
altSegments
,
function
(
alt
)
{
return
alt
.
value
;
});
options
=
_
.
map
(
$scope
.
altSegments
,
function
(
alt
)
{
return
alt
.
value
;
});
// add custom values
// add custom values
if
(
segment
.
value
!==
'select metric'
&&
_
.
indexOf
(
options
,
segment
.
value
)
===
-
1
)
{
if
(
!
segment
.
fake
&&
_
.
indexOf
(
options
,
segment
.
value
)
===
-
1
)
{
options
.
unshift
(
segment
.
value
);
options
.
unshift
(
segment
.
value
);
}
}
...
...
src/app/plugins/datasource/graphite/queryCtrl.js
View file @
da833cbc
...
@@ -113,7 +113,7 @@ function (angular, _, config, gfunc, Parser) {
...
@@ -113,7 +113,7 @@ function (angular, _, config, gfunc, Parser) {
function
checkOtherSegments
(
fromIndex
)
{
function
checkOtherSegments
(
fromIndex
)
{
if
(
fromIndex
===
0
)
{
if
(
fromIndex
===
0
)
{
$scope
.
segments
.
push
(
new
MetricSegment
(
'select metric'
));
$scope
.
segments
.
push
(
MetricSegment
.
newSelectMetric
(
));
return
;
return
;
}
}
...
@@ -123,13 +123,13 @@ function (angular, _, config, gfunc, Parser) {
...
@@ -123,13 +123,13 @@ function (angular, _, config, gfunc, Parser) {
if
(
segments
.
length
===
0
)
{
if
(
segments
.
length
===
0
)
{
if
(
path
!==
''
)
{
if
(
path
!==
''
)
{
$scope
.
segments
=
$scope
.
segments
.
splice
(
0
,
fromIndex
);
$scope
.
segments
=
$scope
.
segments
.
splice
(
0
,
fromIndex
);
$scope
.
segments
.
push
(
new
MetricSegment
(
'select metric'
));
$scope
.
segments
.
push
(
MetricSegment
.
newSelectMetric
(
));
}
}
return
;
return
;
}
}
if
(
segments
[
0
].
expandable
)
{
if
(
segments
[
0
].
expandable
)
{
if
(
$scope
.
segments
.
length
===
fromIndex
)
{
if
(
$scope
.
segments
.
length
===
fromIndex
)
{
$scope
.
segments
.
push
(
new
MetricSegment
(
'select metric'
));
$scope
.
segments
.
push
(
MetricSegment
.
newSelectMetric
(
));
}
}
else
{
else
{
return
checkOtherSegments
(
fromIndex
+
1
);
return
checkOtherSegments
(
fromIndex
+
1
);
...
@@ -238,7 +238,7 @@ function (angular, _, config, gfunc, Parser) {
...
@@ -238,7 +238,7 @@ function (angular, _, config, gfunc, Parser) {
$scope
.
moveAliasFuncLast
();
$scope
.
moveAliasFuncLast
();
$scope
.
smartlyHandleNewAliasByNode
(
newFunc
);
$scope
.
smartlyHandleNewAliasByNode
(
newFunc
);
if
(
$scope
.
segments
.
length
===
1
&&
$scope
.
segments
[
0
].
value
===
'select metric'
)
{
if
(
$scope
.
segments
.
length
===
1
&&
$scope
.
segments
[
0
].
fake
)
{
$scope
.
segments
=
[];
$scope
.
segments
=
[];
}
}
...
@@ -298,18 +298,17 @@ function (angular, _, config, gfunc, Parser) {
...
@@ -298,18 +298,17 @@ function (angular, _, config, gfunc, Parser) {
return
;
return
;
}
}
if
(
_
.
isString
(
options
))
{
this
.
fake
=
options
.
fake
;
this
.
value
=
options
;
this
.
html
=
$sce
.
trustAsHtml
(
this
.
value
);
return
;
}
this
.
value
=
options
.
value
;
this
.
value
=
options
.
value
;
this
.
type
=
options
.
type
;
this
.
type
=
options
.
type
;
this
.
expandable
=
options
.
expandable
;
this
.
expandable
=
options
.
expandable
;
this
.
html
=
$sce
.
trustAsHtml
(
templateSrv
.
highlightVariablesAsHtml
(
this
.
value
));
this
.
html
=
$sce
.
trustAsHtml
(
templateSrv
.
highlightVariablesAsHtml
(
this
.
value
));
}
}
MetricSegment
.
newSelectMetric
=
function
()
{
return
new
MetricSegment
({
value
:
'select metric'
,
fake
:
true
});
};
});
});
module
.
directive
(
'focusMe'
,
function
(
$timeout
,
$parse
)
{
module
.
directive
(
'focusMe'
,
function
(
$timeout
,
$parse
)
{
...
...
src/app/plugins/datasource/influxdb/datasource.js
View file @
da833cbc
...
@@ -36,7 +36,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
...
@@ -36,7 +36,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
var
timeFilter
=
getTimeFilter
(
options
);
var
timeFilter
=
getTimeFilter
(
options
);
var
promises
=
_
.
map
(
options
.
targets
,
function
(
target
)
{
var
promises
=
_
.
map
(
options
.
targets
,
function
(
target
)
{
if
(
target
.
hide
||
!
((
target
.
series
&&
target
.
column
)
||
target
.
query
)
)
{
if
(
target
.
hide
||
!
target
.
query
)
{
return
[];
return
[];
}
}
...
@@ -73,40 +73,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
...
@@ -73,40 +73,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
});
});
};
};
InfluxDatasource
.
prototype
.
listColumns
=
function
(
seriesName
)
{
InfluxDatasource
.
prototype
.
metricFindQuery
=
function
(
query
,
queryType
)
{
seriesName
=
templateSrv
.
replace
(
seriesName
);
if
(
!
seriesName
.
match
(
'^/.*/'
)
&&
!
seriesName
.
match
(
/^merge
\(
.*
\)
/
))
{
seriesName
=
'"'
+
seriesName
+
'"'
;
}
return
this
.
_seriesQuery
(
'select * from '
+
seriesName
+
' limit 1'
).
then
(
function
(
data
)
{
if
(
!
data
)
{
return
[];
}
return
data
[
0
].
columns
.
map
(
function
(
item
)
{
return
/^
\w
+$/
.
test
(
item
)
?
item
:
(
'"'
+
item
+
'"'
);
});
});
};
InfluxDatasource
.
prototype
.
listSeries
=
function
(
query
)
{
// wrap in regex
if
(
query
&&
query
.
length
>
0
&&
query
[
0
]
!==
'/'
)
{
query
=
'/'
+
query
+
'/'
;
}
return
this
.
_seriesQuery
(
'SHOW MEASUREMENTS'
).
then
(
function
(
data
)
{
if
(
!
data
||
data
.
length
===
0
)
{
return
[];
}
return
_
.
map
(
data
[
0
].
points
,
function
(
point
)
{
return
point
[
1
];
});
});
};
InfluxDatasource
.
prototype
.
metricFindQuery
=
function
(
query
)
{
var
interpolated
;
var
interpolated
;
try
{
try
{
interpolated
=
templateSrv
.
replace
(
query
);
interpolated
=
templateSrv
.
replace
(
query
);
...
@@ -115,17 +82,30 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
...
@@ -115,17 +82,30 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
return
$q
.
reject
(
err
);
return
$q
.
reject
(
err
);
}
}
return
this
.
_seriesQuery
(
interpolated
)
console
.
log
(
'metricFindQuery called with: '
+
[
query
,
queryType
].
join
(
', '
));
.
then
(
function
(
results
)
{
if
(
!
results
||
results
.
length
===
0
)
{
return
[];
}
return
_
.
map
(
results
[
0
].
points
,
function
(
metric
)
{
return
this
.
_seriesQuery
(
interpolated
,
queryType
).
then
(
function
(
results
)
{
return
{
if
(
!
results
||
results
.
results
.
length
===
0
)
{
return
[];
}
text
:
metric
[
1
],
expandable
:
false
var
influxResults
=
results
.
results
[
0
];
};
if
(
!
influxResults
.
series
)
{
});
return
[];
});
}
console
.
log
(
'metric find query response'
,
results
);
var
series
=
influxResults
.
series
[
0
];
switch
(
queryType
)
{
case
'MEASUREMENTS'
:
return
_
.
map
(
series
.
values
,
function
(
value
)
{
return
{
text
:
value
[
0
],
expandable
:
true
};
});
case
'TAG_KEYS'
:
var
tagKeys
=
_
.
flatten
(
series
.
values
);
return
_
.
map
(
tagKeys
,
function
(
tagKey
)
{
return
{
text
:
tagKey
,
expandable
:
true
};
});
case
'TAG_VALUES'
:
var
tagValues
=
_
.
flatten
(
series
.
values
);
return
_
.
map
(
tagValues
,
function
(
tagValue
)
{
return
{
text
:
tagValue
,
expandable
:
true
};
});
}
});
};
};
function
retry
(
deferred
,
callback
,
delay
)
{
function
retry
(
deferred
,
callback
,
delay
)
{
...
@@ -143,9 +123,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
...
@@ -143,9 +123,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
}
}
InfluxDatasource
.
prototype
.
_seriesQuery
=
function
(
query
)
{
InfluxDatasource
.
prototype
.
_seriesQuery
=
function
(
query
)
{
return
this
.
_influxRequest
(
'GET'
,
'/query'
,
{
return
this
.
_influxRequest
(
'GET'
,
'/query'
,
{
q
:
query
});
q
:
query
,
});
};
};
InfluxDatasource
.
prototype
.
_influxRequest
=
function
(
method
,
url
,
data
)
{
InfluxDatasource
.
prototype
.
_influxRequest
=
function
(
method
,
url
,
data
)
{
...
...
src/app/plugins/datasource/influxdb/partials/query.editor.html
View file @
da833cbc
<div
class=
"editor-row"
>
<div
class=
"editor-row"
>
<div
ng-repeat=
"target in panel.targets"
ng-controller=
"InfluxQueryCtrl"
ng-init=
"init()"
ng-class=
"{'tight-form-disabled': target.hide}"
class=
"tight-form-container"
>
<div
class=
"tight-form"
>
<div
ng-repeat=
"target in panel.targets"
<ul
class=
"tight-form-list pull-right"
>
class=
"tight-form"
<li
class=
"tight-form-item"
>
ng-class=
"{'tight-form-disabled': target.hide}"
ng-controller=
"InfluxQueryCtrl"
ng-init=
"init()"
>
<ul
class=
"tight-form-list pull-right"
>
<li
ng-show=
"parserError"
class=
"tight-form-item"
>
<a
bs-tooltip=
"parserError"
style=
"color: rgb(229, 189, 28)"
role=
"menuitem"
>
<i
class=
"fa fa-warning"
></i>
</a>
</li>
<li
class=
"tight-form-item"
>
<a
class=
"pointer"
tabindex=
"1"
ng-click=
"toggleQueryMode()"
>
<i
class=
"fa fa-pencil"
></i>
</a>
</li>
<li
class=
"tight-form-item"
>
<div
class=
"dropdown"
>
<div
class=
"dropdown"
>
<a
class=
"pointer dropdown-toggle"
<a
class=
"pointer dropdown-toggle"
data-toggle=
"dropdown"
data-toggle=
"dropdown"
tabindex=
"1"
>
tabindex=
"1"
>
<i
class=
"fa fa-bars"
></i>
<i
class=
"fa fa-bars"
></i>
</a>
</a>
<ul
class=
"dropdown-menu pull-right"
role=
"menu"
>
<ul
class=
"dropdown-menu pull-right"
role=
"menu"
>
<li
role=
"menuitem"
><a
tabindex=
"1"
ng-click=
"duplicate()"
>
Duplicate
</a></li>
<li
role=
"menuitem"
>
<li
role=
"menuitem"
><a
tabindex=
"1"
ng-click=
"moveMetricQuery($index, $index-1)"
>
Move up
</a></li>
<a
tabindex=
"1"
<li
role=
"menuitem"
><a
tabindex=
"1"
ng-click=
"moveMetricQuery($index, $index+1)"
>
Move down
</a></li>
ng-click=
"duplicate()"
>
Duplicate
</a>
</li>
<li
role=
"menuitem"
>
<a
tabindex=
"1"
ng-click=
"moveMetricQuery($index, $index-1)"
>
Move up
</a>
</li>
<li
role=
"menuitem"
>
<a
tabindex=
"1"
ng-click=
"moveMetricQuery($index, $index+1)"
>
Move down
</a>
</li>
</ul>
</ul>
</div>
</div>
</li>
</li>
...
@@ -24,231 +53,40 @@
...
@@ -24,231 +53,40 @@
</ul>
</ul>
<ul
class=
"tight-form-list"
>
<ul
class=
"tight-form-list"
>
<li
class=
"tight-form-item"
style=
"min-width: 15px; text-align: center"
>
{{targetLetters[$index]}}
</li>
<li>
<li>
<a
class=
"tight-form-item"
ng-click=
"target.hide = !target.hide; get_data();"
role=
"menuitem"
>
<a
class=
"tight-form-item"
ng-click=
"target.hide = !target.hide; get_data();"
role=
"menuitem"
>
<i
class=
"fa fa-eye"
></i>
<i
class=
"fa fa-eye"
></i>
</a>
</a>
</li>
</li>
</ul>
</ul>
<!-- Raw Query mode -->
<input
type=
"text"
<ul
class=
"tight-form-list"
ng-show=
"target.rawQuery"
>
class=
"tight-form-clear-input span10"
<li>
ng-model=
"target.query"
<input
type=
"text"
focus-me=
"target.rawQuery"
class=
"tight-form-input span10"
spellcheck=
'false'
ng-model=
"target.query"
ng-model-onblur
ng-change=
"targetTextChanged()"
placeholder=
"select ..."
ng-show=
"target.rawQuery"
/>
focus-me=
"target.rawQuery"
spellcheck=
'false'
<ul
class=
"tight-form-list"
role=
"menu"
ng-hide=
"target.rawQuery"
>
data-min-length=
0
data-items=
100
<li
ng-repeat=
"segment in segments"
role=
"menuitem"
graphite-segment
></li>
ng-model-onblur
<li
ng-repeat=
"func in functions"
>
ng-blur=
"get_data()"
>
<span
graphite-func-editor
class=
"tight-form-item tight-form-func"
>
</li>
</span>
</ul>
</li>
<li
class=
"dropdown"
graphite-add-func
>
<!-- Query editor mode -->
</li>
<ul
class=
"tight-form-list"
role=
"menu"
ng-hide=
"target.rawQuery"
>
</ul>
<li
class=
"tight-form-item"
>
<div
class=
"clearfix"
></div>
series
</div>
</li>
<li>
<input
type=
"text"
class=
"tight-form-input span8"
ng-model=
"target.series"
spellcheck=
'false'
bs-typeahead=
"listSeries"
match-all=
"true"
min-length=
"3"
placeholder=
"series name"
data-min-length=
0
data-items=
100
ng-blur=
"seriesBlur()"
>
</li>
<li
class=
"tight-form-item"
>
alias
</li>
<li>
<input
type=
"text"
class=
"input-medium tight-form-input"
ng-model=
"target.alias"
spellcheck=
'false'
placeholder=
"alias"
ng-blur=
"get_data()"
>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
<div
class=
"tight-form"
>
<!-- Raw Query mode -->
<ul
class=
"tight-form-list"
ng-show=
"target.rawQuery"
>
<li
class=
"tight-form-item"
>
<i
class=
"fa fa-eye invisible"
></i>
</li>
<li
class=
"tight-form-item"
>
alias
</li>
<li>
<input
type=
"text"
class=
"input-medium tight-form-input"
ng-model=
"target.alias"
spellcheck=
'false'
placeholder=
"alias"
ng-blur=
"get_data()"
>
</li>
<li
class=
"tight-form-item"
>
group by time
</li>
<li>
<input
type=
"text"
class=
"input-mini tight-form-input"
ng-model=
"target.interval"
spellcheck=
'false'
placeholder=
"{{interval}}"
data-placement=
"right"
bs-tooltip=
"'Leave blank for auto handling based on time range and panel width'"
ng-model-onblur
ng-change=
"get_data()"
>
</li>
</ul>
<!-- Query editor mode -->
<ul
class=
"tight-form-list"
role=
"menu"
ng-hide=
"target.rawQuery"
>
<li
class=
"tight-form-item"
>
<i
class=
"fa fa-eye invisible"
></i>
</li>
<li
class=
"tight-form-item"
>
select
</li>
<li
class=
"dropdown"
>
<span
influxdb-func-editor
class=
"tight-form-item tight-form-func"
>
</span>
</li>
<li
class=
"tight-form-item"
>
where
</li>
<li>
<input
type=
"text"
class=
"input-medium tight-form-input"
ng-model=
"target.condition"
bs-tooltip=
"'Add a where clause'"
data-placement=
"right"
spellcheck=
'false'
placeholder=
"column ~= value"
ng-blur=
"get_data()"
>
</li>
<li
class=
"tight-form-item"
>
group by time
</li>
<li>
<input
type=
"text"
class=
"input-mini tight-form-input"
ng-model=
"target.interval"
spellcheck=
'false'
placeholder=
"{{interval}}"
data-placement=
"right"
bs-tooltip=
"'Leave blank for auto handling based on time range and panel width'"
ng-model-onblur
ng-change=
"get_data()"
>
</li>
<li
class=
"tight-form-item"
>
and
</li>
<li>
<input
type=
"text"
class=
"input-small tight-form-input"
ng-model=
"target.groupby_field"
bs-tooltip=
"'Add a group by column or leave blank'"
placeholder=
"column"
spellcheck=
"false"
bs-typeahead=
"listColumns"
data-min-length=
0
ng-blur=
"get_data()"
>
</li>
<li
class=
"dropdown"
>
<a
class=
"tight-form-item pointer"
data-toggle=
"dropdown"
bs-tooltip=
"'Insert missing values, important when stacking'"
data-placement=
"right"
>
<span
ng-show=
"target.fill"
>
fill ({{target.fill}})
</span>
<span
ng-show=
"!target.fill"
>
no fill
</span>
</a>
<ul
class=
"dropdown-menu"
>
<li><a
ng-click=
"target.fill = ''"
>
no fill
</a></li>
<li><a
ng-click=
"target.fill = 'null'"
>
fill (null)
</a></li>
<li><a
ng-click=
"target.fill = '0'"
>
fill (0)
</a></li>
</ul>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
</div>
</div>
</div>
<section
class=
"grafana-metric-options"
>
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
>
<li
class=
"tight-form-item tight-form-item-icon"
>
<i
class=
"fa fa-wrench"
></i>
</li>
<li
class=
"tight-form-item"
>
group by time
</li>
<li>
<input
type=
"text"
class=
"input-medium tight-form-input"
ng-model=
"panel.interval"
ng-blur=
"get_data();"
spellcheck=
'false'
placeholder=
"example: >10s"
>
</li>
<li
class=
"tight-form-item"
>
<i
class=
"fa fa-question-circle"
bs-tooltip=
"'Set a low limit by having a greater sign: example: >60s'"
data-placement=
"right"
></i>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
>
<li
class=
"tight-form-item tight-form-item-icon"
>
<i
class=
"fa fa-info-circle"
></i>
</li>
<li
class=
"tight-form-item"
>
<a
ng-click=
"toggleEditorHelp(1);"
bs-tooltip=
"'click to show helpful info'"
data-placement=
"bottom"
>
alias patterns
</a>
</li>
<li
class=
"tight-form-item"
>
<a
ng-click=
"toggleEditorHelp(2)"
bs-tooltip=
"'click to show helpful info'"
data-placement=
"bottom"
>
stacking
&
and fill
</a>
</li>
<li
class=
"tight-form-item"
>
<a
ng-click=
"toggleEditorHelp(3)"
bs-tooltip=
"'click to show helpful info'"
data-placement=
"bottom"
>
group by time
</a>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
</section>
<div
class=
"editor-row"
>
<div
class=
"editor-row"
>
<div
class=
"pull-left"
style=
"margin-top: 30px;"
>
<div
class=
"pull-left"
style=
"margin-top: 30px;"
>
<div
class=
"grafana-info-box span6"
ng-if=
"editorHelpIndex === 1"
>
<h5>
Alias patterns
</h5>
<ul>
<li>
$s = series name
</li>
<li>
$g = group by
</li>
<li>
$[0-9] part of series name for series names seperated by dots.
</li>
</ul>
</div>
<div
class=
"grafana-info-box span6"
ng-if=
"editorHelpIndex === 2"
>
<h5>
Stacking and fill
</h5>
<ul>
<li>
When stacking is enabled it important that points align
</li>
<li>
If there are missing points for one series it can cause gaps or missing bars
</li>
<li>
You must use fill(0), and select a group by time low limit
</li>
<li>
Use the group by time option below your queries and specify for example
>
10s if your metrics are written every 10 seconds
</li>
<li>
This will insert zeros for series that are missing measurements and will make stacking work properly
</li>
</ul>
</div>
<div
class=
"grafana-info-box span6"
ng-if=
"editorHelpIndex === 3"
>
<h5>
Group by time
</h5>
<ul>
<li>
Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana
</li>
<li>
Leave the group by time field empty for each query and it will be calculated based on time range and pixel width of the graph
</li>
<li>
If you use fill(0) or fill(null) set a low limit for the auto group by time interval
</li>
<li>
The low limit can only be set in the group by time option below your queries
</li>
<li>
You set a low limit by adding a greater sign before the interval
</li>
<li>
Example:
>
60s if you write metrics to InfluxDB every 60 seconds
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
src/app/plugins/datasource/influxdb/queryCtrl.js
View file @
da833cbc
...
@@ -7,102 +7,153 @@ function (angular, _) {
...
@@ -7,102 +7,153 @@ function (angular, _) {
var
module
=
angular
.
module
(
'grafana.controllers'
);
var
module
=
angular
.
module
(
'grafana.controllers'
);
var
seriesList
=
null
;
module
.
controller
(
'InfluxQueryCtrl'
,
function
(
$scope
,
$timeout
,
$sce
,
templateSrv
,
$q
)
{
module
.
controller
(
'InfluxQueryCtrl'
,
function
(
$scope
,
$timeout
)
{
$scope
.
init
=
function
()
{
$scope
.
init
=
function
()
{
var
target
=
$scope
.
target
;
$scope
.
segments
=
$scope
.
target
.
segments
||
[];
target
.
function
=
target
.
function
||
'mean'
;
target
.
column
=
target
.
column
||
'value'
;
// backward compatible correction of schema
if
(
target
.
condition_value
)
{
target
.
condition
=
target
.
condition_key
+
' '
+
target
.
condition_op
+
' '
+
target
.
condition_value
;
delete
target
.
condition_key
;
delete
target
.
condition_op
;
delete
target
.
condition_value
;
}
if
(
target
.
groupby_field_add
===
false
)
{
target
.
groupby_field
=
''
;
delete
target
.
groupby_field_add
;
}
$scope
.
rawQuery
=
true
;
$scope
.
functionsSelect
=
[
$scope
.
functions
=
[
'count'
,
'mean'
,
'sum'
,
'min'
,
'count'
,
'mean'
,
'sum'
,
'min'
,
'max'
,
'mode'
,
'distinct'
,
'median'
,
'max'
,
'mode'
,
'distinct'
,
'median'
,
'derivative'
,
'stddev'
,
'first'
,
'last'
,
'derivative'
,
'stddev'
,
'first'
,
'last'
,
'difference'
'difference'
];
];
$scope
.
operators
=
[
'='
,
'=~'
,
'>'
,
'<'
,
'!~'
,
'<>'
];
checkOtherSegments
(
0
);
$scope
.
oldSeries
=
target
.
series
;
$scope
.
$on
(
'typeahead-updated'
,
function
()
{
$timeout
(
$scope
.
get_data
);
});
};
};
$scope
.
showQuery
=
function
()
{
$scope
.
toggleQueryMode
=
function
()
{
$scope
.
target
.
rawQuery
=
true
;
$scope
.
target
.
rawQuery
=
!
$scope
.
target
.
rawQuery
;
};
};
$scope
.
hideQuery
=
function
(
)
{
$scope
.
moveMetricQuery
=
function
(
fromIndex
,
toIndex
)
{
$scope
.
target
.
rawQuery
=
false
;
_
.
move
(
$scope
.
panel
.
targets
,
fromIndex
,
toIndex
)
;
};
};
// Cannot use typeahead and ng-change on blur at the same time
$scope
.
duplicate
=
function
()
{
$scope
.
seriesBlur
=
function
()
{
var
clone
=
angular
.
copy
(
$scope
.
target
);
if
(
$scope
.
oldSeries
!==
$scope
.
target
.
series
)
{
$scope
.
panel
.
targets
.
push
(
clone
);
$scope
.
oldSeries
=
$scope
.
target
.
series
;
$scope
.
columnList
=
null
;
$scope
.
get_data
();
}
};
};
$scope
.
changeFunction
=
function
(
func
)
{
$scope
.
getAltSegments
=
function
(
index
)
{
$scope
.
target
.
function
=
func
;
$scope
.
altSegments
=
[];
$scope
.
get_data
();
var
measurement
=
$scope
.
segments
[
0
].
value
;
var
queryType
,
query
;
if
(
index
===
0
)
{
queryType
=
'MEASUREMENTS'
;
query
=
'SHOW MEASUREMENTS'
;
}
else
if
(
index
%
2
===
1
)
{
queryType
=
'TAG_KEYS'
;
query
=
'SHOW TAG KEYS FROM '
+
measurement
;
}
else
{
queryType
=
'TAG_VALUES'
;
query
=
"SHOW TAG VALUES FROM "
+
measurement
+
" WITH KEY = "
+
$scope
.
segments
[
$scope
.
segments
.
length
-
2
].
value
;
}
console
.
log
(
'getAltSegments: query'
,
query
);
return
$scope
.
datasource
.
metricFindQuery
(
query
,
queryType
).
then
(
function
(
results
)
{
console
.
log
(
'get alt segments: response'
,
results
);
$scope
.
altSegments
=
_
.
map
(
results
,
function
(
segment
)
{
return
new
MetricSegment
({
value
:
segment
.
text
,
expandable
:
segment
.
expandable
});
});
_
.
each
(
templateSrv
.
variables
,
function
(
variable
)
{
$scope
.
altSegments
.
unshift
(
new
MetricSegment
({
type
:
'template'
,
value
:
'$'
+
variable
.
name
,
expandable
:
true
,
}));
});
},
function
(
err
)
{
$scope
.
parserError
=
err
.
message
||
'Failed to issue metric query'
;
});
};
};
// called outside of digest
$scope
.
segmentValueChanged
=
function
(
segment
,
segmentIndex
)
{
$scope
.
listColumns
=
function
(
query
,
callback
)
{
delete
$scope
.
parserError
;
if
(
!
$scope
.
columnList
)
{
$scope
.
$apply
(
function
()
{
if
(
segment
.
expandable
)
{
$scope
.
datasource
.
listColumns
(
$scope
.
target
.
series
).
then
(
function
(
columns
)
{
return
checkOtherSegments
(
segmentIndex
+
1
).
then
(
function
()
{
$scope
.
columnList
=
columns
;
setSegmentFocus
(
segmentIndex
+
1
);
callback
(
columns
);
$scope
.
targetChanged
();
});
});
});
}
}
else
{
else
{
return
$scope
.
columnList
;
$scope
.
segments
=
$scope
.
segments
.
splice
(
0
,
segmentIndex
+
1
)
;
}
}
setSegmentFocus
(
segmentIndex
+
1
);
$scope
.
targetChanged
();
};
};
$scope
.
listSeries
=
function
(
query
,
callback
)
{
$scope
.
targetChanged
=
function
()
{
if
(
query
!==
''
)
{
if
(
$scope
.
parserError
)
{
seriesList
=
[];
return
;
$scope
.
datasource
.
listSeries
(
query
).
then
(
function
(
series
)
{
seriesList
=
series
;
callback
(
seriesList
);
});
}
}
else
{
return
seriesList
;
$scope
.
$parent
.
get_data
();
};
function
checkOtherSegments
(
fromIndex
)
{
if
(
fromIndex
===
0
)
{
$scope
.
segments
.
push
(
MetricSegment
.
newSelectMetric
());
return
;
}
if
(
$scope
.
segments
.
length
===
0
)
{
throw
(
'should always have a scope segment?'
);
}
if
(
_
.
last
(
$scope
.
segments
).
fake
)
{
return
$q
.
when
([]);
}
else
if
(
$scope
.
segments
.
length
%
2
===
1
)
{
$scope
.
segments
.
push
(
MetricSegment
.
newSelectTag
());
return
$q
.
when
([]);
}
else
{
$scope
.
segments
.
push
(
MetricSegment
.
newSelectTagValue
());
return
$q
.
when
([]);
}
}
function
setSegmentFocus
(
segmentIndex
)
{
_
.
each
(
$scope
.
segments
,
function
(
segment
,
index
)
{
segment
.
focus
=
segmentIndex
===
index
;
});
}
function
MetricSegment
(
options
)
{
if
(
options
===
'*'
||
options
.
value
===
'*'
)
{
this
.
value
=
'*'
;
this
.
html
=
$sce
.
trustAsHtml
(
'<i class="fa fa-asterisk"><i>'
);
this
.
expandable
=
true
;
return
;
}
if
(
_
.
isString
(
options
))
{
this
.
value
=
options
;
this
.
html
=
$sce
.
trustAsHtml
(
this
.
value
);
return
;
}
}
this
.
fake
=
options
.
fake
;
this
.
value
=
options
.
value
;
this
.
type
=
options
.
type
;
this
.
expandable
=
options
.
expandable
;
this
.
html
=
$sce
.
trustAsHtml
(
templateSrv
.
highlightVariablesAsHtml
(
this
.
value
));
}
MetricSegment
.
newSelectMetric
=
function
()
{
return
new
MetricSegment
({
value
:
'select metric'
,
fake
:
true
});
};
};
$scope
.
moveMetricQuery
=
function
(
fromIndex
,
toIndex
)
{
MetricSegment
.
newSelectTag
=
function
(
)
{
_
.
move
(
$scope
.
panel
.
targets
,
fromIndex
,
toIndex
);
return
new
MetricSegment
({
value
:
'select tag'
,
fake
:
true
}
);
};
};
$scope
.
duplicate
=
function
()
{
MetricSegment
.
newSelectTagValue
=
function
()
{
var
clone
=
angular
.
copy
(
$scope
.
target
);
return
new
MetricSegment
({
value
:
'select tag value'
,
fake
:
true
});
$scope
.
panel
.
targets
.
push
(
clone
);
};
};
});
});
...
...
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