grafana/panels/timepicker/module.js

291 lines
8.9 KiB
JavaScript
Raw Normal View History

2013-02-06 05:30:08 +08:00
/*
## Timepicker
The timepicker panel is used to select time ranges and inform other panel of
them. It also handles searching for indices that match the given time range and
a pattern
### Parameters
* mode :: The default mode of the panel. Options: 'relative', 'absolute' 'since' Default: 'relative'
* time_options :: An array of possible time options. Default: ['5m','15m','1h','6h','12h','24h','2d','7d','30d']
* timespan :: The default options selected for the relative view. Default: '15m'
* timefield :: The field in which time is stored in the document.
* index :: Index pattern to match. Literals should be double quoted. Default: '"logstash-"yyyy.mm.dd'
* refresh: Object containing refresh parameters
* enable :: true/false, enable auto refresh by default. Default: false
* interval :: Seconds between auto refresh. Default: 30
* min :: The lowest interval a user may set
### Group Events
#### Sends
* time :: Object Includes from, to and index
#### Receives
* get_time :: Receives an object containing a uniqueid, broadcasts to it.
*/
angular.module('kibana.timepicker', [])
.controller('timepicker', function($scope, eventBus, $timeout, timer, $http) {
2013-02-06 05:30:08 +08:00
// Set and populate defaults
var _d = {
2013-02-06 05:30:08 +08:00
mode : "relative",
time_options : ['5m','15m','1h','6h','12h','24h','2d','7d','30d'],
timespan : '15m',
2013-02-14 07:12:57 +08:00
timefield : '@timestamp',
2013-02-06 05:30:08 +08:00
index : '"logstash-"yyyy.mm.dd',
2013-02-16 06:54:36 +08:00
defaultindex : "NOINDEX",
index_interval: "day",
timed_indices : true,
2013-02-06 05:30:08 +08:00
group : "default",
refresh : {
enable : false,
interval: 30,
min : 3
}
}
2013-02-06 05:30:08 +08:00
_.defaults($scope.panel,_d)
var _groups = _.isArray($scope.panel.group) ?
$scope.panel.group : [$scope.panel.group];
2013-02-06 05:30:08 +08:00
$scope.init = function() {
// Private refresh interval that we can use for view display without causing
// unnecessary refreshes during changes
$scope.refresh_interval = $scope.panel.refresh.interval
// Init a private time object with Date() objects depending on mode
switch($scope.panel.mode) {
case 'absolute':
$scope.time = {
from : new Date(Date.parse($scope.panel.time.from)) || time_ago($scope.panel.timespan),
to : new Date(Date.parse($scope.panel.time.to)) || new Date()
2013-02-06 05:30:08 +08:00
}
break;
case 'since':
$scope.time = {
from : new Date(Date.parse($scope.panel.time.from)) || time_ago($scope.panel.timespan),
to : new Date() || new Date()
2013-02-06 05:30:08 +08:00
}
break;
case 'relative':
$scope.time = {
from : time_ago($scope.panel.timespan),
to : new Date()
}
break;
}
$scope.time.field = $scope.panel.timefield;
$scope.time_apply();
2013-02-06 05:30:08 +08:00
// In the case that a panel is not ready to receive a time event, it may
// request one be sent by broadcasting a 'get_time' with its _id to its group
// This panel can handle multiple groups
eventBus.register($scope,"get_time", function(event,id) {
eventBus.broadcast($scope.$id,id,'time',$scope.time)
});
2013-03-14 00:33:51 +08:00
// In case some other panel broadcasts a time, set us to an absolute range
eventBus.register($scope,"set_time", function(event,time) {
$scope.panel.mode = 'absolute';
set_timepicker(time.from,time.to)
$scope.time_apply()
});
$scope.$on('render', function (){
$scope.time_apply();
});
}
$scope.set_interval = function (refresh_interval) {
$scope.panel.refresh.interval = refresh_interval
if(_.isNumber($scope.panel.refresh.interval)) {
if($scope.panel.refresh.interval < $scope.panel.refresh.min) {
$scope.panel.refresh.interval = $scope.panel.refresh.min
timer.cancel($scope.refresh_timer)
return;
}
timer.cancel($scope.refresh_timer)
$scope.refresh()
} else {
timer.cancel($scope.refresh_timer)
}
2013-02-06 05:30:08 +08:00
}
$scope.refresh = function() {
if ($scope.panel.refresh.enable) {
timer.cancel($scope.refresh_timer)
$scope.refresh_timer = timer.register($timeout(function() {
$scope.refresh();
$scope.time_apply();
},$scope.panel.refresh.interval*1000
));
} else {
timer.cancel($scope.refresh_timer)
}
}
$scope.set_mode = function(mode) {
$scope.panel.mode = mode;
$scope.panel.refresh.enable = mode === 'absolute' ?
false : $scope.panel.refresh.enable
}
$scope.to_now = function() {
$scope.timepicker.to = {
time : new Date().format("HH:MM:ss"),
date : new Date().format("mm/dd/yyyy")
}
}
$scope.set_timespan = function(timespan) {
$scope.panel.timespan = timespan;
$scope.timepicker.from = {
time : time_ago(timespan).format("HH:MM:ss"),
date : time_ago(timespan).format("mm/dd/yyyy")
}
$scope.time_apply();
}
$scope.time_check = function(){
// If time picker is defined (on initialization)
if(!(_.isUndefined($scope.timepicker))) {
var from = $scope.panel.mode === 'relative' ? time_ago($scope.panel.timespan) :
new Date(Date.parse($scope.timepicker.from.date + " " + $scope.timepicker.from.time))
var to = $scope.panel.mode !== 'absolute' ? new Date() :
new Date(Date.parse($scope.timepicker.to.date + " " + $scope.timepicker.to.time))
// Otherwise
} else {
var from = $scope.panel.mode === 'relative' ? time_ago($scope.panel.timespan) :
$scope.time.from;
var to = $scope.panel.mode !== 'absolute' ? new Date() :
$scope.time.to;
}
if (from.getTime() >= to.getTime())
from = new Date(to.getTime() - 1000)
$timeout(function(){
2013-03-14 00:33:51 +08:00
set_timepicker(from,to)
});
2013-02-06 05:30:08 +08:00
return {
from : from,
to : to
};
2013-02-06 05:30:08 +08:00
}
2013-02-06 05:30:08 +08:00
$scope.time_apply = function() {
// Update internal time object
$scope.time = $scope.time_check();
$scope.time.field = $scope.panel.timefield
// Get indices for the time period, then broadcast time range and index list
// in a single object. Not sure if I like this.
if($scope.panel.timed_indices) {
indices($scope.time.from,$scope.time.to).then(function (p) {
$scope.time.index = p;
eventBus.broadcast($scope.$id,$scope.panel.group,'time',$scope.time)
});
} else {
$scope.time.index = [$scope.panel.index];
eventBus.broadcast($scope.$id,$scope.panel.group,'time',$scope.time)
}
// Update panel's string representation of the time object
$scope.panel.time = {
from : $scope.time.from.format("mm/dd/yyyy HH:MM:ss"),
2013-02-06 05:30:08 +08:00
to : $scope.time.to.format("mm/dd/yyyy HH:MM:ss"),
index : $scope.time.index,
};
};
2013-03-14 00:33:51 +08:00
function set_timepicker(from,to) {
// Janky 0s timeout to get around $scope queue processing view issue
$scope.timepicker = {
from : {
time : from.format("HH:MM:ss"),
date : from.format("mm/dd/yyyy")
},
to : {
time : to.format("HH:MM:ss"),
date : to.format("mm/dd/yyyy")
}
}
}
2013-02-06 05:30:08 +08:00
// returns a promise containing an array of all indices matching the index
// pattern that exist in a given range
function indices(from,to) {
var possible = [];
_.each(expand_range(fake_utc(from),fake_utc(to),$scope.panel.index_interval),function(d){
2013-02-06 05:30:08 +08:00
possible.push(d.format($scope.panel.index));
});
return all_indices().then(function(p) {
var indices = _.intersection(possible,p);
indices.reverse();
2013-02-16 06:54:36 +08:00
return indices.length == 0 ? [$scope.panel.defaultindex] : indices;
2013-02-06 05:30:08 +08:00
})
};
// returns a promise containing an array of all indices in an elasticsearch
// cluster
function all_indices() {
var something = $http({
url: config.elasticsearch + "/_aliases",
method: "GET"
}).error(function(data, status, headers, config) {
$scope.error = status;
});
return something.then(function(p) {
var indices = [];
_.each(p.data, function(v,k) {
indices.push(k)
});
return indices;
});
}
// this is stupid, but there is otherwise no good way to ensure that when
// I extract the date from an object that I'm get the UTC date. Stupid js.
// I die a little inside every time I call this function.
function fake_utc(date) {
return new Date(date.getTime() + date.getTimezoneOffset() * 60000);
}
// Create an array of date objects by a given interval
function expand_range(start, end, interval) {
if(_.contains(['hour','day','week','month','year'],interval)) {
var range;
start = start.clone();
range = [];
while (start.isBefore(end)) {
range.push(start.clone());
switch (interval) {
case 'hour':
start.addHours(1)
break
case 'day':
start.addDays(1)
break
case 'week':
start.addWeeks(1)
break
case 'month':
start.addMonths(1)
break
case 'year':
start.addYears(1)
break
}
}
range.push(end.clone());
return range;
} else {
return false;
}
}
})