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
a4daba63
Commit
a4daba63
authored
Oct 04, 2017
by
Alexander Zobnin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
graphite-tags: initial tag editor
parent
0c31c7b1
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
212 additions
and
1 deletions
+212
-1
public/app/plugins/datasource/graphite/datasource.ts
+54
-0
public/app/plugins/datasource/graphite/partials/query.editor.html
+13
-1
public/app/plugins/datasource/graphite/query_ctrl.ts
+145
-0
No files found.
public/app/plugins/datasource/graphite/datasource.ts
View file @
a4daba63
...
...
@@ -200,6 +200,60 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv
});
};
this
.
getTags
=
function
(
optionalOptions
)
{
let
options
=
optionalOptions
||
{};
let
httpOptions
:
any
=
{
method
:
'GET'
,
url
:
'/tags'
,
// for cancellations
requestId
:
options
.
requestId
,
};
if
(
options
&&
options
.
range
)
{
httpOptions
.
params
.
from
=
this
.
translateTime
(
options
.
range
.
from
,
false
);
httpOptions
.
params
.
until
=
this
.
translateTime
(
options
.
range
.
to
,
true
);
}
return
this
.
doGraphiteRequest
(
httpOptions
).
then
(
results
=>
{
return
_
.
map
(
results
.
data
,
tag
=>
{
return
{
text
:
tag
.
tag
,
id
:
tag
.
id
};
});
});
};
this
.
getTagValues
=
function
(
tag
,
optionalOptions
)
{
let
options
=
optionalOptions
||
{};
let
httpOptions
:
any
=
{
method
:
'GET'
,
url
:
'/tags/'
+
tag
,
// for cancellations
requestId
:
options
.
requestId
,
};
if
(
options
&&
options
.
range
)
{
httpOptions
.
params
.
from
=
this
.
translateTime
(
options
.
range
.
from
,
false
);
httpOptions
.
params
.
until
=
this
.
translateTime
(
options
.
range
.
to
,
true
);
}
return
this
.
doGraphiteRequest
(
httpOptions
).
then
(
results
=>
{
if
(
results
.
data
&&
results
.
data
.
values
)
{
return
_
.
map
(
results
.
data
.
values
,
value
=>
{
return
{
text
:
value
.
value
,
id
:
value
.
id
};
});
}
else
{
return
[];
}
});
};
this
.
testDatasource
=
function
()
{
return
this
.
metricFindQuery
(
'*'
).
then
(
function
()
{
return
{
status
:
"success"
,
message
:
"Data source is working"
};
...
...
public/app/plugins/datasource/graphite/partials/query.editor.html
View file @
a4daba63
...
...
@@ -6,12 +6,24 @@
<div
ng-hide=
"ctrl.target.textEditor"
>
<div
class=
"gf-form-inline"
>
<div
class=
"gf-form"
ng-if=
"ctrl.seriesByTagUsed"
>
<label
class=
"gf-form-label query-keyword"
>
seriesByTag
</label>
</div>
<div
ng-repeat=
"tagSegment in ctrl.tagSegments"
role=
"menuitem"
class=
"gf-form"
>
<metric-segment
segment=
"tagSegment"
get-options=
"ctrl.getAltTagSegments($index)"
on-change=
"ctrl.tagSegmentChanged(tagSegment, $index)"
>
</metric-segment>
<label
class=
"gf-form-label query-keyword"
ng-if=
"ctrl.showDelimiter($index)"
>
,
</label>
</div>
<div
ng-repeat=
"segment in ctrl.segments"
role=
"menuitem"
class=
"gf-form"
>
<metric-segment
segment=
"segment"
get-options=
"ctrl.getAltSegments($index)"
on-change=
"ctrl.segmentValueChanged(segment, $index)"
></metric-segment>
</div>
<div
ng-repeat=
"func in ctrl.functions"
class=
"gf-form"
>
<span
graphite-func-editor
class=
"gf-form-label query-part"
></span>
<span
graphite-func-editor
class=
"gf-form-label query-part"
ng-hide=
"ctrl.getSeriesByTagFuncIndex() === $index"
></span>
</div>
<div
class=
"gf-form dropdown"
>
...
...
public/app/plugins/datasource/graphite/query_ctrl.ts
View file @
a4daba63
...
...
@@ -12,6 +12,9 @@ export class GraphiteQueryCtrl extends QueryCtrl {
functions
:
any
[];
segments
:
any
[];
tagSegments
:
any
[];
seriesByTagUsed
:
boolean
;
removeTagSegment
:
any
;
/** @ngInject **/
constructor
(
$scope
,
$injector
,
private
uiSegmentSrv
,
private
templateSrv
)
{
...
...
@@ -21,6 +24,8 @@ export class GraphiteQueryCtrl extends QueryCtrl {
this
.
target
.
target
=
this
.
target
.
target
||
''
;
this
.
parseTarget
();
}
this
.
removeTagSegment
=
uiSegmentSrv
.
newSegment
({
fake
:
true
,
value
:
'-- remove tag --'
});
}
toggleEditorMode
()
{
...
...
@@ -59,6 +64,7 @@ export class GraphiteQueryCtrl extends QueryCtrl {
}
this
.
checkOtherSegments
(
this
.
segments
.
length
-
1
);
this
.
checkForSeriesByTag
();
}
addFunctionParameter
(
func
,
value
,
index
,
shiftBack
)
{
...
...
@@ -114,6 +120,40 @@ export class GraphiteQueryCtrl extends QueryCtrl {
return
func
.
def
.
name
!==
'seriesByTag'
;
}
checkForSeriesByTag
()
{
let
seriesByTagFunc
=
_
.
find
(
this
.
functions
,
(
func
)
=>
func
.
def
.
name
===
'seriesByTag'
);
if
(
seriesByTagFunc
)
{
this
.
seriesByTagUsed
=
true
;
let
tags
=
this
.
splitSeriesByTagParams
(
seriesByTagFunc
);
this
.
tagSegments
=
[];
_
.
each
(
tags
,
(
tag
)
=>
{
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newKey
(
tag
.
key
));
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newOperator
(
tag
.
operator
));
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newKeyValue
(
tag
.
value
));
});
this
.
fixTagSegments
();
}
}
splitSeriesByTagParams
(
func
)
{
const
tagPattern
=
/
([^\!
=~
]
+
)([\!
=~
]
+
)([^\!
=~
]
+
)
/
;
return
_
.
flatten
(
_
.
map
(
func
.
params
,
(
param
:
string
)
=>
{
let
matches
=
tagPattern
.
exec
(
param
);
if
(
matches
)
{
let
tag
=
matches
.
slice
(
1
);
if
(
tag
.
length
===
3
)
{
return
{
key
:
tag
[
0
],
operator
:
tag
[
1
],
value
:
tag
[
2
]
}
}
}
return
[];
}));
}
getSegmentPathUpTo
(
index
)
{
var
arr
=
this
.
segments
.
slice
(
0
,
index
);
...
...
@@ -161,6 +201,36 @@ export class GraphiteQueryCtrl extends QueryCtrl {
return
func
.
render
(
target
);
}
getAltTagSegments
(
index
)
{
let
paramPartIndex
=
getParamPartIndex
(
index
);
if
(
paramPartIndex
===
1
)
{
// Operator
let
operators
=
[
'='
,
'!='
,
'=~'
,
'!=~'
];
let
segments
=
_
.
map
(
operators
,
(
operator
)
=>
this
.
uiSegmentSrv
.
newOperator
(
operator
));
return
Promise
.
resolve
(
segments
);
}
else
if
(
paramPartIndex
===
0
)
{
// Tag
return
this
.
datasource
.
getTags
().
then
(
segments
=>
{
let
altSegments
=
_
.
map
(
segments
,
segment
=>
{
return
this
.
uiSegmentSrv
.
newSegment
({
value
:
segment
.
text
,
expandable
:
false
});
});
altSegments
.
splice
(
0
,
0
,
_
.
cloneDeep
(
this
.
removeTagSegment
));
return
altSegments
;
});
}
else
{
// Tag value
let
relatedTagSegmentIndex
=
getRelatedTagSegmentIndex
(
index
);
let
tag
=
this
.
tagSegments
[
relatedTagSegmentIndex
].
value
;
return
this
.
datasource
.
getTagValues
(
tag
).
then
(
segments
=>
{
let
altSegments
=
_
.
map
(
segments
,
segment
=>
{
return
this
.
uiSegmentSrv
.
newSegment
({
value
:
segment
.
text
,
expandable
:
false
});
});
return
altSegments
;
});
}
}
getAltSegments
(
index
)
{
var
query
=
index
===
0
?
'*'
:
this
.
getSegmentPathUpTo
(
index
)
+
'.*'
;
var
options
=
{
range
:
this
.
panelCtrl
.
range
,
requestId
:
"get-alt-segments"
};
...
...
@@ -209,6 +279,52 @@ export class GraphiteQueryCtrl extends QueryCtrl {
this
.
targetChanged
();
}
tagSegmentChanged
(
tagSegment
,
segmentIndex
)
{
this
.
error
=
null
;
if
(
tagSegment
.
value
===
this
.
removeTagSegment
.
value
)
{
this
.
removeTag
(
segmentIndex
);
return
;
}
if
(
tagSegment
.
type
===
'plus-button'
)
{
let
newTag
=
{
key
:
tagSegment
.
value
,
operator
:
'='
,
value
:
'select tag value'
};
this
.
tagSegments
.
splice
(
this
.
tagSegments
.
length
-
1
,
1
);
this
.
addNewTag
(
newTag
);
}
let
paramIndex
=
getParamIndex
(
segmentIndex
);
let
newTagParam
=
this
.
renderTagParam
(
segmentIndex
);
this
.
functions
[
this
.
getSeriesByTagFuncIndex
()].
params
[
paramIndex
]
=
newTagParam
;
this
.
targetChanged
();
this
.
parseTarget
();
}
getSeriesByTagFuncIndex
()
{
return
_
.
findIndex
(
this
.
functions
,
(
func
)
=>
func
.
def
.
name
===
'seriesByTag'
);
}
addNewTag
(
tag
)
{
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newKey
(
tag
.
key
));
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newOperator
(
tag
.
operator
));
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newKeyValue
(
tag
.
value
));
}
removeTag
(
index
)
{
let
paramIndex
=
getParamIndex
(
index
);
this
.
tagSegments
.
splice
(
index
,
3
);
this
.
functions
[
this
.
getSeriesByTagFuncIndex
()].
params
.
splice
(
paramIndex
,
1
);
this
.
targetChanged
();
this
.
parseTarget
();
}
renderTagParam
(
segmentIndex
)
{
let
tagIndex
=
getRelatedTagSegmentIndex
(
segmentIndex
)
return
_
.
map
(
this
.
tagSegments
.
slice
(
tagIndex
,
tagIndex
+
3
),
(
segment
)
=>
segment
.
value
).
join
(
''
);
}
targetTextChanged
()
{
this
.
updateModelTarget
();
this
.
refresh
();
...
...
@@ -304,6 +420,10 @@ export class GraphiteQueryCtrl extends QueryCtrl {
if
(
!
newFunc
.
params
.
length
&&
newFunc
.
added
)
{
this
.
targetChanged
();
}
if
(
newFunc
.
def
.
name
===
'seriesByTag'
)
{
this
.
parseTarget
();
}
}
moveAliasFuncLast
()
{
...
...
@@ -333,4 +453,29 @@ export class GraphiteQueryCtrl extends QueryCtrl {
}
}
}
fixTagSegments
()
{
var
count
=
this
.
tagSegments
.
length
;
var
lastSegment
=
this
.
tagSegments
[
Math
.
max
(
count
-
1
,
0
)];
if
(
!
lastSegment
||
lastSegment
.
type
!==
'plus-button'
)
{
this
.
tagSegments
.
push
(
this
.
uiSegmentSrv
.
newPlusButton
());
}
}
showDelimiter
(
index
)
{
return
getParamPartIndex
(
index
)
===
2
&&
index
!==
this
.
tagSegments
.
length
-
2
;
}
}
function
getParamIndex
(
segmentIndex
)
{
return
Math
.
floor
(
segmentIndex
/
3
);
}
function
getParamPartIndex
(
segmentIndex
)
{
return
segmentIndex
%
3
;
}
function
getRelatedTagSegmentIndex
(
segmentIndex
)
{
return
getParamIndex
(
segmentIndex
)
*
3
;
}
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