mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Backports the following commits to 6.x: - [devUtils/toolingLog] give tooling log configurable writers (#22110)
This commit is contained in:
parent
377644bd4b
commit
8faacedc17
44 changed files with 1272 additions and 475 deletions
19
packages/kbn-dev-utils/index.d.ts
vendored
19
packages/kbn-dev-utils/index.d.ts
vendored
|
@ -17,21 +17,4 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { Readable } from 'stream';
|
||||
|
||||
type LogLevel = 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose';
|
||||
|
||||
export class ToolingLog extends Readable {
|
||||
public verbose(...args: any[]): void;
|
||||
public debug(...args: any[]): void;
|
||||
public info(...args: any[]): void;
|
||||
public success(...args: any[]): void;
|
||||
public warning(...args: any[]): void;
|
||||
public error(errOrMsg: string | Error): void;
|
||||
public write(...args: any[]): void;
|
||||
public indent(spaces: number): void;
|
||||
public getLevel(): LogLevel;
|
||||
public setLevel(level: LogLevel): void;
|
||||
}
|
||||
|
||||
export function createToolingLog(level?: LogLevel): ToolingLog;
|
||||
export * from './src/tooling_log';
|
||||
|
|
|
@ -18,4 +18,4 @@
|
|||
*/
|
||||
|
||||
export { withProcRunner } from './proc_runner';
|
||||
export { createToolingLog, pickLevelFromFlags } from './tooling_log';
|
||||
export { ToolingLog, pickLevelFromFlags } from './tooling_log';
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { createToolingLog } from '../../tooling_log';
|
||||
import { ToolingLog } from '../../tooling_log';
|
||||
import { withProcRunner } from '../with_proc_runner';
|
||||
|
||||
describe('proc runner', () => {
|
||||
|
@ -34,7 +34,7 @@ describe('proc runner', () => {
|
|||
}
|
||||
|
||||
it('passes procs to a function', async () => {
|
||||
await withProcRunner(createToolingLog(), async procs => {
|
||||
await withProcRunner(new ToolingLog(), async procs => {
|
||||
await runProc({ procs });
|
||||
await procs.stop('proc');
|
||||
});
|
||||
|
|
|
@ -82,7 +82,7 @@ export function createProc(name, { cmd, args, cwd, env, stdin, log }) {
|
|||
name = name;
|
||||
|
||||
lines$ = Rx.merge(observeLines(childProcess.stdout), observeLines(childProcess.stderr)).pipe(
|
||||
tap(line => log.write(` ${gray('proc')} [${gray(name)}] ${line}`)),
|
||||
tap(line => log.write(` ${gray('proc')} [${gray(name)}] ${line}`)),
|
||||
share()
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`parses valid log levels correctly: debug 1`] = `
|
||||
Object {
|
||||
"flags": Object {
|
||||
"debug": true,
|
||||
"error": true,
|
||||
"info": true,
|
||||
"silent": true,
|
||||
"verbose": false,
|
||||
"warning": true,
|
||||
},
|
||||
"name": "debug",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`parses valid log levels correctly: error 1`] = `
|
||||
Object {
|
||||
"flags": Object {
|
||||
"debug": false,
|
||||
"error": true,
|
||||
"info": false,
|
||||
"silent": true,
|
||||
"verbose": false,
|
||||
"warning": false,
|
||||
},
|
||||
"name": "error",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`parses valid log levels correctly: info 1`] = `
|
||||
Object {
|
||||
"flags": Object {
|
||||
"debug": false,
|
||||
"error": true,
|
||||
"info": true,
|
||||
"silent": true,
|
||||
"verbose": false,
|
||||
"warning": true,
|
||||
},
|
||||
"name": "info",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`parses valid log levels correctly: silent 1`] = `
|
||||
Object {
|
||||
"flags": Object {
|
||||
"debug": false,
|
||||
"error": false,
|
||||
"info": false,
|
||||
"silent": true,
|
||||
"verbose": false,
|
||||
"warning": false,
|
||||
},
|
||||
"name": "silent",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`parses valid log levels correctly: verbose 1`] = `
|
||||
Object {
|
||||
"flags": Object {
|
||||
"debug": true,
|
||||
"error": true,
|
||||
"info": true,
|
||||
"silent": true,
|
||||
"verbose": true,
|
||||
"warning": true,
|
||||
},
|
||||
"name": "verbose",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`parses valid log levels correctly: warning 1`] = `
|
||||
Object {
|
||||
"flags": Object {
|
||||
"debug": false,
|
||||
"error": true,
|
||||
"info": false,
|
||||
"silent": true,
|
||||
"verbose": false,
|
||||
"warning": true,
|
||||
},
|
||||
"name": "warning",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`throws error for invalid levels: bar 1`] = `"Invalid log level \\"bar\\" (expected one of silent,error,warning,info,debug,verbose)"`;
|
||||
|
||||
exports[`throws error for invalid levels: foo 1`] = `"Invalid log level \\"foo\\" (expected one of silent,error,warning,info,debug,verbose)"`;
|
||||
|
||||
exports[`throws error for invalid levels: warn 1`] = `"Invalid log level \\"warn\\" (expected one of silent,error,warning,info,debug,verbose)"`;
|
|
@ -0,0 +1,226 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`#debug() sends a msg of type "debug" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "debug",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#error() sends a msg of type "error" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
[Error: error message],
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "error",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"string message",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "error",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#getWritten$() does not emit msg if all writers return false 1`] = `Array []`;
|
||||
|
||||
exports[`#getWritten$() does not emit msg when no writers 1`] = `Array []`;
|
||||
|
||||
exports[`#getWritten$() emits msg if all writers return true 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "debug",
|
||||
},
|
||||
Object {
|
||||
"args": Array [
|
||||
"bar",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "info",
|
||||
},
|
||||
Object {
|
||||
"args": Array [
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "verbose",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#getWritten$() emits msg if some writers return true 1`] = `
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "debug",
|
||||
},
|
||||
Object {
|
||||
"args": Array [
|
||||
"bar",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "info",
|
||||
},
|
||||
Object {
|
||||
"args": Array [
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "verbose",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#indent() changes the indent on each written msg 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
],
|
||||
"indent": 1,
|
||||
"type": "debug",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"bar",
|
||||
],
|
||||
"indent": 3,
|
||||
"type": "debug",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"baz",
|
||||
],
|
||||
"indent": 6,
|
||||
"type": "debug",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"box",
|
||||
],
|
||||
"indent": 4,
|
||||
"type": "debug",
|
||||
},
|
||||
],
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "debug",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#info() sends a msg of type "info" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "info",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#success() sends a msg of type "success" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "success",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#verbose() sends a msg of type "verbose" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "verbose",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#warning() sends a msg of type "warning" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "warning",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`#write() sends a msg of type "write" to each writer with indent and arguments 1`] = `
|
||||
Array [
|
||||
Array [
|
||||
Object {
|
||||
"args": Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
],
|
||||
"indent": 0,
|
||||
"type": "write",
|
||||
},
|
||||
],
|
||||
]
|
||||
`;
|
|
@ -0,0 +1,178 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`formats %s patterns and indents multi-line messages correctly 1`] = `
|
||||
" │ [32msucc[39m foo bar
|
||||
│ { foo: { bar: { '1': [Array] } },
|
||||
│ bar: { bar: { '1': [Array] } } }
|
||||
│
|
||||
│ Infinity
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:debug/type:debug snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:debug/type:debug snapshots: output 1`] = `
|
||||
" [2mdebg[22m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:debug/type:error snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:debug/type:error snapshots: output 1`] = `
|
||||
"[31mERROR[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:debug/type:info snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:debug/type:info snapshots: output 1`] = `
|
||||
" [34minfo[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:debug/type:success snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:debug/type:success snapshots: output 1`] = `
|
||||
" [32msucc[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:debug/type:verbose snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:debug/type:warning snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:debug/type:warning snapshots: output 1`] = `
|
||||
" [33mwarn[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:error/type:debug snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:error/type:error snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:error/type:error snapshots: output 1`] = `
|
||||
"[31mERROR[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:error/type:info snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:error/type:success snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:error/type:verbose snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:error/type:warning snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:info/type:debug snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:info/type:error snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:info/type:error snapshots: output 1`] = `
|
||||
"[31mERROR[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:info/type:info snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:info/type:info snapshots: output 1`] = `
|
||||
" [34minfo[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:info/type:success snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:info/type:success snapshots: output 1`] = `
|
||||
" [32msucc[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:info/type:verbose snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:info/type:warning snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:info/type:warning snapshots: output 1`] = `
|
||||
" [33mwarn[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:silent/type:debug snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:silent/type:error snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:silent/type:info snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:silent/type:success snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:silent/type:verbose snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:silent/type:warning snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:verbose/type:debug snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:verbose/type:debug snapshots: output 1`] = `
|
||||
" [2mdebg[22m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:verbose/type:error snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:verbose/type:error snapshots: output 1`] = `
|
||||
"[31mERROR[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:verbose/type:info snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:verbose/type:info snapshots: output 1`] = `
|
||||
" [34minfo[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:verbose/type:success snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:verbose/type:success snapshots: output 1`] = `
|
||||
" [32msucc[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:verbose/type:verbose snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:verbose/type:verbose snapshots: output 1`] = `
|
||||
" [95msill[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:verbose/type:warning snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:verbose/type:warning snapshots: output 1`] = `
|
||||
" [33mwarn[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:warning/type:debug snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:warning/type:error snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:warning/type:error snapshots: output 1`] = `
|
||||
"[31mERROR[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`level:warning/type:info snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:warning/type:success snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:warning/type:verbose snapshots: is written 1`] = `false`;
|
||||
|
||||
exports[`level:warning/type:warning snapshots: is written 1`] = `true`;
|
||||
|
||||
exports[`level:warning/type:warning snapshots: output 1`] = `
|
||||
" [33mwarn[39m foo
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`throws error if created with invalid level 1`] = `"Invalid log level \\"foo\\" (expected one of silent,error,warning,info,debug,verbose)"`;
|
||||
|
||||
exports[`throws error if writeTo config is not defined or doesn't have a write method 1`] = `"ToolingLogTextWriter requires the \`writeTo\` option be set to a stream (like process.stdout)"`;
|
||||
|
||||
exports[`throws error if writeTo config is not defined or doesn't have a write method 2`] = `"ToolingLogTextWriter requires the \`writeTo\` option be set to a stream (like process.stdout)"`;
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
import Chance from 'chance';
|
||||
|
||||
import { createConcatStream, createPromiseFromStreams } from '../../streams';
|
||||
|
||||
import { createToolingLog } from '../tooling_log';
|
||||
|
||||
const chance = new Chance();
|
||||
const capture = (level, block) => {
|
||||
const log = createToolingLog(level);
|
||||
block(log);
|
||||
log.end();
|
||||
return createPromiseFromStreams([log, createConcatStream('')]);
|
||||
};
|
||||
|
||||
const nothingTest = (logLevel, method) => {
|
||||
describe(`#${method}(...any)`, () => {
|
||||
it('logs nothing', async () => {
|
||||
const output = await capture(logLevel, log => log[method]('foo'));
|
||||
expect(output).to.be('');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const somethingTest = (logLevel, method) => {
|
||||
describe(`#${method}(...any)`, () => {
|
||||
it('logs to output stream', async () => {
|
||||
const output = await capture(logLevel, log => log[method]('foo'));
|
||||
expect(output).to.contain('foo');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
describe('utils: createToolingLog(logLevel, output)', () => {
|
||||
it('is a readable stream', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
log.info('Foo');
|
||||
log.info('Bar');
|
||||
log.info('Baz');
|
||||
log.end();
|
||||
|
||||
const output = await createPromiseFromStreams([log, createConcatStream('')]);
|
||||
|
||||
expect(output).to.contain('Foo');
|
||||
expect(output).to.contain('Bar');
|
||||
expect(output).to.contain('Baz');
|
||||
});
|
||||
|
||||
describe('log level', () => {
|
||||
describe('logLevel=silent', () => {
|
||||
nothingTest('silent', 'debug');
|
||||
nothingTest('silent', 'info');
|
||||
nothingTest('silent', 'error');
|
||||
});
|
||||
describe('logLevel=error', () => {
|
||||
nothingTest('error', 'debug');
|
||||
nothingTest('error', 'info');
|
||||
somethingTest('error', 'error');
|
||||
});
|
||||
describe('logLevel=info', () => {
|
||||
nothingTest('info', 'debug');
|
||||
somethingTest('info', 'info');
|
||||
somethingTest('info', 'error');
|
||||
});
|
||||
describe('logLevel=debug', () => {
|
||||
somethingTest('debug', 'debug');
|
||||
somethingTest('debug', 'info');
|
||||
somethingTest('debug', 'error');
|
||||
});
|
||||
describe('invalid logLevel', () => {
|
||||
it('throw error', () => {
|
||||
// avoid the impossibility that a valid level is generated
|
||||
// by specifying a long length
|
||||
const level = chance.word({ length: 10 });
|
||||
|
||||
expect(() => createToolingLog(level)).to.throwError(level);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect.js';
|
||||
import Chance from 'chance';
|
||||
import { parseLogLevel } from '../log_levels';
|
||||
|
||||
const chance = new Chance();
|
||||
|
||||
describe('parseLogLevel(logLevel).flags', () => {
|
||||
describe('logLevel=silent', () => {
|
||||
it('produces correct map', () => {
|
||||
expect(parseLogLevel('silent').flags).to.eql({
|
||||
silent: true,
|
||||
error: false,
|
||||
warning: false,
|
||||
info: false,
|
||||
debug: false,
|
||||
verbose: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('logLevel=error', () => {
|
||||
it('produces correct map', () => {
|
||||
expect(parseLogLevel('error').flags).to.eql({
|
||||
silent: true,
|
||||
error: true,
|
||||
warning: false,
|
||||
info: false,
|
||||
debug: false,
|
||||
verbose: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('logLevel=warning', () => {
|
||||
it('produces correct map', () => {
|
||||
expect(parseLogLevel('warning').flags).to.eql({
|
||||
silent: true,
|
||||
error: true,
|
||||
warning: true,
|
||||
info: false,
|
||||
debug: false,
|
||||
verbose: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('logLevel=info', () => {
|
||||
it('produces correct map', () => {
|
||||
expect(parseLogLevel('info').flags).to.eql({
|
||||
silent: true,
|
||||
error: true,
|
||||
warning: true,
|
||||
info: true,
|
||||
debug: false,
|
||||
verbose: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('logLevel=debug', () => {
|
||||
it('produces correct map', () => {
|
||||
expect(parseLogLevel('debug').flags).to.eql({
|
||||
silent: true,
|
||||
error: true,
|
||||
warning: true,
|
||||
info: true,
|
||||
debug: true,
|
||||
verbose: false,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('logLevel=verbose', () => {
|
||||
it('produces correct map', () => {
|
||||
expect(parseLogLevel('verbose').flags).to.eql({
|
||||
silent: true,
|
||||
error: true,
|
||||
warning: true,
|
||||
info: true,
|
||||
debug: true,
|
||||
verbose: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('invalid logLevel', () => {
|
||||
it('throws error', () => {
|
||||
// avoid the impossibility that a valid level is generated
|
||||
// by specifying a long length
|
||||
const level = chance.word({ length: 10 });
|
||||
|
||||
expect(() => parseLogLevel(level)).to.throwError(level);
|
||||
});
|
||||
});
|
||||
});
|
22
packages/kbn-dev-utils/src/tooling_log/index.d.ts
vendored
Normal file
22
packages/kbn-dev-utils/src/tooling_log/index.d.ts
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export { ToolingLog } from './tooling_log';
|
||||
export { ToolingLogTextWriter, WriterConfig } from './tooling_log_text_writer';
|
||||
export { pickLevelFromFlags, LogLevel } from './log_levels';
|
|
@ -17,5 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
export { createToolingLog } from './tooling_log';
|
||||
export { ToolingLog } from './tooling_log';
|
||||
export { ToolingLogTextWriter } from './tooling_log_text_writer';
|
||||
export { pickLevelFromFlags } from './log_levels';
|
||||
|
|
29
packages/kbn-dev-utils/src/tooling_log/log_levels.d.ts
vendored
Normal file
29
packages/kbn-dev-utils/src/tooling_log/log_levels.d.ts
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export type LogLevel = 'silent' | 'error' | 'warning' | 'info' | 'debug' | 'verbose';
|
||||
|
||||
export interface ParsedLogLevel {
|
||||
name: LogLevel;
|
||||
flags: { [key in LogLevel]: boolean };
|
||||
}
|
||||
|
||||
export function pickLevelFromFlags(flags: { [key: string]: any }): LogLevel;
|
||||
|
||||
export function parseLogLevel(level: LogLevel): ParsedLogLevel;
|
35
packages/kbn-dev-utils/src/tooling_log/log_levels.test.js
Normal file
35
packages/kbn-dev-utils/src/tooling_log/log_levels.test.js
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { parseLogLevel } from './log_levels';
|
||||
|
||||
it('parses valid log levels correctly', () => {
|
||||
expect(parseLogLevel('silent')).toMatchSnapshot('silent');
|
||||
expect(parseLogLevel('error')).toMatchSnapshot('error');
|
||||
expect(parseLogLevel('warning')).toMatchSnapshot('warning');
|
||||
expect(parseLogLevel('info')).toMatchSnapshot('info');
|
||||
expect(parseLogLevel('debug')).toMatchSnapshot('debug');
|
||||
expect(parseLogLevel('verbose')).toMatchSnapshot('verbose');
|
||||
});
|
||||
|
||||
it('throws error for invalid levels', () => {
|
||||
expect(() => parseLogLevel('warn')).toThrowErrorMatchingSnapshot('warn');
|
||||
expect(() => parseLogLevel('foo')).toThrowErrorMatchingSnapshot('foo');
|
||||
expect(() => parseLogLevel('bar')).toThrowErrorMatchingSnapshot('bar');
|
||||
});
|
45
packages/kbn-dev-utils/src/tooling_log/tooling_log.d.ts
vendored
Normal file
45
packages/kbn-dev-utils/src/tooling_log/tooling_log.d.ts
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
// tslint:disable max-classes-per-file
|
||||
|
||||
import * as Rx from 'rxjs';
|
||||
|
||||
import { ToolingLogWriter, WriterConfig } from './tooling_log_text_writer';
|
||||
|
||||
export interface LogMessage {
|
||||
type: 'verbose' | 'debug' | 'info' | 'success' | 'warning' | 'error' | 'write';
|
||||
indent: number;
|
||||
args: any[];
|
||||
}
|
||||
|
||||
export class ToolingLog {
|
||||
constructor(config?: WriterConfig);
|
||||
public verbose(...args: any[]): void;
|
||||
public debug(...args: any[]): void;
|
||||
public info(...args: any[]): void;
|
||||
public success(...args: any[]): void;
|
||||
public warning(...args: any[]): void;
|
||||
public error(errOrMsg: string | Error): void;
|
||||
public write(...args: any[]): void;
|
||||
public indent(spaces: number): void;
|
||||
public getWriters(): ToolingLogWriter[];
|
||||
public setWriters(reporters: ToolingLogWriter[]): void;
|
||||
public getWritten$(): Rx.Observable<LogMessage>;
|
||||
}
|
|
@ -17,87 +17,85 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { format } from 'util';
|
||||
import { PassThrough } from 'stream';
|
||||
import * as Rx from 'rxjs';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
import { magentaBright, yellow, red, blue, green, dim } from 'chalk';
|
||||
import { ToolingLogTextWriter } from './tooling_log_text_writer';
|
||||
|
||||
import { parseLogLevel } from './log_levels';
|
||||
export class ToolingLog extends EventEmitter {
|
||||
/**
|
||||
* Create a ToolingLog object
|
||||
* @param {WriterConfig} writerConfig
|
||||
*/
|
||||
constructor(writerConfig) {
|
||||
super();
|
||||
|
||||
export function createToolingLog(initialLogLevelName = 'silent') {
|
||||
// current log level (see logLevel.name and logLevel.flags) changed
|
||||
// with ToolingLog#setLevel(newLogLevelName);
|
||||
let logLevel = parseLogLevel(initialLogLevelName);
|
||||
|
||||
// current indentation level, changed with ToolingLog#indent(delta)
|
||||
let indentString = '';
|
||||
|
||||
class ToolingLog extends PassThrough {
|
||||
constructor() {
|
||||
super({ objectMode: true });
|
||||
}
|
||||
|
||||
verbose(...args) {
|
||||
if (!logLevel.flags.verbose) return;
|
||||
this.write(' %s ', magentaBright('sill'), format(...args));
|
||||
}
|
||||
|
||||
debug(...args) {
|
||||
if (!logLevel.flags.debug) return;
|
||||
this.write(' %s ', dim('debg'), format(...args));
|
||||
}
|
||||
|
||||
info(...args) {
|
||||
if (!logLevel.flags.info) return;
|
||||
this.write(' %s ', blue('info'), format(...args));
|
||||
}
|
||||
|
||||
success(...args) {
|
||||
if (!logLevel.flags.info) return;
|
||||
this.write(' %s ', green('succ'), format(...args));
|
||||
}
|
||||
|
||||
warning(...args) {
|
||||
if (!logLevel.flags.warning) return;
|
||||
this.write(' %s ', yellow('warn'), format(...args));
|
||||
}
|
||||
|
||||
error(err) {
|
||||
if (!logLevel.flags.error) return;
|
||||
|
||||
if (typeof err !== 'string' && !(err instanceof Error)) {
|
||||
err = new Error(`"${err}" thrown`);
|
||||
}
|
||||
|
||||
this.write('%s ', red('ERROR'), err.stack || err.message || err);
|
||||
}
|
||||
|
||||
indent(delta = 0) {
|
||||
const width = Math.max(0, indentString.length + delta);
|
||||
indentString = ' '.repeat(width);
|
||||
return indentString.length;
|
||||
}
|
||||
|
||||
getLevel() {
|
||||
return logLevel.name;
|
||||
}
|
||||
|
||||
setLevel(newLogLevelName) {
|
||||
logLevel = parseLogLevel(newLogLevelName);
|
||||
}
|
||||
|
||||
write(...args) {
|
||||
format(...args)
|
||||
.split('\n')
|
||||
.forEach((line, i) => {
|
||||
const subLineIndent = i === 0 ? '' : ' ';
|
||||
const indent = !indentString
|
||||
? ''
|
||||
: indentString.slice(0, -1) + (i === 0 && line[0] === '-' ? '└' : '│');
|
||||
super.write(`${indent}${subLineIndent}${line}\n`);
|
||||
});
|
||||
}
|
||||
this._indent = 0;
|
||||
this._writers = writerConfig ? [new ToolingLogTextWriter(writerConfig)] : [];
|
||||
this._written$ = new Rx.Subject();
|
||||
}
|
||||
|
||||
return new ToolingLog();
|
||||
indent(delta = 0) {
|
||||
this._indent = Math.max(this._indent + delta, 0);
|
||||
return this._indent;
|
||||
}
|
||||
|
||||
verbose(...args) {
|
||||
this._write('verbose', args);
|
||||
}
|
||||
|
||||
debug(...args) {
|
||||
this._write('debug', args);
|
||||
}
|
||||
|
||||
info(...args) {
|
||||
this._write('info', args);
|
||||
}
|
||||
|
||||
success(...args) {
|
||||
this._write('success', args);
|
||||
}
|
||||
|
||||
warning(...args) {
|
||||
this._write('warning', args);
|
||||
}
|
||||
|
||||
error(error) {
|
||||
this._write('error', [error]);
|
||||
}
|
||||
|
||||
write(...args) {
|
||||
this._write('write', args);
|
||||
}
|
||||
|
||||
getWriters() {
|
||||
return this._writers.slice(0);
|
||||
}
|
||||
|
||||
setWriters(writers) {
|
||||
this._writers = [...writers];
|
||||
}
|
||||
|
||||
getWritten$() {
|
||||
return this._written$.asObservable();
|
||||
}
|
||||
|
||||
_write(type, args) {
|
||||
const msg = {
|
||||
type,
|
||||
indent: this._indent,
|
||||
args,
|
||||
};
|
||||
|
||||
let written = false;
|
||||
for (const writer of this._writers) {
|
||||
if (writer.write(msg)) {
|
||||
written = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (written) {
|
||||
this._written$.next(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
143
packages/kbn-dev-utils/src/tooling_log/tooling_log.test.js
Normal file
143
packages/kbn-dev-utils/src/tooling_log/tooling_log.test.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import * as Rx from 'rxjs';
|
||||
import { toArray, takeUntil } from 'rxjs/operators';
|
||||
|
||||
import { ToolingLog } from './tooling_log';
|
||||
import { ToolingLogTextWriter } from './tooling_log_text_writer';
|
||||
|
||||
it('creates zero writers without a config', () => {
|
||||
const log = new ToolingLog();
|
||||
expect(log.getWriters()).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('creates a single writer with a single object', () => {
|
||||
const log = new ToolingLog({ level: 'warning', writeTo: process.stdout });
|
||||
expect(log.getWriters()).toHaveLength(1);
|
||||
const [writer] = log.getWriters();
|
||||
expect(writer.level).toHaveProperty('name', 'warning');
|
||||
expect(writer.writeTo).toBe(process.stdout);
|
||||
});
|
||||
|
||||
describe('#get/setWriters()', () => {
|
||||
it('returns/replaces the current writers', () => {
|
||||
const log = new ToolingLog();
|
||||
expect(log.getWriters()).toHaveLength(0);
|
||||
|
||||
log.setWriters([
|
||||
new ToolingLogTextWriter({
|
||||
level: 'verbose',
|
||||
writeTo: process.stdout,
|
||||
}),
|
||||
new ToolingLogTextWriter({
|
||||
level: 'verbose',
|
||||
writeTo: process.stdout,
|
||||
}),
|
||||
]);
|
||||
expect(log.getWriters()).toHaveLength(2);
|
||||
|
||||
log.setWriters([]);
|
||||
expect(log.getWriters()).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#indent()', () => {
|
||||
it('changes the indent on each written msg', () => {
|
||||
const log = new ToolingLog();
|
||||
const write = jest.fn();
|
||||
log.setWriters([{ write }]);
|
||||
|
||||
log.indent(1);
|
||||
log.debug('foo');
|
||||
log.indent(2);
|
||||
log.debug('bar');
|
||||
log.indent(3);
|
||||
log.debug('baz');
|
||||
log.indent(-2);
|
||||
log.debug('box');
|
||||
log.indent(-Infinity);
|
||||
log.debug('foo');
|
||||
|
||||
expect(write.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
['verbose', 'debug', 'info', 'success', 'warning', 'error', 'write'].forEach(method => {
|
||||
describe(`#${method}()`, () => {
|
||||
it(`sends a msg of type "${method}" to each writer with indent and arguments`, () => {
|
||||
const log = new ToolingLog();
|
||||
const writeA = jest.fn();
|
||||
const writeB = jest.fn();
|
||||
|
||||
log.setWriters([{ write: writeA }, { write: writeB }]);
|
||||
|
||||
if (method === 'error') {
|
||||
const error = new Error('error message');
|
||||
error.stack = '... stack trace ...';
|
||||
log.error(error);
|
||||
log.error('string message');
|
||||
} else {
|
||||
log[method]('foo', 'bar', 'baz');
|
||||
}
|
||||
|
||||
expect(writeA.mock.calls).toMatchSnapshot();
|
||||
expect(writeA.mock.calls).toEqual(writeB.mock.calls);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getWritten$()', () => {
|
||||
async function testWrittenMsgs(writers) {
|
||||
const log = new ToolingLog();
|
||||
log.setWriters(writers);
|
||||
|
||||
const done$ = new Rx.Subject();
|
||||
const promise = log
|
||||
.getWritten$()
|
||||
.pipe(
|
||||
takeUntil(done$),
|
||||
toArray()
|
||||
)
|
||||
.toPromise();
|
||||
|
||||
log.debug('foo');
|
||||
log.info('bar');
|
||||
log.verbose('baz');
|
||||
done$.next();
|
||||
|
||||
expect(await promise).toMatchSnapshot();
|
||||
}
|
||||
|
||||
it('does not emit msg when no writers', async () => {
|
||||
await testWrittenMsgs([]);
|
||||
});
|
||||
|
||||
it('emits msg if all writers return true', async () => {
|
||||
await testWrittenMsgs([{ write: jest.fn(() => true) }, { write: jest.fn(() => true) }]);
|
||||
});
|
||||
|
||||
it('emits msg if some writers return true', async () => {
|
||||
await testWrittenMsgs([{ write: jest.fn(() => true) }, { write: jest.fn(() => false) }]);
|
||||
});
|
||||
|
||||
it('does not emit msg if all writers return false', async () => {
|
||||
await testWrittenMsgs([{ write: jest.fn(() => false) }, { write: jest.fn(() => false) }]);
|
||||
});
|
||||
});
|
42
packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.d.ts
vendored
Normal file
42
packages/kbn-dev-utils/src/tooling_log/tooling_log_text_writer.d.ts
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { LogLevel, ParsedLogLevel } from './log_levels';
|
||||
import { LogMessage } from './tooling_log';
|
||||
|
||||
export interface ToolingLogWriter {
|
||||
write(msg: LogMessage): boolean;
|
||||
}
|
||||
|
||||
export interface WriteTarget {
|
||||
write(chunk: string): void;
|
||||
}
|
||||
|
||||
export interface WriterConfig {
|
||||
level: LogLevel;
|
||||
writeTo: WriteTarget;
|
||||
}
|
||||
|
||||
export class ToolingLogTextWriter implements ToolingLogTextWriter {
|
||||
public level: ParsedLogLevel;
|
||||
public writeTo: WriteTarget;
|
||||
|
||||
constructor(config: WriterConfig);
|
||||
public write(msg: LogMessage): boolean;
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { format } from 'util';
|
||||
|
||||
import { magentaBright, yellow, red, blue, green, dim } from 'chalk';
|
||||
|
||||
import { parseLogLevel } from './log_levels';
|
||||
|
||||
const PREFIX_INDENT = ' '.repeat(6);
|
||||
const MSG_PREFIXES = {
|
||||
verbose: ` ${magentaBright('sill')} `,
|
||||
debug: ` ${dim('debg')} `,
|
||||
info: ` ${blue('info')} `,
|
||||
success: ` ${green('succ')} `,
|
||||
warning: ` ${yellow('warn')} `,
|
||||
error: `${red('ERROR')} `,
|
||||
};
|
||||
|
||||
function shouldWriteType(level, type) {
|
||||
if (type === 'write') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Boolean(level.flags[type === 'success' ? 'info' : type]);
|
||||
}
|
||||
|
||||
function stringifyError(error) {
|
||||
if (typeof error !== 'string' && !(error instanceof Error)) {
|
||||
error = new Error(`"${error}" thrown`);
|
||||
}
|
||||
|
||||
return error.stack || error.message || error;
|
||||
}
|
||||
|
||||
export class ToolingLogTextWriter {
|
||||
constructor(config) {
|
||||
this.level = parseLogLevel(config.level);
|
||||
this.writeTo = config.writeTo;
|
||||
|
||||
if (!this.writeTo || typeof this.writeTo.write !== 'function') {
|
||||
throw new Error(
|
||||
'ToolingLogTextWriter requires the `writeTo` option be set to a stream (like process.stdout)'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
write({ type, indent, args }) {
|
||||
if (!shouldWriteType(this.level, type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const txt = type === 'error' ? stringifyError(args[0]) : format(...args);
|
||||
const prefix = MSG_PREFIXES[type] || '';
|
||||
|
||||
(prefix + txt).split('\n').forEach((line, i) => {
|
||||
let lineIndent = '';
|
||||
|
||||
if (indent > 0) {
|
||||
// if we are indenting write some spaces followed by a symbol
|
||||
lineIndent += ' '.repeat(indent - 1);
|
||||
lineIndent += line.startsWith('-') ? '└' : '│';
|
||||
}
|
||||
|
||||
if (line && prefix && i > 0) {
|
||||
// apply additional indentation to lines after
|
||||
// the first if this message gets a prefix
|
||||
lineIndent += PREFIX_INDENT;
|
||||
}
|
||||
|
||||
this.writeTo.write(`${lineIndent}${line}\n`);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ToolingLogTextWriter } from './tooling_log_text_writer';
|
||||
|
||||
it('throws error if created with invalid level', () => {
|
||||
expect(
|
||||
() =>
|
||||
new ToolingLogTextWriter({
|
||||
level: 'foo',
|
||||
})
|
||||
).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
it("throws error if writeTo config is not defined or doesn't have a write method", () => {
|
||||
expect(() => {
|
||||
new ToolingLogTextWriter({
|
||||
level: 'verbose',
|
||||
writeTo: null,
|
||||
});
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
|
||||
expect(() => {
|
||||
new ToolingLogTextWriter({
|
||||
level: 'verbose',
|
||||
writeTo: 'foo',
|
||||
});
|
||||
}).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
const levels = ['silent', 'verbose', 'debug', 'info', 'warning', 'error'];
|
||||
const types = ['verbose', 'debug', 'info', 'warning', 'error', 'success'];
|
||||
for (const level of levels) {
|
||||
for (const type of types) {
|
||||
it(`level:${level}/type:${type} snapshots`, () => {
|
||||
const write = jest.fn();
|
||||
const writer = new ToolingLogTextWriter({
|
||||
level,
|
||||
writeTo: {
|
||||
write,
|
||||
},
|
||||
});
|
||||
|
||||
const written = writer.write({
|
||||
type: type,
|
||||
indent: 0,
|
||||
args: ['foo'],
|
||||
});
|
||||
|
||||
expect(written).toMatchSnapshot('is written');
|
||||
|
||||
if (written) {
|
||||
const output = write.mock.calls.reduce((acc, chunk) => `${acc}${chunk}`, '');
|
||||
expect(output).toMatchSnapshot('output');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
it('formats %s patterns and indents multi-line messages correctly', () => {
|
||||
const write = jest.fn();
|
||||
const writer = new ToolingLogTextWriter({
|
||||
level: 'debug',
|
||||
writeTo: {
|
||||
write,
|
||||
},
|
||||
});
|
||||
|
||||
writer.write({
|
||||
type: 'success',
|
||||
indent: 10,
|
||||
args: [
|
||||
'%s\n%O\n\n%d',
|
||||
'foo bar',
|
||||
{ foo: { bar: { 1: [1, 2, 3] } }, bar: { bar: { 1: [1, 2, 3] } } },
|
||||
Infinity,
|
||||
],
|
||||
});
|
||||
|
||||
const output = write.mock.calls.reduce((acc, chunk) => `${acc}${chunk}`, '');
|
||||
expect(output).toMatchSnapshot();
|
||||
});
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": [
|
||||
"index.d.ts"
|
||||
"index.d.ts",
|
||||
"src/**/*.d.ts"
|
||||
],
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
const { createToolingLog } = require('@kbn/dev-utils');
|
||||
const { ToolingLog } = require('@kbn/dev-utils');
|
||||
const execa = require('execa');
|
||||
const { Cluster } = require('../cluster');
|
||||
const { installSource, installSnapshot, installArchive } = require('../install');
|
||||
|
@ -30,9 +30,7 @@ jest.mock('../install', () => ({
|
|||
|
||||
jest.mock('execa', () => jest.fn());
|
||||
|
||||
const log = createToolingLog('verbose');
|
||||
log.onData = jest.fn();
|
||||
log.on('data', log.onData);
|
||||
const log = new ToolingLog();
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
const { createToolingLog } = require('@kbn/dev-utils');
|
||||
const { ToolingLog } = require('@kbn/dev-utils');
|
||||
|
||||
const log = createToolingLog('verbose');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: 'verbose',
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
exports.log = log;
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import dedent from 'dedent';
|
||||
import { createToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
import { ToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
|
||||
const options = {
|
||||
help: { desc: 'Display this menu and exit.' },
|
||||
|
@ -99,9 +99,10 @@ export function processOptions(userOptions, defaultConfigPaths) {
|
|||
}
|
||||
|
||||
function createLogger() {
|
||||
const log = createToolingLog(pickLevelFromFlags(userOptions));
|
||||
log.pipe(process.stdout);
|
||||
return log;
|
||||
return new ToolingLog({
|
||||
level: pickLevelFromFlags(userOptions),
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import dedent from 'dedent';
|
||||
import { createToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
import { ToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
|
||||
const options = {
|
||||
help: { desc: 'Display this menu and exit.' },
|
||||
|
@ -86,9 +86,10 @@ export function processOptions(userOptions, defaultConfigPath) {
|
|||
}
|
||||
|
||||
function createLogger() {
|
||||
const log = createToolingLog(pickLevelFromFlags(userOptions));
|
||||
log.pipe(process.stdout);
|
||||
return log;
|
||||
return new ToolingLog({
|
||||
level: pickLevelFromFlags(userOptions),
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
@ -22,6 +22,14 @@ import { inspect } from 'util';
|
|||
import chalk from 'chalk';
|
||||
import getopts from 'getopts';
|
||||
|
||||
export class CliError extends Error {
|
||||
constructor(message, exitCode = 1) {
|
||||
super(message);
|
||||
this.exitCode = exitCode;
|
||||
Error.captureStackTrace(this, CliError);
|
||||
}
|
||||
}
|
||||
|
||||
export async function runCli(getHelpText, run) {
|
||||
try {
|
||||
const userOptions = getopts(process.argv.slice(2)) || {};
|
||||
|
@ -39,20 +47,25 @@ export async function runCli(getHelpText, run) {
|
|||
console.log();
|
||||
console.log(chalk.red(error.message));
|
||||
|
||||
// first line in the stack trace is the message, skip it as we log it directly and color it red
|
||||
if (error.stack) {
|
||||
console.log(
|
||||
error.stack
|
||||
.split('\n')
|
||||
.slice(1)
|
||||
.join('\n')
|
||||
);
|
||||
} else {
|
||||
console.log(' (no stack trace)');
|
||||
// CliError is a special error class that indicates that the error is produced as a part
|
||||
// of using the CLI, and does not need a stack trace to make sense, so we skip the stack
|
||||
// trace logging if the error thrown is an instance of this class
|
||||
if (!(error instanceof CliError)) {
|
||||
// first line in the stack trace is the message, skip it as we log it directly and color it red
|
||||
if (error.stack) {
|
||||
console.log(
|
||||
error.stack
|
||||
.split('\n')
|
||||
.slice(1)
|
||||
.join('\n')
|
||||
);
|
||||
} else {
|
||||
console.log(' (no stack trace)');
|
||||
}
|
||||
}
|
||||
|
||||
console.log();
|
||||
|
||||
process.exit(1);
|
||||
process.exit(error.exitCode || 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,33 +17,26 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { KIBANA_FTR_SCRIPT, PROJECT_ROOT } from './paths';
|
||||
import { createFunctionalTestRunner } from '../../../../../src/functional_test_runner';
|
||||
import { CliError } from './run_cli';
|
||||
|
||||
export async function runFtr({
|
||||
procs,
|
||||
configPath,
|
||||
cwd = PROJECT_ROOT,
|
||||
options: { log, bail, grep, updateBaselines },
|
||||
}) {
|
||||
const args = [KIBANA_FTR_SCRIPT];
|
||||
|
||||
if (getLogFlag(log)) args.push(`--${getLogFlag(log)}`);
|
||||
if (bail) args.push('--bail');
|
||||
if (configPath) args.push('--config', configPath);
|
||||
if (grep) args.push('--grep', grep);
|
||||
if (updateBaselines) args.push('--updateBaselines');
|
||||
|
||||
await procs.run('ftr', {
|
||||
cmd: 'node',
|
||||
args,
|
||||
cwd,
|
||||
wait: true,
|
||||
export async function runFtr({ configPath, options: { log, bail, grep, updateBaselines } }) {
|
||||
const ftr = createFunctionalTestRunner({
|
||||
log,
|
||||
configFile: configPath,
|
||||
configOverrides: {
|
||||
mochaOpts: {
|
||||
bail: !!bail,
|
||||
grep,
|
||||
},
|
||||
updateBaselines,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function getLogFlag(log) {
|
||||
const level = log.getLevel();
|
||||
|
||||
if (level === 'info') return null;
|
||||
return level === 'error' ? 'quiet' : level;
|
||||
const failureCount = await ftr.run();
|
||||
if (failureCount > 0) {
|
||||
throw new CliError(
|
||||
`${failureCount} functional test ${failureCount === 1 ? 'failure' : 'failures'}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ export async function startServers(options) {
|
|||
}
|
||||
|
||||
async function silence(milliseconds, { log }) {
|
||||
await Rx.fromEvent(log, 'data')
|
||||
await log
|
||||
.getWritten$()
|
||||
.pipe(
|
||||
startWith(null),
|
||||
switchMap(() => Rx.timer(milliseconds)),
|
||||
|
@ -115,15 +116,7 @@ async function runSingleConfig(configPath, options) {
|
|||
|
||||
const es = await runElasticsearch({ config, options: opts });
|
||||
await runKibanaServer({ procs, config, options: opts });
|
||||
|
||||
// Note: When solving how to incorporate functional_test_runner
|
||||
// clean this up
|
||||
await runFtr({
|
||||
procs,
|
||||
configPath,
|
||||
cwd: process.cwd(),
|
||||
options: opts,
|
||||
});
|
||||
await runFtr({ configPath, options: opts });
|
||||
|
||||
await procs.stop('kibana');
|
||||
await es.cleanup();
|
||||
|
|
|
@ -23,7 +23,7 @@ import getopts from 'getopts';
|
|||
import dedent from 'dedent';
|
||||
import chalk from 'chalk';
|
||||
|
||||
import { createToolingLog, pickLevelFromFlags } from '../tooling_log';
|
||||
import { ToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
import { buildDistributables } from './build_distributables';
|
||||
import { isErrorLogged } from './lib';
|
||||
|
||||
|
@ -82,8 +82,10 @@ if (flags.help) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const log = createToolingLog(pickLevelFromFlags(flags));
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: pickLevelFromFlags(flags),
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
function isOsPackageDesired(name) {
|
||||
if (flags['skip-os-packages']) {
|
||||
|
|
|
@ -20,16 +20,22 @@
|
|||
import sinon from 'sinon';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
|
||||
import { createToolingLog } from '../../../tooling_log';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { exec } from '../exec';
|
||||
|
||||
describe('dev/build/lib/exec', () => {
|
||||
const sandbox = sinon.createSandbox();
|
||||
afterEach(() => sandbox.reset());
|
||||
|
||||
const log = createToolingLog('verbose');
|
||||
const onLogLine = sandbox.stub();
|
||||
log.on('data', line => onLogLine(stripAnsi(line)));
|
||||
const log = new ToolingLog({
|
||||
level: 'verbose',
|
||||
writeTo: {
|
||||
write: chunk => {
|
||||
onLogLine(stripAnsi(chunk));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it('executes a command, logs the command, and logs the output', async () => {
|
||||
await exec(log, process.execPath, ['-e', 'console.log("hi")']);
|
||||
|
@ -49,4 +55,4 @@ describe('dev/build/lib/exec', () => {
|
|||
// log output of the process
|
||||
sinon.assert.calledWithExactly(onLogLine, sinon.match(/info\s+hi/));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
import sinon from 'sinon';
|
||||
import expect from 'expect.js';
|
||||
|
||||
import { createToolingLog } from '../../../tooling_log';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { createRunner } from '../runner';
|
||||
import { isErrorLogged, markErrorLogged } from '../errors';
|
||||
|
||||
|
@ -29,9 +29,13 @@ describe('dev/build/lib/runner', () => {
|
|||
|
||||
const config = {};
|
||||
|
||||
const log = createToolingLog('verbose');
|
||||
const onLogLine = sandbox.stub();
|
||||
log.on('data', onLogLine);
|
||||
const log = new ToolingLog({
|
||||
level: 'verbose',
|
||||
writeTo: {
|
||||
write: onLogLine
|
||||
}
|
||||
});
|
||||
|
||||
const buildMatcher = sinon.match({
|
||||
isOss: sinon.match.func,
|
||||
|
|
|
@ -26,7 +26,7 @@ import sinon from 'sinon';
|
|||
import expect from 'expect.js';
|
||||
import Wreck from 'wreck';
|
||||
|
||||
import { createToolingLog } from '../../../../tooling_log';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { download } from '../download';
|
||||
|
||||
const TMP_DESTINATION = resolve(__dirname, '__tmp__');
|
||||
|
@ -41,9 +41,13 @@ describe('src/dev/build/tasks/nodejs/download', () => {
|
|||
const sandbox = sinon.createSandbox();
|
||||
afterEach(() => sandbox.reset());
|
||||
|
||||
const log = createToolingLog('verbose');
|
||||
const onLogLine = sandbox.stub();
|
||||
log.on('data', onLogLine);
|
||||
const log = new ToolingLog({
|
||||
level: 'verbose',
|
||||
writeTo: {
|
||||
write: onLogLine
|
||||
}
|
||||
});
|
||||
|
||||
const FOO_SHA256 = '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae';
|
||||
const createSendHandler = (send) => (req, res) => {
|
||||
|
|
|
@ -22,7 +22,7 @@ import { resolve } from 'path';
|
|||
|
||||
import getopts from 'getopts';
|
||||
import dedent from 'dedent';
|
||||
import { createToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
import { ToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
|
||||
import { REPO_ROOT } from '../constants';
|
||||
import { generateNoticeFromSource } from './generate_notice_from_source';
|
||||
|
@ -40,8 +40,10 @@ const opts = getopts(process.argv.slice(2), {
|
|||
}
|
||||
});
|
||||
|
||||
const log = createToolingLog(pickLevelFromFlags(opts));
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: pickLevelFromFlags(opts),
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
if (unknownFlags.length) {
|
||||
log.error(`Unknown flags ${unknownFlags.map(f => `"${f}"`).join(',')}`);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { createToolingLog, pickLevelFromFlags } from '../tooling_log';
|
||||
import { ToolingLog, pickLevelFromFlags } from '@kbn/dev-utils';
|
||||
import { isFailError } from './fail';
|
||||
import { getFlags, getHelp } from './flags';
|
||||
|
||||
|
@ -29,8 +29,10 @@ export async function run(body) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const log = createToolingLog(pickLevelFromFlags(flags));
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: pickLevelFromFlags(flags),
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
try {
|
||||
await body({ log, flags });
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { createToolingLog } from '@kbn/dev-utils';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import getopts from 'getopts';
|
||||
|
||||
import { execInProjects, filterProjectsByFlag, Project } from '../typescript';
|
||||
|
@ -27,8 +27,10 @@ export function runTslintCliOnTsConfigPaths(tsConfigPaths: string[]) {
|
|||
}
|
||||
|
||||
export function runTslintCli(projects?: Project[]) {
|
||||
const log = createToolingLog('info');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: 'info',
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
const opts = getopts(process.argv.slice(2));
|
||||
projects = projects || filterProjectsByFlag(opts.project);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { createToolingLog } from '@kbn/dev-utils';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import chalk from 'chalk';
|
||||
import dedent from 'dedent';
|
||||
import getopts from 'getopts';
|
||||
|
@ -38,8 +38,10 @@ export function runTypeCheckCli() {
|
|||
},
|
||||
});
|
||||
|
||||
const log = createToolingLog('info');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: 'info',
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
if (extraFlags.length) {
|
||||
for (const flag of extraFlags) {
|
||||
|
|
|
@ -31,7 +31,7 @@ import { Command } from 'commander';
|
|||
import elasticsearch from 'elasticsearch';
|
||||
|
||||
import { EsArchiver } from './es_archiver';
|
||||
import { createToolingLog } from '../dev';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { readConfigFile } from '../functional_test_runner';
|
||||
|
||||
const cmd = new Command('node scripts/es_archiver');
|
||||
|
@ -74,8 +74,10 @@ if (missingCommand) {
|
|||
|
||||
async function execute(operation, ...args) {
|
||||
try {
|
||||
const log = createToolingLog(cmd.verbose ? 'debug' : 'info');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: cmd.verbose ? 'debug' : 'info',
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
if (cmd.config) {
|
||||
// load default values from the specified config file
|
||||
|
|
|
@ -22,18 +22,17 @@ import { uniq } from 'lodash';
|
|||
import sinon from 'sinon';
|
||||
|
||||
import { createStats } from '../';
|
||||
import { createToolingLog } from '../../../dev';
|
||||
import {
|
||||
createConcatStream,
|
||||
createPromiseFromStreams
|
||||
} from '../../../utils';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
|
||||
function drain(log) {
|
||||
log.end();
|
||||
return createPromiseFromStreams([
|
||||
log,
|
||||
createConcatStream('')
|
||||
]);
|
||||
function createBufferedLog() {
|
||||
const log = new ToolingLog({
|
||||
level: 'debug',
|
||||
writeTo: {
|
||||
write: (chunk) => log.buffer += chunk
|
||||
}
|
||||
});
|
||||
log.buffer = '';
|
||||
return log;
|
||||
}
|
||||
|
||||
function assertDeepClones(a, b) {
|
||||
|
@ -66,110 +65,106 @@ function assertDeepClones(a, b) {
|
|||
describe('esArchiver: Stats', () => {
|
||||
describe('#skippedIndex(index)', () => {
|
||||
it('marks the index as skipped', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.skippedIndex('index-name');
|
||||
const indexStats = stats.toJSON()['index-name'];
|
||||
expect(indexStats).to.have.property('skipped', true);
|
||||
});
|
||||
|
||||
it('logs that the index was skipped', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.skippedIndex('index-name');
|
||||
expect(await drain(log)).to.contain('Skipped');
|
||||
expect(log.buffer).to.contain('Skipped');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#deletedIndex(index)', () => {
|
||||
it('marks the index as deleted', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.deletedIndex('index-name');
|
||||
const indexStats = stats.toJSON()['index-name'];
|
||||
expect(indexStats).to.have.property('deleted', true);
|
||||
});
|
||||
it('logs that the index was deleted', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.deletedIndex('index-name');
|
||||
expect(await drain(log)).to.contain('Deleted');
|
||||
expect(log.buffer).to.contain('Deleted');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#createdIndex(index, [metadata])', () => {
|
||||
it('marks the index as created', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.createdIndex('index-name');
|
||||
const indexStats = stats.toJSON()['index-name'];
|
||||
expect(indexStats).to.have.property('created', true);
|
||||
});
|
||||
it('logs that the index was created', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.createdIndex('index-name');
|
||||
expect(await drain(log)).to.contain('Created');
|
||||
expect(log.buffer).to.contain('Created');
|
||||
});
|
||||
describe('with metadata', () => {
|
||||
it('debug-logs each key from the metadata', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.createdIndex('index-name', {
|
||||
foo: 'bar'
|
||||
});
|
||||
const output = await drain(log);
|
||||
expect(output).to.contain('debg');
|
||||
expect(output).to.contain('foo "bar"');
|
||||
expect(log.buffer).to.contain('debg');
|
||||
expect(log.buffer).to.contain('foo "bar"');
|
||||
});
|
||||
});
|
||||
describe('without metadata', () => {
|
||||
it('no debug logging', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.createdIndex('index-name');
|
||||
const output = await drain(log);
|
||||
expect(output).to.not.contain('debg');
|
||||
expect(log.buffer).to.not.contain('debg');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#archivedIndex(index, [metadata])', () => {
|
||||
it('marks the index as archived', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.archivedIndex('index-name');
|
||||
const indexStats = stats.toJSON()['index-name'];
|
||||
expect(indexStats).to.have.property('archived', true);
|
||||
});
|
||||
it('logs that the index was archived', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.archivedIndex('index-name');
|
||||
expect(await drain(log)).to.contain('Archived');
|
||||
expect(log.buffer).to.contain('Archived');
|
||||
});
|
||||
describe('with metadata', () => {
|
||||
it('debug-logs each key from the metadata', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.archivedIndex('index-name', {
|
||||
foo: 'bar'
|
||||
});
|
||||
const output = await drain(log);
|
||||
expect(output).to.contain('debg');
|
||||
expect(output).to.contain('foo "bar"');
|
||||
expect(log.buffer).to.contain('debg');
|
||||
expect(log.buffer).to.contain('foo "bar"');
|
||||
});
|
||||
});
|
||||
describe('without metadata', () => {
|
||||
it('no debug logging', async () => {
|
||||
const log = createToolingLog('debug');
|
||||
const log = createBufferedLog();
|
||||
const stats = createStats('name', log);
|
||||
stats.archivedIndex('index-name');
|
||||
const output = await drain(log);
|
||||
expect(output).to.not.contain('debg');
|
||||
expect(log.buffer).to.not.contain('debg');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#indexedDoc(index)', () => {
|
||||
it('increases the docs.indexed count for the index', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.indexedDoc('index-name');
|
||||
expect(stats.toJSON()['index-name'].docs.indexed).to.be(1);
|
||||
stats.indexedDoc('index-name');
|
||||
|
@ -180,7 +175,7 @@ describe('esArchiver: Stats', () => {
|
|||
|
||||
describe('#archivedDoc(index)', () => {
|
||||
it('increases the docs.archived count for the index', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.archivedDoc('index-name');
|
||||
expect(stats.toJSON()['index-name'].docs.archived).to.be(1);
|
||||
stats.archivedDoc('index-name');
|
||||
|
@ -191,13 +186,13 @@ describe('esArchiver: Stats', () => {
|
|||
|
||||
describe('#toJSON()', () => {
|
||||
it('returns the stats for all indexes', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.archivedIndex('index1');
|
||||
stats.archivedIndex('index2');
|
||||
expect(Object.keys(stats.toJSON())).to.eql(['index1', 'index2']);
|
||||
});
|
||||
it('returns a deep clone of the stats', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.archivedIndex('index1');
|
||||
stats.archivedIndex('index2');
|
||||
stats.deletedIndex('index3');
|
||||
|
@ -208,7 +203,7 @@ describe('esArchiver: Stats', () => {
|
|||
|
||||
describe('#forEachIndex(fn)', () => {
|
||||
it('iterates a clone of the index stats', () => {
|
||||
const stats = createStats('name', createToolingLog());
|
||||
const stats = createStats('name', new ToolingLog());
|
||||
stats.archivedIndex('index1');
|
||||
stats.archivedIndex('index2');
|
||||
stats.deletedIndex('index3');
|
||||
|
|
|
@ -21,7 +21,7 @@ import { resolve } from 'path';
|
|||
|
||||
import { Command } from 'commander';
|
||||
|
||||
import { createToolingLog } from '../dev';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { createFunctionalTestRunner } from './functional_test_runner';
|
||||
|
||||
const cmd = new Command('node scripts/functional_test_runner');
|
||||
|
@ -46,8 +46,10 @@ if (cmd.quiet) logLevel = 'error';
|
|||
if (cmd.debug) logLevel = 'debug';
|
||||
if (cmd.verbose) logLevel = 'verbose';
|
||||
|
||||
const log = createToolingLog(logLevel);
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: logLevel,
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
const functionalTestRunner = createFunctionalTestRunner({
|
||||
log,
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
import expect from 'expect.js';
|
||||
|
||||
import { createToolingLog } from '../../../../dev';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { readConfigFile } from '../read_config_file';
|
||||
import { Config } from '../config';
|
||||
|
||||
const log = createToolingLog().resume();
|
||||
const log = new ToolingLog();
|
||||
|
||||
describe('readConfigFile()', () => {
|
||||
it('reads config from a file, returns an instance of Config class', async () => {
|
||||
|
|
|
@ -123,25 +123,19 @@ export function MochaReporterProvider({ getService }) {
|
|||
console.log = realLog;
|
||||
}
|
||||
|
||||
log.indent(-2);
|
||||
log.write(
|
||||
`- ${symbols.err} ` +
|
||||
colors.fail(`fail: "${test.fullTitle()}"`) +
|
||||
'\n' +
|
||||
output
|
||||
.split('\n')
|
||||
.slice(2) // drop the first two lines, (empty + test title)
|
||||
.map(line => {
|
||||
// move leading colors behind leading spaces
|
||||
return line.replace(/^((?:\[.+m)+)(\s+)/, '$2$1');
|
||||
})
|
||||
.map(line => {
|
||||
// shrink mocha's indentation
|
||||
return line.replace(/^\s{5,5}/, ' ');
|
||||
})
|
||||
// drop the first two lines, (empty + test title)
|
||||
.slice(2)
|
||||
// move leading colors behind leading spaces
|
||||
.map(line => line.replace(/^((?:\[.+m)+)(\s+)/, '$2$1'))
|
||||
.map(line => ` ${line}`)
|
||||
.join('\n')
|
||||
);
|
||||
log.indent(2);
|
||||
}
|
||||
|
||||
onEnd = () => {
|
||||
|
|
|
@ -22,7 +22,7 @@ import expect from 'expect.js';
|
|||
|
||||
import { createEsTestCluster } from '@kbn/test';
|
||||
import { createServerWithCorePlugins } from '../../../../test_utils/kbn_server';
|
||||
import { createToolingLog } from '../../../../dev';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { createOrUpgradeSavedConfig } from '../create_or_upgrade_saved_config';
|
||||
|
||||
describe('createOrUpgradeSavedConfig()', () => {
|
||||
|
@ -31,8 +31,10 @@ describe('createOrUpgradeSavedConfig()', () => {
|
|||
const cleanup = [];
|
||||
|
||||
before(async function () {
|
||||
const log = createToolingLog('debug');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: 'debug',
|
||||
writeTo: process.stdout
|
||||
});
|
||||
log.indent(6);
|
||||
|
||||
log.info('starting elasticsearch');
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { createEsTestCluster } from '@kbn/test';
|
||||
import { createToolingLog } from '@kbn/dev-utils';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import * as kbnTestServer from '../../../../../test_utils/kbn_server';
|
||||
|
||||
let kbnServer;
|
||||
|
@ -26,8 +26,10 @@ let services;
|
|||
let es;
|
||||
|
||||
export async function startServers() {
|
||||
const log = createToolingLog('debug');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: 'debug',
|
||||
writeTo: process.stdout
|
||||
});
|
||||
log.indent(6);
|
||||
|
||||
log.info('starting elasticsearch');
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import { createFunctionalTestRunner } from '../src/functional_test_runner';
|
||||
import { createToolingLog } from '../src/dev';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
|
||||
export default function (grunt) {
|
||||
grunt.registerMultiTask('functional_test_runner', 'run tests with the functional test runner', function () {
|
||||
|
@ -28,8 +28,10 @@ export default function (grunt) {
|
|||
configOverrides
|
||||
} = this.options();
|
||||
|
||||
const log = createToolingLog(logLevel);
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: logLevel,
|
||||
writeTo: process.stdout,
|
||||
});
|
||||
|
||||
const functionalTestRunner = createFunctionalTestRunner({
|
||||
log,
|
||||
|
|
|
@ -15,7 +15,7 @@ const path = require('path');
|
|||
const del = require('del');
|
||||
const runSequence = require('run-sequence');
|
||||
const pluginHelpers = require('@kbn/plugin-helpers');
|
||||
const { createToolingLog } = require('@kbn/dev-utils');
|
||||
const { ToolingLog } = require('@kbn/dev-utils');
|
||||
|
||||
const logger = require('./gulp_helpers/logger');
|
||||
const buildVersion = require('./gulp_helpers/build_version')();
|
||||
|
@ -76,8 +76,10 @@ gulp.task('build', ['clean', 'report', 'prepare'], async () => {
|
|||
});
|
||||
|
||||
const buildRoot = path.resolve(buildTarget, 'kibana/x-pack');
|
||||
const log = createToolingLog('info');
|
||||
log.pipe(process.stdout);
|
||||
const log = new ToolingLog({
|
||||
level: 'info',
|
||||
writeTo: process.stdout
|
||||
});
|
||||
|
||||
writeFileSync(
|
||||
path.resolve(buildRoot, 'NOTICE.txt'),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue