mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Merge pull request #4914 from epixa/4899-error-build
Render version and build number in fatal errors
This commit is contained in:
commit
076717597a
7 changed files with 234 additions and 1 deletions
|
@ -21,6 +21,8 @@ ${pluginSlug}
|
|||
*/
|
||||
|
||||
window.__KBN__ = {
|
||||
version: '1.2.3',
|
||||
buildNum: 1234,
|
||||
vars: {
|
||||
kbnIndex: '.kibana',
|
||||
esShardTimeout: 1500,
|
||||
|
|
17
src/ui/public/__tests__/metadata.js
Normal file
17
src/ui/public/__tests__/metadata.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
describe('ui/metadata', () => {
|
||||
const expect = require('expect.js');
|
||||
|
||||
const metadata = require('ui/metadata');
|
||||
|
||||
it('is same data as window.__KBN__', () => {
|
||||
expect(metadata.version).to.equal(window.__KBN__.version);
|
||||
expect(metadata.vars.kbnIndex).to.equal(window.__KBN__.vars.kbnIndex);
|
||||
});
|
||||
|
||||
it('is immutable', () => {
|
||||
expect(() => metadata.foo = 'something').to.throw;
|
||||
expect(() => metadata.version = 'something').to.throw;
|
||||
expect(() => metadata.vars = {}).to.throw;
|
||||
expect(() => metadata.vars.kbnIndex = 'something').to.throw;
|
||||
});
|
||||
});
|
|
@ -8,6 +8,7 @@ require('ui/timefilter');
|
|||
require('ui/private');
|
||||
require('ui/promises');
|
||||
|
||||
var metadata = require('ui/metadata');
|
||||
var TabCollection = require('ui/chrome/TabCollection');
|
||||
|
||||
var chrome = {
|
||||
|
@ -17,7 +18,7 @@ var chrome = {
|
|||
};
|
||||
|
||||
var internals = _.assign(
|
||||
_.cloneDeep(window.__KBN__ || {}),
|
||||
_.cloneDeep(metadata),
|
||||
{
|
||||
tabs: new TabCollection(),
|
||||
rootController: null,
|
||||
|
|
24
src/ui/public/metadata.js
Normal file
24
src/ui/public/metadata.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
// singleton for immutable copy of window.__KBN__
|
||||
define(function (require) {
|
||||
const _ = require('lodash');
|
||||
|
||||
if (!_.has(window, '__KBN__')) {
|
||||
throw new Error('window.__KBN__ must be set for metadata');
|
||||
}
|
||||
|
||||
const kbn = _.cloneDeep(window.__KBN__ || {});
|
||||
return deepFreeze(kbn);
|
||||
|
||||
function deepFreeze(object) {
|
||||
// for any properties that reference an object, makes sure that object is
|
||||
// recursively frozen as well
|
||||
Object.keys(object).forEach(key => {
|
||||
const value = object[key];
|
||||
if (_.isObject(value)) {
|
||||
deepFreeze(value);
|
||||
}
|
||||
});
|
||||
|
||||
return Object.freeze(object);
|
||||
}
|
||||
});
|
|
@ -3,9 +3,13 @@ define(function (require) {
|
|||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
|
||||
var metadata = require('ui/metadata');
|
||||
|
||||
var notifs = [];
|
||||
var setTO = setTimeout;
|
||||
var clearTO = clearTimeout;
|
||||
var version = metadata.version;
|
||||
var buildNum = metadata.buildNum;
|
||||
var consoleGroups = ('group' in window.console) && ('groupCollapsed' in window.console) && ('groupEnd' in window.console);
|
||||
|
||||
var fatalSplashScreen = require('ui/notify/partials/fatal_splash_screen.html');
|
||||
|
@ -40,6 +44,9 @@ define(function (require) {
|
|||
}
|
||||
|
||||
function add(notif, cb) {
|
||||
_.set(notif, 'info.version', version);
|
||||
_.set(notif, 'info.buildNum', buildNum);
|
||||
|
||||
if (notif.lifetime !== Infinity) {
|
||||
notif.timerId = setTO(function () {
|
||||
closeNotif(cb, 'ignore').call(notif);
|
||||
|
@ -85,6 +92,20 @@ define(function (require) {
|
|||
return rtn;
|
||||
}
|
||||
|
||||
function formatInfo() {
|
||||
var info = [];
|
||||
|
||||
if (!_.isUndefined(version)) {
|
||||
info.push(`Version: ${version}`);
|
||||
}
|
||||
|
||||
if (!_.isUndefined(buildNum)) {
|
||||
info.push(`Build: ${buildNum}`);
|
||||
}
|
||||
|
||||
return info.join('\n');
|
||||
}
|
||||
|
||||
// browsers format Error.stack differently; always include message
|
||||
function formatStack(err) {
|
||||
if (err.stack && !~err.stack.indexOf(err.message)) {
|
||||
|
@ -192,6 +213,7 @@ define(function (require) {
|
|||
}
|
||||
|
||||
var html = fatalToastTemplate({
|
||||
info: formatInfo(),
|
||||
msg: formatMsg(err, this.from),
|
||||
stack: formatStack(err)
|
||||
});
|
||||
|
|
164
src/ui/public/notify/__tests__/Notifier.js
Normal file
164
src/ui/public/notify/__tests__/Notifier.js
Normal file
|
@ -0,0 +1,164 @@
|
|||
describe('Notifier', function () {
|
||||
var _ = require('lodash');
|
||||
var ngMock = require('ngMock');
|
||||
var expect = require('expect.js');
|
||||
var Notifier = require('ui/notify/Notifier');
|
||||
|
||||
var message = 'Oh, the humanity!';
|
||||
var notifier;
|
||||
var params;
|
||||
var version = window.__KBN__.version;
|
||||
var buildNum = window.__KBN__.buildNum;
|
||||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
|
||||
beforeEach(function () {
|
||||
params = { location: 'foo' };
|
||||
while (Notifier.prototype._notifs.pop()); // clear global notifications
|
||||
notifier = new Notifier(params);
|
||||
});
|
||||
|
||||
describe('#constructor()', function () {
|
||||
it('sets #from from given location', function () {
|
||||
expect(notifier.from).to.equal(params.location);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#error', function () {
|
||||
testVersionInfo('error');
|
||||
|
||||
it('prepends location to message for content', function () {
|
||||
expect(notify('error').content).to.equal(params.location + ': ' + message);
|
||||
});
|
||||
|
||||
it('sets type to "danger"', function () {
|
||||
expect(notify('error').type).to.equal('danger');
|
||||
});
|
||||
|
||||
it('sets icon to "warning"', function () {
|
||||
expect(notify('error').icon).to.equal('warning');
|
||||
});
|
||||
|
||||
it('sets title to "Error"', function () {
|
||||
expect(notify('error').title).to.equal('Error');
|
||||
});
|
||||
|
||||
it('sets lifetime to Infinity', function () {
|
||||
expect(notify('error').lifetime).to.equal(Infinity);
|
||||
});
|
||||
|
||||
it('allows reporting', function () {
|
||||
var includesReport = _.includes(notify('error').actions, 'report');
|
||||
expect(includesReport).to.true;
|
||||
});
|
||||
|
||||
it('allows accepting', function () {
|
||||
var includesAccept = _.includes(notify('error').actions, 'accept');
|
||||
expect(includesAccept).to.true;
|
||||
});
|
||||
|
||||
it('includes stack', function () {
|
||||
expect(notify('error').stack).to.be.defined;
|
||||
});
|
||||
});
|
||||
|
||||
describe('#warning', function () {
|
||||
testVersionInfo('warning');
|
||||
|
||||
it('prepends location to message for content', function () {
|
||||
expect(notify('warning').content).to.equal(params.location + ': ' + message);
|
||||
});
|
||||
|
||||
it('sets type to "warning"', function () {
|
||||
expect(notify('warning').type).to.equal('warning');
|
||||
});
|
||||
|
||||
it('sets icon to "warning"', function () {
|
||||
expect(notify('warning').icon).to.equal('warning');
|
||||
});
|
||||
|
||||
it('sets title to "Warning"', function () {
|
||||
expect(notify('warning').title).to.equal('Warning');
|
||||
});
|
||||
|
||||
it('sets lifetime to 10000', function () {
|
||||
expect(notify('warning').lifetime).to.equal(10000);
|
||||
});
|
||||
|
||||
it('does not allow reporting', function () {
|
||||
var includesReport = _.includes(notify('warning').actions, 'report');
|
||||
expect(includesReport).to.false;
|
||||
});
|
||||
|
||||
it('allows accepting', function () {
|
||||
var includesAccept = _.includes(notify('warning').actions, 'accept');
|
||||
expect(includesAccept).to.true;
|
||||
});
|
||||
|
||||
it('does not include stack', function () {
|
||||
expect(notify('warning').stack).not.to.be.defined;
|
||||
});
|
||||
});
|
||||
|
||||
describe('#info', function () {
|
||||
testVersionInfo('info');
|
||||
|
||||
it('prepends location to message for content', function () {
|
||||
expect(notify('info').content).to.equal(params.location + ': ' + message);
|
||||
});
|
||||
|
||||
it('sets type to "info"', function () {
|
||||
expect(notify('info').type).to.equal('info');
|
||||
});
|
||||
|
||||
it('sets icon to "info-circle"', function () {
|
||||
expect(notify('info').icon).to.equal('info-circle');
|
||||
});
|
||||
|
||||
it('sets title to "Debug"', function () {
|
||||
expect(notify('info').title).to.equal('Debug');
|
||||
});
|
||||
|
||||
it('sets lifetime to 5000', function () {
|
||||
expect(notify('info').lifetime).to.equal(5000);
|
||||
});
|
||||
|
||||
it('does not allow reporting', function () {
|
||||
var includesReport = _.includes(notify('info').actions, 'report');
|
||||
expect(includesReport).to.false;
|
||||
});
|
||||
|
||||
it('allows accepting', function () {
|
||||
var includesAccept = _.includes(notify('info').actions, 'accept');
|
||||
expect(includesAccept).to.true;
|
||||
});
|
||||
|
||||
it('does not include stack', function () {
|
||||
expect(notify('info').stack).not.to.be.defined;
|
||||
});
|
||||
});
|
||||
|
||||
function notify(fnName) {
|
||||
notifier[fnName](message);
|
||||
return latestNotification();
|
||||
}
|
||||
|
||||
function latestNotification() {
|
||||
return _.last(notifier._notifs);
|
||||
}
|
||||
|
||||
function testVersionInfo(fnName) {
|
||||
context('when version is configured', function () {
|
||||
it('adds version to notification', function () {
|
||||
var notification = notify(fnName);
|
||||
expect(notification.info.version).to.equal(version);
|
||||
});
|
||||
});
|
||||
context('when build number is configured', function () {
|
||||
it('adds buildNum to notification', function () {
|
||||
var notification = notify(fnName);
|
||||
expect(notification.info.buildNum).to.equal(buildNum);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
|
@ -12,6 +12,9 @@
|
|||
</h1>
|
||||
</div>
|
||||
<div class="panel-body fatal-body"><%- msg %></div>
|
||||
<% if (info) { %>
|
||||
<div class="panel-footer"><pre><%- info %></pre></div>
|
||||
<% } %>
|
||||
<% if (stack) { %>
|
||||
<div class="panel-footer"><pre><%- stack %></pre></div>
|
||||
<% } %>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue