@spalger/kibana
Version:
Kibana is an open source (Apache Licensed), browser based analytics and search dashboard for Elasticsearch. Kibana is a snap to setup and start using. Kibana strives to be easy to get started with, while also being flexible and powerful, just like Elastic
281 lines (242 loc) • 8.38 kB
JavaScript
define(function (require) {
var _ = require('lodash');
var moment = require('moment');
var { IndexPatternMissingIndices } = require('ui/errors');
require('ui/directives/validate_index_name');
require('ui/directives/auto_select_if_only_one');
require('ui/routes')
.when('/settings/indices/', {
template: require('plugins/kibana/settings/sections/indices/_create.html')
});
require('ui/modules').get('apps/settings')
.controller('settingsIndicesCreate', function ($scope, kbnUrl, Private, Notifier, indexPatterns, es, config, Promise) {
var notify = new Notifier();
var refreshKibanaIndex = Private(require('plugins/kibana/settings/sections/indices/_refresh_kibana_index'));
var intervals = indexPatterns.intervals;
var samplePromise;
// this and child scopes will write pattern vars here
var index = $scope.index = {
name: 'logstash-*',
isTimeBased: true,
nameIsPattern: false,
sampleCount: 5,
nameIntervalOptions: intervals,
fetchFieldsError: 'Loading'
};
index.nameInterval = _.find(index.nameIntervalOptions, { name: 'daily' });
index.timeField = null;
$scope.refreshFieldList = function () {
fetchFieldList().then(updateFieldList);
};
$scope.createIndexPattern = function () {
// get an empty indexPattern to start
indexPatterns.get()
.then(function (indexPattern) {
// set both the id and title to the index index
indexPattern.id = indexPattern.title = index.name;
if (index.isTimeBased) {
indexPattern.timeFieldName = index.timeField.name;
if (index.nameIsPattern) {
indexPattern.intervalName = index.nameInterval.name;
}
}
// fetch the fields
return indexPattern.create()
.then(function (id) {
if (id) {
refreshKibanaIndex().then(function () {
if (!config.get('defaultIndex')) {
config.set('defaultIndex', indexPattern.id);
}
indexPatterns.cache.clear(indexPattern.id);
kbnUrl.change('/settings/indices/' + indexPattern.id);
});
}
});
// refreshFields calls save() after a successfull fetch, no need to save again
// .then(function () { indexPattern.save(); })
})
.catch(function (err) {
if (err instanceof IndexPatternMissingIndices) {
notify.error('Could not locate any indices matching that pattern. Please add the index to Elasticsearch');
}
else notify.fatal(err);
});
};
$scope.$watchMulti([
'index.isTimeBased',
'index.nameIsPattern',
'index.nameInterval.name'
], function (newVal, oldVal) {
var isTimeBased = newVal[0];
var nameIsPattern = newVal[1];
var newDefault = getPatternDefault(newVal[2]);
var oldDefault = getPatternDefault(oldVal[2]);
if (index.name === oldDefault) {
index.name = newDefault;
}
if (!isTimeBased) {
index.nameIsPattern = false;
}
if (!nameIsPattern) {
delete index.nameInterval;
delete index.timeField;
} else {
index.nameInterval = index.nameInterval || intervals.byName.days;
index.name = index.name || getPatternDefault(index.nameInterval);
}
});
$scope.moreSamples = function (andUpdate) {
index.sampleCount += 5;
if (andUpdate) updateSamples();
};
$scope.$watchMulti([
'index.name',
'index.nameInterval'
], function (newVal, oldVal) {
var lastPromise;
resetIndex();
samplePromise = lastPromise = updateSamples()
.then(function () {
promiseMatch(lastPromise, function () {
index.samples = null;
index.patternErrors = [];
});
})
.catch(function (errors) {
promiseMatch(lastPromise, function () {
index.existing = null;
index.patternErrors = errors;
});
})
.finally(function () {
// prevent running when no change happened (ie, first watcher call)
if (!_.isEqual(newVal, oldVal)) {
fetchFieldList().then(function (results) {
if (lastPromise === samplePromise) {
updateFieldList(results);
samplePromise = null;
}
});
}
});
});
$scope.$watchMulti([
'index.isTimeBased',
'index.sampleCount'
], $scope.refreshFieldList);
function updateSamples() {
var patternErrors = [];
if (!index.nameInterval || !index.name) {
return Promise.resolve();
}
var pattern = mockIndexPattern(index);
return indexPatterns.mapper.getIndicesForIndexPattern(pattern)
.catch(notify.error)
.then(function (existing) {
var all = existing.all;
var matches = existing.matches;
if (all.length) {
index.existing = {
class: 'success',
all: all,
matches: matches,
matchPercent: Math.round((matches.length / all.length) * 100) + '%',
failures: _.difference(all, matches)
};
return;
}
patternErrors.push('Pattern does not match any existing indices');
var radius = Math.round(index.sampleCount / 2);
var samples = intervals.toIndexList(index.name, index.nameInterval, -radius, radius);
if (_.uniq(samples).length !== samples.length) {
patternErrors.push('Invalid pattern, interval does not create unique index names');
} else {
index.samples = samples;
}
throw patternErrors;
});
}
function fetchFieldList() {
index.dateFields = index.timeField = index.listUsed = null;
var useIndexList = index.isTimeBased && index.nameIsPattern;
var fetchFieldsError;
var dateFields;
// we don't have enough info to continue
if (!index.name) {
fetchFieldsError = 'Set an index name first';
return;
}
if (useIndexList && !index.nameInterval) {
fetchFieldsError = 'Select the interval at which your indices are populated.';
return;
}
return indexPatterns.mapper.clearCache(index.name)
.then(function () {
var pattern = mockIndexPattern(index);
return indexPatterns.mapper.getFieldsForIndexPattern(pattern, true)
.catch(function (err) {
// TODO: we should probably display a message of some kind
if (err instanceof IndexPatternMissingIndices) {
fetchFieldsError = 'Unable to fetch mapping. Do you have indices matching the pattern?';
return [];
}
throw err;
});
})
.then(function (fields) {
if (fields.length > 0) {
fetchFieldsError = null;
dateFields = fields.filter(function (field) {
return field.type === 'date';
});
}
return {
fetchFieldsError: fetchFieldsError,
dateFields: dateFields
};
}, notify.fatal);
}
function updateFieldList(results) {
index.fetchFieldsError = results.fetchFieldsError;
index.dateFields = results.dateFields;
}
function promiseMatch(lastPromise, cb) {
if (lastPromise === samplePromise) {
cb();
} else if (samplePromise != null) {
// haven't hit the last promise yet, reset index params
resetIndex();
}
}
function resetIndex() {
index.patternErrors = [];
index.samples = null;
index.existing = null;
index.fetchFieldsError = 'Loading';
}
function getPatternDefault(interval) {
switch (interval) {
case 'hours':
return '[logstash-]YYYY.MM.DD.HH';
case 'days':
return '[logstash-]YYYY.MM.DD';
case 'weeks':
return '[logstash-]GGGG.WW';
case 'months':
return '[logstash-]YYYY.MM';
case 'years':
return '[logstash-]YYYY';
default:
return 'logstash-*';
}
}
function mockIndexPattern(index) {
// trick the mapper into thinking this is an indexPattern
return {
id: index.name,
intervalName: index.nameInterval
};
}
});
});