Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start consuming np logging config #56480

Merged
merged 11 commits into from
Feb 4, 2020
Prev Previous commit
Next Next commit
add integration tests
mshustov committed Jan 31, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 003cd4371e9e289c71d76a92e27155149db2f31c
220 changes: 220 additions & 0 deletions src/core/server/legacy/integration_tests/logging.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
/*
* 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 Fs from 'fs';
import Path from 'path';
import Util from 'util';
import del from 'del';

import * as kbnTestServer from '../../../../test_utils/kbn_server';
import { fromRoot } from '../../utils';
import {
getPlatformLoggingContent as _getPlatformLoggingContent,
getLegacyPlatformLoggingContent as _getLegacyPlatformLoggingContent,
} from '../../logging/integration_tests/utils';

import { LegacyLoggingConfig } from '../config/legacy_object_to_config_adapter';

const mkdir = Util.promisify(Fs.mkdir);
const truncate = Util.promisify(Fs.truncate);

const tempFolderPath = fromRoot('data/test/tmp-logging-service');
const platformDestination = Path.join(tempFolderPath, 'compatibility-np.txt');
const legacyPlatformDestination = Path.join(tempFolderPath, 'compatibility-lp.txt');

const getPlatformLoggingContent = () => _getPlatformLoggingContent(platformDestination);
const getLegacyPlatformLoggingContent = () =>
_getLegacyPlatformLoggingContent(legacyPlatformDestination);

function createRoot(legacyLoggingConfig: LegacyLoggingConfig = {}) {
return kbnTestServer.createRoot({
logging: {
// legacy platform config
silent: false,
dest: legacyPlatformDestination,
json: false,
...legacyLoggingConfig,
events: {
log: ['test-file-legacy'],
},
// platform config
appenders: {
file: {
kind: 'file',
path: platformDestination,
layout: {
kind: 'pattern',
},
},
},
loggers: [
{
context: 'test-file',
appenders: ['file'],
level: 'info',
},
],
},
});
}

describe('logging service', () => {
describe('compatibility', () => {
beforeAll(async () => {
await mkdir(tempFolderPath, { recursive: true });
});
afterAll(async () => {
await del(tempFolderPath);
});
afterEach(async () => {
await truncate(platformDestination);
await truncate(legacyPlatformDestination);
});
describe('uses configured loggers', () => {
let root: ReturnType<typeof createRoot>;
beforeAll(async () => {
root = createRoot();

await root.setup();
await root.start();
}, 30000);

afterAll(async () => {
await root.shutdown();
});

it('when context matches', async () => {
root.logger.get('test-file').info('handled by NP');

expect(await getPlatformLoggingContent()).toMatchInlineSnapshot(`
"[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] handled by NP
"
`);

expect(await getLegacyPlatformLoggingContent()).toHaveLength(0);
});

it('falls back to the root legacy logger otherwise', async () => {
root.logger.get('test-file-legacy').info('handled by LP');

expect(await getLegacyPlatformLoggingContent()).toMatchInlineSnapshot(`
" log [xx:xx:xx.xxx] [info][test-file-legacy] handled by LP
"
`);
expect(await getPlatformLoggingContent()).toHaveLength(0);
});
});

describe('logging config respects legacy logging settings', () => {
it('"silent": true', async () => {
const root = createRoot({ silent: true });

await root.setup();
await root.start();

const platformLogger = root.logger.get('test-file');
platformLogger.info('info');
platformLogger.warn('warn');
platformLogger.error('error');

const legacyPlatformLogger = root.logger.get('test-file-legacy');
legacyPlatformLogger.info('info');
legacyPlatformLogger.warn('warn');
legacyPlatformLogger.error('error');

// calls shutdown to close write stream and flush logged messages
await root.shutdown();

expect(await getPlatformLoggingContent()).toMatchInlineSnapshot(`
"[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] info
[xxxx-xx-xxTxx:xx:xx.xxxZ][WARN ][test-file] warn
[xxxx-xx-xxTxx:xx:xx.xxxZ][ERROR][test-file] error
"
`);

expect(await getLegacyPlatformLoggingContent()).toHaveLength(0);
});

it('"quiet": true', async () => {
const root = createRoot({ quiet: true });

await root.setup();
await root.start();

const platformLogger = root.logger.get('test-file');
platformLogger.info('info');
platformLogger.warn('warn');
platformLogger.error('error');

const legacyPlatformLogger = root.logger.get('test-file-legacy');
legacyPlatformLogger.info('info');
legacyPlatformLogger.warn('warn');
legacyPlatformLogger.error('error');

// calls shutdown to close write stream and flush logged messages
await root.shutdown();

expect(await getPlatformLoggingContent()).toMatchInlineSnapshot(`
"[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] info
[xxxx-xx-xxTxx:xx:xx.xxxZ][WARN ][test-file] warn
[xxxx-xx-xxTxx:xx:xx.xxxZ][ERROR][test-file] error
"
`);

expect(await getLegacyPlatformLoggingContent()).toMatchInlineSnapshot(`
" log [xx:xx:xx.xxx] [error][test-file-legacy] error
"
`);
});

it('"verbose": true', async () => {
const root = createRoot({ verbose: true });

await root.setup();
await root.start();

const platformLogger = root.logger.get('test-file');
platformLogger.info('info');
platformLogger.warn('warn');
platformLogger.error('error');

const legacyPlatformLogger = root.logger.get('test-file-legacy');
legacyPlatformLogger.info('info');
legacyPlatformLogger.warn('warn');
legacyPlatformLogger.error('error');

// calls shutdown to close write stream and flush logged messages
await root.shutdown();

expect(await getPlatformLoggingContent()).toMatchInlineSnapshot(`
"[xxxx-xx-xxTxx:xx:xx.xxxZ][INFO ][test-file] info
[xxxx-xx-xxTxx:xx:xx.xxxZ][WARN ][test-file] warn
[xxxx-xx-xxTxx:xx:xx.xxxZ][ERROR][test-file] error
"
`);

expect(await getLegacyPlatformLoggingContent()).toMatchInlineSnapshot(`
" log [xx:xx:xx.xxx] [info][test-file-legacy] info
log [xx:xx:xx.xxx] [warning][test-file-legacy] warn
log [xx:xx:xx.xxx] [error][test-file-legacy] error
"
`);
});
});
});
});
114 changes: 114 additions & 0 deletions src/core/server/logging/integration_tests/logging.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* 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 kbnTestServer from '../../../../test_utils/kbn_server';

function createRoot() {
return kbnTestServer.createRoot({
logging: {
silent: true, // set "true" in kbnTestServer
appenders: {
'test-console': {
kind: 'console',
layout: {
highlight: false,
kind: 'pattern',
pattern: '{level}|{context}|{message}',
},
},
},
loggers: [
{
context: 'parent',
appenders: ['test-console'],
level: 'warn',
},
{
context: 'parent.child',
appenders: ['test-console'],
level: 'error',
},
],
},
});
}

describe('logging service', () => {
describe('logs according to context hierarchy', () => {
let root: ReturnType<typeof createRoot>;
let mockConsoleLog: jest.SpyInstance;
beforeAll(async () => {
mockConsoleLog = jest.spyOn(global.console, 'log');
root = createRoot();

await root.setup();
}, 30000);

beforeEach(() => {
mockConsoleLog.mockClear();
});

afterAll(async () => {
mockConsoleLog.mockRestore();
await root.shutdown();
});

it('uses the most specific context', () => {
const logger = root.logger.get('parent.child');

logger.error('error from "parent.child" context');
logger.warn('warning from "parent.child" context');
logger.info('info from "parent.child" context');

expect(mockConsoleLog).toHaveBeenCalledTimes(1);
expect(mockConsoleLog).toHaveBeenCalledWith(
'ERROR|parent.child|error from "parent.child" context'
);
});

it('uses parent context', () => {
const logger = root.logger.get('parent.another-child');

logger.error('error from "parent.another-child" context');
logger.warn('warning from "parent.another-child" context');
logger.info('info from "parent.another-child" context');

expect(mockConsoleLog).toHaveBeenCalledTimes(2);
expect(mockConsoleLog).toHaveBeenNthCalledWith(
1,
'ERROR|parent.another-child|error from "parent.another-child" context'
);
expect(mockConsoleLog).toHaveBeenNthCalledWith(
2,
'WARN |parent.another-child|warning from "parent.another-child" context'
);
});

it('falls back to the root settings', () => {
const logger = root.logger.get('fallback');

logger.error('error from "fallback" context');
logger.warn('warning from fallback" context');
logger.info('info from "fallback" context');

// output muted by silent: true
expect(mockConsoleLog).toHaveBeenCalledTimes(0);
});
});
});
57 changes: 57 additions & 0 deletions src/core/server/logging/integration_tests/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 Fs from 'fs';
import Util from 'util';
const readFile = Util.promisify(Fs.readFile);

function replaceAllNumbers(input: string) {
return input.replace(/\d/g, 'x');
}

function replaceTimestamp(input: string) {
return input.replace(/\[(.*?)\]/, (full, key) => `[${replaceAllNumbers(key)}]`);
}

function stripColors(input: string) {
return input.replace(/\u001b[^m]+m/g, '');
}

export function normalizePlatformLogging(input: string) {
return replaceTimestamp(input);
}

export function normalizeLegacyPlatformLogging(input: string) {
return replaceTimestamp(stripColors(input));
}

export async function getPlatformLoggingContent(path: string) {
const fileContent = await readFile(path, 'utf-8');
return fileContent
.split('\n')
.map(s => normalizePlatformLogging(s))
.join('\n');
}

export async function getLegacyPlatformLoggingContent(path: string) {
const fileContent = await readFile(path, 'utf-8');
return fileContent
.split('\n')
.map(s => normalizeLegacyPlatformLogging(s))
.join('\n');
}