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
25d93d10
Commit
25d93d10
authored
Dec 15, 2015
by
Carl Bergquist
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #3066 from mtanda/cloudwatch_annotation
(cloudwatch) annotation support
parents
e28c9b33
31de9faa
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
502 additions
and
222 deletions
+502
-222
pkg/api/cloudwatch/cloudwatch.go
+101
-7
public/app/plugins/datasource/cloudwatch/datasource.js
+76
-4
public/app/plugins/datasource/cloudwatch/directives.js
+18
-0
public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html
+1
-0
public/app/plugins/datasource/cloudwatch/partials/query.editor.html
+1
-46
public/app/plugins/datasource/cloudwatch/partials/query.parameter.html
+53
-0
public/app/plugins/datasource/cloudwatch/plugin.json
+2
-1
public/app/plugins/datasource/cloudwatch/query_ctrl.js
+1
-164
public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.js
+192
-0
public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts
+57
-0
No files found.
pkg/api/cloudwatch/cloudwatch.go
View file @
25d93d10
...
@@ -31,13 +31,15 @@ type cwRequest struct {
...
@@ -31,13 +31,15 @@ type cwRequest struct {
func
init
()
{
func
init
()
{
actionHandlers
=
map
[
string
]
actionHandler
{
actionHandlers
=
map
[
string
]
actionHandler
{
"GetMetricStatistics"
:
handleGetMetricStatistics
,
"GetMetricStatistics"
:
handleGetMetricStatistics
,
"ListMetrics"
:
handleListMetrics
,
"ListMetrics"
:
handleListMetrics
,
"DescribeInstances"
:
handleDescribeInstances
,
"DescribeAlarmsForMetric"
:
handleDescribeAlarmsForMetric
,
"__GetRegions"
:
handleGetRegions
,
"DescribeAlarmHistory"
:
handleDescribeAlarmHistory
,
"__GetNamespaces"
:
handleGetNamespaces
,
"DescribeInstances"
:
handleDescribeInstances
,
"__GetMetrics"
:
handleGetMetrics
,
"__GetRegions"
:
handleGetRegions
,
"__GetDimensions"
:
handleGetDimensions
,
"__GetNamespaces"
:
handleGetNamespaces
,
"__GetMetrics"
:
handleGetMetrics
,
"__GetDimensions"
:
handleGetDimensions
,
}
}
}
}
...
@@ -137,6 +139,98 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
...
@@ -137,6 +139,98 @@ func handleListMetrics(req *cwRequest, c *middleware.Context) {
c
.
JSON
(
200
,
resp
)
c
.
JSON
(
200
,
resp
)
}
}
func
handleDescribeAlarmsForMetric
(
req
*
cwRequest
,
c
*
middleware
.
Context
)
{
sess
:=
session
.
New
()
creds
:=
credentials
.
NewChainCredentials
(
[]
credentials
.
Provider
{
&
credentials
.
EnvProvider
{},
&
credentials
.
SharedCredentialsProvider
{
Filename
:
""
,
Profile
:
req
.
DataSource
.
Database
},
&
ec2rolecreds
.
EC2RoleProvider
{
Client
:
ec2metadata
.
New
(
sess
),
ExpiryWindow
:
5
*
time
.
Minute
},
})
cfg
:=
&
aws
.
Config
{
Region
:
aws
.
String
(
req
.
Region
),
Credentials
:
creds
,
}
svc
:=
cloudwatch
.
New
(
session
.
New
(
cfg
),
cfg
)
reqParam
:=
&
struct
{
Parameters
struct
{
Namespace
string
`json:"namespace"`
MetricName
string
`json:"metricName"`
Dimensions
[]
*
cloudwatch
.
Dimension
`json:"dimensions"`
Statistic
string
`json:"statistic"`
Period
int64
`json:"period"`
}
`json:"parameters"`
}{}
json
.
Unmarshal
(
req
.
Body
,
reqParam
)
params
:=
&
cloudwatch
.
DescribeAlarmsForMetricInput
{
Namespace
:
aws
.
String
(
reqParam
.
Parameters
.
Namespace
),
MetricName
:
aws
.
String
(
reqParam
.
Parameters
.
MetricName
),
Period
:
aws
.
Int64
(
reqParam
.
Parameters
.
Period
),
}
if
len
(
reqParam
.
Parameters
.
Dimensions
)
!=
0
{
params
.
Dimensions
=
reqParam
.
Parameters
.
Dimensions
}
if
reqParam
.
Parameters
.
Statistic
!=
""
{
params
.
Statistic
=
aws
.
String
(
reqParam
.
Parameters
.
Statistic
)
}
resp
,
err
:=
svc
.
DescribeAlarmsForMetric
(
params
)
if
err
!=
nil
{
c
.
JsonApiErr
(
500
,
"Unable to call AWS API"
,
err
)
return
}
c
.
JSON
(
200
,
resp
)
}
func
handleDescribeAlarmHistory
(
req
*
cwRequest
,
c
*
middleware
.
Context
)
{
sess
:=
session
.
New
()
creds
:=
credentials
.
NewChainCredentials
(
[]
credentials
.
Provider
{
&
credentials
.
EnvProvider
{},
&
credentials
.
SharedCredentialsProvider
{
Filename
:
""
,
Profile
:
req
.
DataSource
.
Database
},
&
ec2rolecreds
.
EC2RoleProvider
{
Client
:
ec2metadata
.
New
(
sess
),
ExpiryWindow
:
5
*
time
.
Minute
},
})
cfg
:=
&
aws
.
Config
{
Region
:
aws
.
String
(
req
.
Region
),
Credentials
:
creds
,
}
svc
:=
cloudwatch
.
New
(
session
.
New
(
cfg
),
cfg
)
reqParam
:=
&
struct
{
Parameters
struct
{
AlarmName
string
`json:"alarmName"`
HistoryItemType
string
`json:"historyItemType"`
StartDate
int64
`json:"startDate"`
EndDate
int64
`json:"endDate"`
}
`json:"parameters"`
}{}
json
.
Unmarshal
(
req
.
Body
,
reqParam
)
params
:=
&
cloudwatch
.
DescribeAlarmHistoryInput
{
AlarmName
:
aws
.
String
(
reqParam
.
Parameters
.
AlarmName
),
StartDate
:
aws
.
Time
(
time
.
Unix
(
reqParam
.
Parameters
.
StartDate
,
0
)),
EndDate
:
aws
.
Time
(
time
.
Unix
(
reqParam
.
Parameters
.
EndDate
,
0
)),
}
if
reqParam
.
Parameters
.
HistoryItemType
!=
""
{
params
.
HistoryItemType
=
aws
.
String
(
reqParam
.
Parameters
.
HistoryItemType
)
}
resp
,
err
:=
svc
.
DescribeAlarmHistory
(
params
)
if
err
!=
nil
{
c
.
JsonApiErr
(
500
,
"Unable to call AWS API"
,
err
)
return
}
c
.
JSON
(
200
,
resp
)
}
func
handleDescribeInstances
(
req
*
cwRequest
,
c
*
middleware
.
Context
)
{
func
handleDescribeInstances
(
req
*
cwRequest
,
c
*
middleware
.
Context
)
{
sess
:=
session
.
New
()
sess
:=
session
.
New
()
creds
:=
credentials
.
NewChainCredentials
(
creds
:=
credentials
.
NewChainCredentials
(
...
...
public/app/plugins/datasource/cloudwatch/datasource.js
View file @
25d93d10
...
@@ -2,10 +2,11 @@ define([
...
@@ -2,10 +2,11 @@ define([
'angular'
,
'angular'
,
'lodash'
,
'lodash'
,
'moment'
,
'moment'
,
'app/core/utils/datemath'
,
'./query_ctrl'
,
'./query_ctrl'
,
'./directives'
,
'./directives'
,
],
],
function
(
angular
,
_
)
{
function
(
angular
,
_
,
moment
,
dateMath
)
{
'use strict'
;
'use strict'
;
var
module
=
angular
.
module
(
'grafana.services'
);
var
module
=
angular
.
module
(
'grafana.services'
);
...
@@ -21,8 +22,8 @@ function (angular, _) {
...
@@ -21,8 +22,8 @@ function (angular, _) {
}
}
CloudWatchDatasource
.
prototype
.
query
=
function
(
options
)
{
CloudWatchDatasource
.
prototype
.
query
=
function
(
options
)
{
var
start
=
convertToCloudWatchTime
(
options
.
range
.
from
);
var
start
=
convertToCloudWatchTime
(
options
.
range
.
from
,
false
);
var
end
=
convertToCloudWatchTime
(
options
.
range
.
to
);
var
end
=
convertToCloudWatchTime
(
options
.
range
.
to
,
true
);
var
queries
=
[];
var
queries
=
[];
options
=
angular
.
copy
(
options
);
options
=
angular
.
copy
(
options
);
...
@@ -209,6 +210,74 @@ function (angular, _) {
...
@@ -209,6 +210,74 @@ function (angular, _) {
return
$q
.
when
([]);
return
$q
.
when
([]);
};
};
CloudWatchDatasource
.
prototype
.
performDescribeAlarmsForMetric
=
function
(
region
,
namespace
,
metricName
,
dimensions
,
statistic
,
period
)
{
return
this
.
awsRequest
({
region
:
region
,
action
:
'DescribeAlarmsForMetric'
,
parameters
:
{
namespace
:
namespace
,
metricName
:
metricName
,
dimensions
:
dimensions
,
statistic
:
statistic
,
period
:
period
}
});
};
CloudWatchDatasource
.
prototype
.
performDescribeAlarmHistory
=
function
(
region
,
alarmName
,
startDate
,
endDate
)
{
return
this
.
awsRequest
({
region
:
region
,
action
:
'DescribeAlarmHistory'
,
parameters
:
{
alarmName
:
alarmName
,
startDate
:
startDate
,
endDate
:
endDate
}
});
};
CloudWatchDatasource
.
prototype
.
annotationQuery
=
function
(
options
)
{
var
annotation
=
options
.
annotation
;
var
region
=
templateSrv
.
replace
(
annotation
.
region
);
var
namespace
=
templateSrv
.
replace
(
annotation
.
namespace
);
var
metricName
=
templateSrv
.
replace
(
annotation
.
metricName
);
var
dimensions
=
convertDimensionFormat
(
annotation
.
dimensions
);
var
statistics
=
_
.
map
(
annotation
.
statistics
,
function
(
s
)
{
return
templateSrv
.
replace
(
s
);
});
var
period
=
annotation
.
period
||
'300'
;
period
=
parseInt
(
period
,
10
);
if
(
!
region
||
!
namespace
||
!
metricName
||
_
.
isEmpty
(
statistics
))
{
return
$q
.
when
([]);
}
var
d
=
$q
.
defer
();
var
self
=
this
;
var
allQueryPromise
=
_
.
map
(
statistics
,
function
(
statistic
)
{
return
self
.
performDescribeAlarmsForMetric
(
region
,
namespace
,
metricName
,
dimensions
,
statistic
,
period
);
});
$q
.
all
(
allQueryPromise
).
then
(
function
(
alarms
)
{
var
eventList
=
[];
var
start
=
convertToCloudWatchTime
(
options
.
range
.
from
,
false
);
var
end
=
convertToCloudWatchTime
(
options
.
range
.
to
,
true
);
_
.
chain
(
alarms
)
.
pluck
(
'MetricAlarms'
)
.
flatten
()
.
each
(
function
(
alarm
)
{
if
(
!
alarm
)
{
d
.
resolve
(
eventList
);
return
;
}
self
.
performDescribeAlarmHistory
(
region
,
alarm
.
AlarmName
,
start
,
end
).
then
(
function
(
history
)
{
_
.
each
(
history
.
AlarmHistoryItems
,
function
(
h
)
{
var
event
=
{
annotation
:
annotation
,
time
:
Date
.
parse
(
h
.
Timestamp
),
title
:
h
.
AlarmName
,
tags
:
[
h
.
HistoryItemType
],
text
:
h
.
HistorySummary
};
eventList
.
push
(
event
);
});
d
.
resolve
(
eventList
);
});
});
});
return
d
.
promise
;
};
CloudWatchDatasource
.
prototype
.
testDatasource
=
function
()
{
CloudWatchDatasource
.
prototype
.
testDatasource
=
function
()
{
/* use billing metrics for test */
/* use billing metrics for test */
var
region
=
this
.
defaultRegion
;
var
region
=
this
.
defaultRegion
;
...
@@ -276,7 +345,10 @@ function (angular, _) {
...
@@ -276,7 +345,10 @@ function (angular, _) {
});
});
}
}
function
convertToCloudWatchTime
(
date
)
{
function
convertToCloudWatchTime
(
date
,
roundUp
)
{
if
(
_
.
isString
(
date
))
{
date
=
dateMath
.
parse
(
date
,
roundUp
);
}
return
Math
.
round
(
date
.
valueOf
()
/
1000
);
return
Math
.
round
(
date
.
valueOf
()
/
1000
);
}
}
...
...
public/app/plugins/datasource/cloudwatch/directives.js
View file @
25d93d10
define
([
define
([
'angular'
,
'angular'
,
'./query_parameter_ctrl'
,
],
],
function
(
angular
)
{
function
(
angular
)
{
'use strict'
;
'use strict'
;
...
@@ -10,4 +11,21 @@ function (angular) {
...
@@ -10,4 +11,21 @@ function (angular) {
return
{
controller
:
'CloudWatchQueryCtrl'
,
templateUrl
:
'app/plugins/datasource/cloudwatch/partials/query.editor.html'
};
return
{
controller
:
'CloudWatchQueryCtrl'
,
templateUrl
:
'app/plugins/datasource/cloudwatch/partials/query.editor.html'
};
});
});
module
.
directive
(
'annotationsQueryEditorCloudwatch'
,
function
()
{
return
{
templateUrl
:
'app/plugins/datasource/cloudwatch/partials/annotations.editor.html'
};
});
module
.
directive
(
'cloudwatchQueryParameter'
,
function
()
{
return
{
templateUrl
:
'app/plugins/datasource/cloudwatch/partials/query.parameter.html'
,
controller
:
'CloudWatchQueryParameterCtrl'
,
restrict
:
'E'
,
scope
:
{
target
:
"="
,
datasourceName
:
"@"
,
onChange
:
"&"
,
}
};
});
});
});
public/app/plugins/datasource/cloudwatch/partials/annotations.editor.html
0 → 100644
View file @
25d93d10
<cloudwatch-query-parameter
target=
"currentAnnotation"
datasource-name=
"{{currentAnnotation.datasource}}"
></cloudwatch-query-parameter>
public/app/plugins/datasource/cloudwatch/partials/query.editor.html
View file @
25d93d10
...
@@ -33,61 +33,16 @@
...
@@ -33,61 +33,16 @@
</ul>
</ul>
<ul
class=
"tight-form-list"
role=
"menu"
>
<ul
class=
"tight-form-list"
role=
"menu"
>
<li
class=
"tight-form-item query-keyword"
style=
"width: 100px"
>
Metric
</li>
<li>
<metric-segment
segment=
"regionSegment"
get-options=
"getRegions()"
on-change=
"regionChanged()"
></metric-segment>
</li>
<li>
<metric-segment
segment=
"namespaceSegment"
get-options=
"getNamespaces()"
on-change=
"namespaceChanged()"
></metric-segment>
</li>
<li>
<metric-segment
segment=
"metricSegment"
get-options=
"getMetrics()"
on-change=
"metricChanged()"
></metric-segment>
</li>
<li
class=
"tight-form-item query-keyword"
>
<li
class=
"tight-form-item query-keyword"
>
Stats
</li>
<li
ng-repeat=
"segment in statSegments"
>
<metric-segment
segment=
"segment"
get-options=
"getStatSegments(segment, $index)"
on-change=
"statSegmentChanged(segment, $index)"
></metric-segment>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
role=
"menu"
>
<li
class=
"tight-form-item query-keyword tight-form-align"
style=
"width: 100px"
>
Dimensions
</li>
<li
ng-repeat=
"segment in dimSegments"
>
<metric-segment
segment=
"segment"
get-options=
"getDimSegments(segment, $index)"
on-change=
"dimSegmentChanged(segment, $index)"
></metric-segment>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
role=
"menu"
>
<li
class=
"tight-form-item query-keyword tight-form-align"
style=
"width: 100px"
>
Alias
Alias
<tip>
{{metric}} {{stat}} {{namespace}} {{region}} {{DIMENSION_NAME}}
</tip>
<tip>
{{metric}} {{stat}} {{namespace}} {{region}} {{DIMENSION_NAME}}
</tip>
</li>
</li>
<li>
<li>
<input
type=
"text"
class=
"input-xlarge tight-form-input"
ng-model=
"target.alias"
spellcheck=
'false'
ng-model-onblur
ng-change=
"refreshMetricData()"
>
<input
type=
"text"
class=
"input-xlarge tight-form-input"
ng-model=
"target.alias"
spellcheck=
'false'
ng-model-onblur
ng-change=
"refreshMetricData()"
>
</li>
</li>
<li
class=
"tight-form-item query-keyword"
>
Period
<tip>
Interval between points in seconds
</tip>
</li>
<li>
<input
type=
"text"
class=
"input-mini tight-form-input"
ng-model=
"target.period"
spellcheck=
'false'
placeholder=
"auto"
ng-model-onblur
ng-change=
"refreshMetricData()"
/>
</li>
</ul>
</ul>
<div
class=
"clearfix"
></div>
<div
class=
"clearfix"
></div>
</div>
</div>
<cloudwatch-query-parameter
target=
"target"
datasource-name=
"{{datasource.name}}"
on-change=
"refreshMetricData()"
></cloudwatch-query-parameter>
public/app/plugins/datasource/cloudwatch/partials/query.parameter.html
0 → 100644
View file @
25d93d10
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
role=
"menu"
>
<li
class=
"tight-form-item query-keyword tight-form-align"
style=
"width: 100px"
>
Metric
</li>
<li>
<metric-segment
segment=
"regionSegment"
get-options=
"getRegions()"
on-change=
"regionChanged()"
></metric-segment>
</li>
<li>
<metric-segment
segment=
"namespaceSegment"
get-options=
"getNamespaces()"
on-change=
"namespaceChanged()"
></metric-segment>
</li>
<li>
<metric-segment
segment=
"metricSegment"
get-options=
"getMetrics()"
on-change=
"metricChanged()"
></metric-segment>
</li>
<li
class=
"tight-form-item query-keyword"
>
Stats
</li>
<li
ng-repeat=
"segment in statSegments"
>
<metric-segment
segment=
"segment"
get-options=
"getStatSegments(segment, $index)"
on-change=
"statSegmentChanged(segment, $index)"
></metric-segment>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
role=
"menu"
>
<li
class=
"tight-form-item query-keyword tight-form-align"
style=
"width: 100px"
>
Dimensions
</li>
<li
ng-repeat=
"segment in dimSegments"
>
<metric-segment
segment=
"segment"
get-options=
"getDimSegments(segment, $index)"
on-change=
"dimSegmentChanged(segment, $index)"
></metric-segment>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
<div
class=
"tight-form"
>
<ul
class=
"tight-form-list"
role=
"menu"
>
<li
class=
"tight-form-item query-keyword tight-form-align"
style=
"width: 100px"
>
Period
<tip>
Interval between points in seconds
</tip>
</li>
<li>
<input
type=
"text"
class=
"input-mini tight-form-input"
ng-model=
"target.period"
spellcheck=
'false'
placeholder=
"auto"
ng-model-onblur
ng-change=
"refreshMetricData()"
/>
</li>
</ul>
<div
class=
"clearfix"
></div>
</div>
public/app/plugins/datasource/cloudwatch/plugin.json
View file @
25d93d10
...
@@ -12,5 +12,6 @@
...
@@ -12,5 +12,6 @@
"query"
:
"app/plugins/datasource/cloudwatch/partials/query.editor.html"
"query"
:
"app/plugins/datasource/cloudwatch/partials/query.editor.html"
},
},
"metrics"
:
true
"metrics"
:
true
,
"annotations"
:
true
}
}
public/app/plugins/datasource/cloudwatch/query_ctrl.js
View file @
25d93d10
...
@@ -7,173 +7,10 @@ function (angular, _) {
...
@@ -7,173 +7,10 @@ function (angular, _) {
var
module
=
angular
.
module
(
'grafana.controllers'
);
var
module
=
angular
.
module
(
'grafana.controllers'
);
module
.
controller
(
'CloudWatchQueryCtrl'
,
function
(
$scope
,
templateSrv
,
uiSegmentSrv
,
$q
)
{
module
.
controller
(
'CloudWatchQueryCtrl'
,
function
(
$scope
)
{
$scope
.
init
=
function
()
{
$scope
.
init
=
function
()
{
var
target
=
$scope
.
target
;
target
.
namespace
=
target
.
namespace
||
''
;
target
.
metricName
=
target
.
metricName
||
''
;
target
.
statistics
=
target
.
statistics
||
[
'Average'
];
target
.
dimensions
=
target
.
dimensions
||
{};
target
.
period
=
target
.
period
||
''
;
target
.
region
=
target
.
region
||
$scope
.
datasource
.
getDefaultRegion
();
$scope
.
aliasSyntax
=
'{{metric}} {{stat}} {{namespace}} {{region}} {{<dimension name>}}'
;
$scope
.
aliasSyntax
=
'{{metric}} {{stat}} {{namespace}} {{region}} {{<dimension name>}}'
;
$scope
.
regionSegment
=
uiSegmentSrv
.
getSegmentForValue
(
$scope
.
target
.
region
,
'select region'
);
$scope
.
namespaceSegment
=
uiSegmentSrv
.
getSegmentForValue
(
$scope
.
target
.
namespace
,
'select namespace'
);
$scope
.
metricSegment
=
uiSegmentSrv
.
getSegmentForValue
(
$scope
.
target
.
metricName
,
'select metric'
);
$scope
.
dimSegments
=
_
.
reduce
(
$scope
.
target
.
dimensions
,
function
(
memo
,
value
,
key
)
{
memo
.
push
(
uiSegmentSrv
.
newKey
(
key
));
memo
.
push
(
uiSegmentSrv
.
newOperator
(
"="
));
memo
.
push
(
uiSegmentSrv
.
newKeyValue
(
value
));
return
memo
;
},
[]);
$scope
.
statSegments
=
_
.
map
(
$scope
.
target
.
statistics
,
function
(
stat
)
{
return
uiSegmentSrv
.
getSegmentForValue
(
stat
);
});
$scope
.
ensurePlusButton
(
$scope
.
statSegments
);
$scope
.
ensurePlusButton
(
$scope
.
dimSegments
);
$scope
.
removeDimSegment
=
uiSegmentSrv
.
newSegment
({
fake
:
true
,
value
:
'-- remove dimension --'
});
$scope
.
removeStatSegment
=
uiSegmentSrv
.
newSegment
({
fake
:
true
,
value
:
'-- remove stat --'
});
};
$scope
.
getStatSegments
=
function
()
{
return
$q
.
when
([
angular
.
copy
(
$scope
.
removeStatSegment
),
uiSegmentSrv
.
getSegmentForValue
(
'Average'
),
uiSegmentSrv
.
getSegmentForValue
(
'Maximum'
),
uiSegmentSrv
.
getSegmentForValue
(
'Minimum'
),
uiSegmentSrv
.
getSegmentForValue
(
'Sum'
),
uiSegmentSrv
.
getSegmentForValue
(
'SampleCount'
),
]);
};
$scope
.
statSegmentChanged
=
function
(
segment
,
index
)
{
if
(
segment
.
value
===
$scope
.
removeStatSegment
.
value
)
{
$scope
.
statSegments
.
splice
(
index
,
1
);
}
else
{
segment
.
type
=
'value'
;
}
$scope
.
target
.
statistics
=
_
.
reduce
(
$scope
.
statSegments
,
function
(
memo
,
seg
)
{
if
(
!
seg
.
fake
)
{
memo
.
push
(
seg
.
value
);
}
return
memo
;
},
[]);
$scope
.
ensurePlusButton
(
$scope
.
statSegments
);
$scope
.
get_data
();
};
$scope
.
ensurePlusButton
=
function
(
segments
)
{
var
count
=
segments
.
length
;
var
lastSegment
=
segments
[
Math
.
max
(
count
-
1
,
0
)];
if
(
!
lastSegment
||
lastSegment
.
type
!==
'plus-button'
)
{
segments
.
push
(
uiSegmentSrv
.
newPlusButton
());
}
};
$scope
.
getDimSegments
=
function
(
segment
,
$index
)
{
if
(
segment
.
type
===
'operator'
)
{
return
$q
.
when
([]);
}
var
target
=
$scope
.
target
;
var
query
=
$q
.
when
([]);
if
(
segment
.
type
===
'key'
||
segment
.
type
===
'plus-button'
)
{
query
=
$scope
.
datasource
.
getDimensionKeys
(
$scope
.
target
.
namespace
);
}
else
if
(
segment
.
type
===
'value'
)
{
var
dimensionKey
=
$scope
.
dimSegments
[
$index
-
2
].
value
;
query
=
$scope
.
datasource
.
getDimensionValues
(
target
.
region
,
target
.
namespace
,
target
.
metricName
,
dimensionKey
,
{});
}
return
query
.
then
(
$scope
.
transformToSegments
(
true
)).
then
(
function
(
results
)
{
if
(
segment
.
type
===
'key'
)
{
results
.
splice
(
0
,
0
,
angular
.
copy
(
$scope
.
removeDimSegment
));
}
return
results
;
});
};
$scope
.
dimSegmentChanged
=
function
(
segment
,
index
)
{
$scope
.
dimSegments
[
index
]
=
segment
;
if
(
segment
.
value
===
$scope
.
removeDimSegment
.
value
)
{
$scope
.
dimSegments
.
splice
(
index
,
3
);
}
else
if
(
segment
.
type
===
'plus-button'
)
{
$scope
.
dimSegments
.
push
(
uiSegmentSrv
.
newOperator
(
'='
));
$scope
.
dimSegments
.
push
(
uiSegmentSrv
.
newFake
(
'select dimension value'
,
'value'
,
'query-segment-value'
));
segment
.
type
=
'key'
;
segment
.
cssClass
=
'query-segment-key'
;
}
$scope
.
syncDimSegmentsWithModel
();
$scope
.
ensurePlusButton
(
$scope
.
dimSegments
);
$scope
.
get_data
();
};
$scope
.
syncDimSegmentsWithModel
=
function
()
{
var
dims
=
{};
var
length
=
$scope
.
dimSegments
.
length
;
for
(
var
i
=
0
;
i
<
length
-
2
;
i
+=
3
)
{
var
keySegment
=
$scope
.
dimSegments
[
i
];
var
valueSegment
=
$scope
.
dimSegments
[
i
+
2
];
if
(
!
valueSegment
.
fake
)
{
dims
[
keySegment
.
value
]
=
valueSegment
.
value
;
}
}
$scope
.
target
.
dimensions
=
dims
;
};
$scope
.
getRegions
=
function
()
{
return
$scope
.
datasource
.
metricFindQuery
(
'regions()'
)
.
then
(
$scope
.
transformToSegments
(
true
));
};
$scope
.
getNamespaces
=
function
()
{
return
$scope
.
datasource
.
metricFindQuery
(
'namespaces()'
)
.
then
(
$scope
.
transformToSegments
(
true
));
};
$scope
.
getMetrics
=
function
()
{
return
$scope
.
datasource
.
metricFindQuery
(
'metrics('
+
$scope
.
target
.
namespace
+
')'
)
.
then
(
$scope
.
transformToSegments
(
true
));
};
$scope
.
regionChanged
=
function
()
{
$scope
.
target
.
region
=
$scope
.
regionSegment
.
value
;
$scope
.
get_data
();
};
$scope
.
namespaceChanged
=
function
()
{
$scope
.
target
.
namespace
=
$scope
.
namespaceSegment
.
value
;
$scope
.
get_data
();
};
$scope
.
metricChanged
=
function
()
{
$scope
.
target
.
metricName
=
$scope
.
metricSegment
.
value
;
$scope
.
get_data
();
};
$scope
.
transformToSegments
=
function
(
addTemplateVars
)
{
return
function
(
results
)
{
var
segments
=
_
.
map
(
results
,
function
(
segment
)
{
return
uiSegmentSrv
.
newSegment
({
value
:
segment
.
text
,
expandable
:
segment
.
expandable
});
});
if
(
addTemplateVars
)
{
_
.
each
(
templateSrv
.
variables
,
function
(
variable
)
{
segments
.
unshift
(
uiSegmentSrv
.
newSegment
({
type
:
'template'
,
value
:
'$'
+
variable
.
name
,
expandable
:
true
}));
});
}
return
segments
;
};
};
};
$scope
.
refreshMetricData
=
function
()
{
$scope
.
refreshMetricData
=
function
()
{
...
...
public/app/plugins/datasource/cloudwatch/query_parameter_ctrl.js
0 → 100644
View file @
25d93d10
define
([
'angular'
,
'lodash'
,
],
function
(
angular
,
_
)
{
'use strict'
;
var
module
=
angular
.
module
(
'grafana.controllers'
);
module
.
controller
(
'CloudWatchQueryParameterCtrl'
,
function
(
$scope
,
templateSrv
,
uiSegmentSrv
,
datasourceSrv
,
$q
)
{
$scope
.
init
=
function
()
{
var
target
=
$scope
.
target
;
target
.
namespace
=
target
.
namespace
||
''
;
target
.
metricName
=
target
.
metricName
||
''
;
target
.
statistics
=
target
.
statistics
||
[
'Average'
];
target
.
dimensions
=
target
.
dimensions
||
{};
target
.
period
=
target
.
period
||
''
;
target
.
region
=
target
.
region
||
''
;
$scope
.
regionSegment
=
uiSegmentSrv
.
getSegmentForValue
(
$scope
.
target
.
region
,
'select region'
);
$scope
.
namespaceSegment
=
uiSegmentSrv
.
getSegmentForValue
(
$scope
.
target
.
namespace
,
'select namespace'
);
$scope
.
metricSegment
=
uiSegmentSrv
.
getSegmentForValue
(
$scope
.
target
.
metricName
,
'select metric'
);
$scope
.
dimSegments
=
_
.
reduce
(
$scope
.
target
.
dimensions
,
function
(
memo
,
value
,
key
)
{
memo
.
push
(
uiSegmentSrv
.
newKey
(
key
));
memo
.
push
(
uiSegmentSrv
.
newOperator
(
"="
));
memo
.
push
(
uiSegmentSrv
.
newKeyValue
(
value
));
return
memo
;
},
[]);
$scope
.
statSegments
=
_
.
map
(
$scope
.
target
.
statistics
,
function
(
stat
)
{
return
uiSegmentSrv
.
getSegmentForValue
(
stat
);
});
$scope
.
ensurePlusButton
(
$scope
.
statSegments
);
$scope
.
ensurePlusButton
(
$scope
.
dimSegments
);
$scope
.
removeDimSegment
=
uiSegmentSrv
.
newSegment
({
fake
:
true
,
value
:
'-- remove dimension --'
});
$scope
.
removeStatSegment
=
uiSegmentSrv
.
newSegment
({
fake
:
true
,
value
:
'-- remove stat --'
});
datasourceSrv
.
get
(
$scope
.
datasourceName
).
then
(
function
(
datasource
)
{
$scope
.
datasource
=
datasource
;
if
(
_
.
isEmpty
(
$scope
.
target
.
region
))
{
$scope
.
target
.
region
=
$scope
.
datasource
.
getDefaultRegion
();
}
});
if
(
!
$scope
.
onChange
)
{
$scope
.
onChange
=
function
()
{};
}
};
$scope
.
getStatSegments
=
function
()
{
return
$q
.
when
([
angular
.
copy
(
$scope
.
removeStatSegment
),
uiSegmentSrv
.
getSegmentForValue
(
'Average'
),
uiSegmentSrv
.
getSegmentForValue
(
'Maximum'
),
uiSegmentSrv
.
getSegmentForValue
(
'Minimum'
),
uiSegmentSrv
.
getSegmentForValue
(
'Sum'
),
uiSegmentSrv
.
getSegmentForValue
(
'SampleCount'
),
]);
};
$scope
.
statSegmentChanged
=
function
(
segment
,
index
)
{
if
(
segment
.
value
===
$scope
.
removeStatSegment
.
value
)
{
$scope
.
statSegments
.
splice
(
index
,
1
);
}
else
{
segment
.
type
=
'value'
;
}
$scope
.
target
.
statistics
=
_
.
reduce
(
$scope
.
statSegments
,
function
(
memo
,
seg
)
{
if
(
!
seg
.
fake
)
{
memo
.
push
(
seg
.
value
);
}
return
memo
;
},
[]);
$scope
.
ensurePlusButton
(
$scope
.
statSegments
);
$scope
.
onChange
();
};
$scope
.
ensurePlusButton
=
function
(
segments
)
{
var
count
=
segments
.
length
;
var
lastSegment
=
segments
[
Math
.
max
(
count
-
1
,
0
)];
if
(
!
lastSegment
||
lastSegment
.
type
!==
'plus-button'
)
{
segments
.
push
(
uiSegmentSrv
.
newPlusButton
());
}
};
$scope
.
getDimSegments
=
function
(
segment
,
$index
)
{
if
(
segment
.
type
===
'operator'
)
{
return
$q
.
when
([]);
}
var
target
=
$scope
.
target
;
var
query
=
$q
.
when
([]);
if
(
segment
.
type
===
'key'
||
segment
.
type
===
'plus-button'
)
{
query
=
$scope
.
datasource
.
getDimensionKeys
(
$scope
.
target
.
namespace
);
}
else
if
(
segment
.
type
===
'value'
)
{
var
dimensionKey
=
$scope
.
dimSegments
[
$index
-
2
].
value
;
query
=
$scope
.
datasource
.
getDimensionValues
(
target
.
region
,
target
.
namespace
,
target
.
metricName
,
dimensionKey
,
{});
}
return
query
.
then
(
$scope
.
transformToSegments
(
true
)).
then
(
function
(
results
)
{
if
(
segment
.
type
===
'key'
)
{
results
.
splice
(
0
,
0
,
angular
.
copy
(
$scope
.
removeDimSegment
));
}
return
results
;
});
};
$scope
.
dimSegmentChanged
=
function
(
segment
,
index
)
{
$scope
.
dimSegments
[
index
]
=
segment
;
if
(
segment
.
value
===
$scope
.
removeDimSegment
.
value
)
{
$scope
.
dimSegments
.
splice
(
index
,
3
);
}
else
if
(
segment
.
type
===
'plus-button'
)
{
$scope
.
dimSegments
.
push
(
uiSegmentSrv
.
newOperator
(
'='
));
$scope
.
dimSegments
.
push
(
uiSegmentSrv
.
newFake
(
'select dimension value'
,
'value'
,
'query-segment-value'
));
segment
.
type
=
'key'
;
segment
.
cssClass
=
'query-segment-key'
;
}
$scope
.
syncDimSegmentsWithModel
();
$scope
.
ensurePlusButton
(
$scope
.
dimSegments
);
$scope
.
onChange
();
};
$scope
.
syncDimSegmentsWithModel
=
function
()
{
var
dims
=
{};
var
length
=
$scope
.
dimSegments
.
length
;
for
(
var
i
=
0
;
i
<
length
-
2
;
i
+=
3
)
{
var
keySegment
=
$scope
.
dimSegments
[
i
];
var
valueSegment
=
$scope
.
dimSegments
[
i
+
2
];
if
(
!
valueSegment
.
fake
)
{
dims
[
keySegment
.
value
]
=
valueSegment
.
value
;
}
}
$scope
.
target
.
dimensions
=
dims
;
};
$scope
.
getRegions
=
function
()
{
return
$scope
.
datasource
.
metricFindQuery
(
'regions()'
)
.
then
(
$scope
.
transformToSegments
(
true
));
};
$scope
.
getNamespaces
=
function
()
{
return
$scope
.
datasource
.
metricFindQuery
(
'namespaces()'
)
.
then
(
$scope
.
transformToSegments
(
true
));
};
$scope
.
getMetrics
=
function
()
{
return
$scope
.
datasource
.
metricFindQuery
(
'metrics('
+
$scope
.
target
.
namespace
+
')'
)
.
then
(
$scope
.
transformToSegments
(
true
));
};
$scope
.
regionChanged
=
function
()
{
$scope
.
target
.
region
=
$scope
.
regionSegment
.
value
;
$scope
.
onChange
();
};
$scope
.
namespaceChanged
=
function
()
{
$scope
.
target
.
namespace
=
$scope
.
namespaceSegment
.
value
;
$scope
.
onChange
();
};
$scope
.
metricChanged
=
function
()
{
$scope
.
target
.
metricName
=
$scope
.
metricSegment
.
value
;
$scope
.
onChange
();
};
$scope
.
transformToSegments
=
function
(
addTemplateVars
)
{
return
function
(
results
)
{
var
segments
=
_
.
map
(
results
,
function
(
segment
)
{
return
uiSegmentSrv
.
newSegment
({
value
:
segment
.
text
,
expandable
:
segment
.
expandable
});
});
if
(
addTemplateVars
)
{
_
.
each
(
templateSrv
.
variables
,
function
(
variable
)
{
segments
.
unshift
(
uiSegmentSrv
.
newSegment
({
type
:
'template'
,
value
:
'$'
+
variable
.
name
,
expandable
:
true
}));
});
}
return
segments
;
};
};
$scope
.
init
();
});
});
public/app/plugins/datasource/cloudwatch/specs/datasource_specs.ts
View file @
25d93d10
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
///<amd-dependency path="test/specs/helpers" name="helpers" />
///<amd-dependency path="test/specs/helpers" name="helpers" />
import
{
describe
,
beforeEach
,
it
,
sinon
,
expect
,
angularMocks
}
from
'test/lib/common'
;
import
{
describe
,
beforeEach
,
it
,
sinon
,
expect
,
angularMocks
}
from
'test/lib/common'
;
import
moment
=
require
(
'moment'
);
declare
var
helpers
:
any
;
declare
var
helpers
:
any
;
...
@@ -189,4 +190,60 @@ describe('CloudWatchDatasource', function() {
...
@@ -189,4 +190,60 @@ describe('CloudWatchDatasource', function() {
});
});
});
});
describe
(
'When performing annotationQuery'
,
function
()
{
var
parameter
=
{
annotation
:
{
region
:
'us-east-1'
,
namespace
:
'AWS/EC2'
,
metricName
:
'CPUUtilization'
,
dimensions
:
{
InstanceId
:
'i-12345678'
},
statistics
:
[
'Average'
],
period
:
300
},
range
:
{
from
:
moment
(
1443438674760
),
to
:
moment
(
1443460274760
)
}
};
var
alarmResponse
=
{
MetricAlarms
:
[
{
AlarmName
:
'test_alarm_name'
}
]
};
var
historyResponse
=
{
AlarmHistoryItems
:
[
{
Timestamp
:
'2015-01-01T00:00:00.000Z'
,
HistoryItemType
:
'StateUpdate'
,
AlarmName
:
'test_alarm_name'
,
HistoryData
:
'{}'
,
HistorySummary
:
'test_history_summary'
}
]
};
beforeEach
(
function
()
{
ctx
.
backendSrv
.
datasourceRequest
=
function
(
params
)
{
switch
(
params
.
data
.
action
)
{
case
'DescribeAlarmsForMetric'
:
return
ctx
.
$q
.
when
({
data
:
alarmResponse
});
break
;
case
'DescribeAlarmHistory'
:
return
ctx
.
$q
.
when
({
data
:
historyResponse
});
break
;
}
};
});
it
(
'should return annotation list'
,
function
(
done
)
{
ctx
.
ds
.
annotationQuery
(
parameter
).
then
(
function
(
result
)
{
expect
(
result
[
0
].
title
).
to
.
be
(
'test_alarm_name'
);
expect
(
result
[
0
].
text
).
to
.
be
(
'test_history_summary'
);
done
();
});
ctx
.
$rootScope
.
$apply
();
});
});
});
});
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