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.
|
|
|
|
|
|
|
|
|
|
*/
|
2013-02-05 08:05:36 +08:00
|
|
|
angular.module('kibana.timepicker', [])
|
2013-02-12 23:42:31 +08:00
|
|
|
.controller('timepicker', function($scope, eventBus, $timeout, timer, $http) {
|
2013-02-06 05:30:08 +08:00
|
|
|
|
2013-02-05 08:05:36 +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",
|
2013-02-28 01:00:39 +08:00
|
|
|
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-05 08:05:36 +08:00
|
|
|
}
|
|
|
|
|
}
|
2013-02-06 05:30:08 +08:00
|
|
|
_.defaults($scope.panel,_d)
|
|
|
|
|
|
2013-02-06 07:24:46 +08:00
|
|
|
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 = {
|
2013-03-13 06:59:50 +08:00
|
|
|
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 = {
|
2013-03-13 06:59:50 +08:00
|
|
|
from : new Date(Date.parse($scope.panel.time.from)) || time_ago($scope.panel.timespan),
|
2013-02-20 07:27:07 +08:00
|
|
|
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-05 08:05:36 +08:00
|
|
|
|
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
|
2013-02-06 07:24:46 +08:00
|
|
|
// This panel can handle multiple groups
|
2013-02-08 06:05:55 +08:00
|
|
|
eventBus.register($scope,"get_time", function(event,id) {
|
|
|
|
|
eventBus.broadcast($scope.$id,id,'time',$scope.time)
|
2013-02-05 08:05:36 +08:00
|
|
|
});
|
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()
|
|
|
|
|
});
|
|
|
|
|
|
2013-03-06 05:55:24 +08:00
|
|
|
$scope.$on('render', function (){
|
|
|
|
|
$scope.time_apply();
|
|
|
|
|
});
|
2013-02-28 05:47:43 +08:00
|
|
|
}
|
2013-02-06 07:24:46 +08:00
|
|
|
|
2013-02-28 05:47:43 +08:00
|
|
|
$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
|
|
|
}
|
2013-02-05 08:05:36 +08:00
|
|
|
|
|
|
|
|
$scope.refresh = function() {
|
|
|
|
|
if ($scope.panel.refresh.enable) {
|
2013-02-12 23:42:31 +08:00
|
|
|
timer.cancel($scope.refresh_timer)
|
2013-02-13 07:25:39 +08:00
|
|
|
$scope.refresh_timer = timer.register($timeout(function() {
|
|
|
|
|
$scope.refresh();
|
|
|
|
|
$scope.time_apply();
|
|
|
|
|
},$scope.panel.refresh.interval*1000
|
2013-02-12 23:42:31 +08:00
|
|
|
));
|
2013-02-05 08:05:36 +08:00
|
|
|
} else {
|
2013-02-12 23:42:31 +08:00
|
|
|
timer.cancel($scope.refresh_timer)
|
2013-02-05 08:05:36 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$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(){
|
2013-02-28 06:41:53 +08:00
|
|
|
|
2013-03-14 00:08:23 +08:00
|
|
|
// If time picker is defined (on initialization)
|
2013-02-20 07:27:07 +08:00
|
|
|
if(!(_.isUndefined($scope.timepicker))) {
|
|
|
|
|
var from = $scope.panel.mode === 'relative' ? time_ago($scope.panel.timespan) :
|
2013-02-28 06:41:53 +08:00
|
|
|
new Date(Date.parse($scope.timepicker.from.date + " " + $scope.timepicker.from.time))
|
2013-02-20 07:27:07 +08:00
|
|
|
var to = $scope.panel.mode !== 'absolute' ? new Date() :
|
2013-02-28 06:41:53 +08:00
|
|
|
new Date(Date.parse($scope.timepicker.to.date + " " + $scope.timepicker.to.time))
|
2013-03-14 00:08:23 +08:00
|
|
|
// Otherwise
|
2013-02-20 07:27:07 +08:00
|
|
|
} 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;
|
|
|
|
|
}
|
2013-02-05 08:05:36 +08:00
|
|
|
|
|
|
|
|
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-05 08:05:36 +08:00
|
|
|
});
|
|
|
|
|
|
2013-02-06 05:30:08 +08:00
|
|
|
return {
|
|
|
|
|
from : from,
|
|
|
|
|
to : to
|
2013-02-05 08:05:36 +08:00
|
|
|
};
|
2013-02-06 05:30:08 +08:00
|
|
|
}
|
2013-02-05 08:05:36 +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.
|
2013-02-28 01:00:39 +08:00
|
|
|
if($scope.panel.timed_indices) {
|
|
|
|
|
indices($scope.time.from,$scope.time.to).then(function (p) {
|
2013-02-28 03:51:59 +08:00
|
|
|
$scope.time.index = p;
|
2013-02-28 01:00:39 +08:00
|
|
|
eventBus.broadcast($scope.$id,$scope.panel.group,'time',$scope.time)
|
|
|
|
|
});
|
|
|
|
|
} else {
|
2013-02-28 06:48:26 +08:00
|
|
|
$scope.time.index = [$scope.panel.index];
|
2013-02-08 06:05:55 +08:00
|
|
|
eventBus.broadcast($scope.$id,$scope.panel.group,'time',$scope.time)
|
2013-02-28 01:00:39 +08:00
|
|
|
}
|
2013-02-05 08:05:36 +08:00
|
|
|
|
|
|
|
|
// 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-02-05 08:05:36 +08:00
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
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 = [];
|
2013-02-28 01:00:39 +08:00
|
|
|
_.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) {
|
2013-02-28 03:51:59 +08:00
|
|
|
var indices = _.intersection(possible,p);
|
2013-02-20 07:27:07 +08:00
|
|
|
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;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-28 01:00:39 +08:00
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-02-05 08:05:36 +08:00
|
|
|
})
|