mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-09 19:22:51 +00:00
fix: compatibility with log aggregators
This commit is contained in:
@@ -22,8 +22,7 @@ To select your desired log levels add the corresponding numbers and set the valu
|
|||||||
|
|
||||||
For example `STAPPS_LOG_LEVEL=17` is 16 + 1 and would log everything that is `OK` or `INFO`.
|
For example `STAPPS_LOG_LEVEL=17` is 16 + 1 and would log everything that is `OK` or `INFO`.
|
||||||
|
|
||||||
If you want to use logger in production (`NODE_ENV=production`) and allow all transports to fail set
|
If you want to use logger in production (`NODE_ENV=production`) and allow all transports to fail set `ALLOW_NO_TRANSPORT` to `true`.
|
||||||
`ALLOW_NO_TRANSPORT` to `true`.
|
|
||||||
|
|
||||||
Additionally setting the environment variable `STAPPS_EXIT_LEVEL` which works in the same manner as `STAPPS_LOG_LEVEL` will terminate your process after logging at the selected level(s) (usefull for integration tests). It will be ignored in afore mentioned productive environments.
|
Additionally setting the environment variable `STAPPS_EXIT_LEVEL` which works in the same manner as `STAPPS_LOG_LEVEL` will terminate your process after logging at the selected level(s) (usefull for integration tests). It will be ignored in afore mentioned productive environments.
|
||||||
|
|
||||||
@@ -52,7 +51,7 @@ Environment variables are:
|
|||||||
|
|
||||||
## Transformations
|
## Transformations
|
||||||
|
|
||||||
By default the logger will only add the log level to the message.
|
By default the logger will only add the log level to the message. It will replace newlines with spaces and might skip some of your choosen Transformers when in production (`NODE_ENV=production`) for compatibility reasons with existing log aggregators and analyzers.
|
||||||
|
|
||||||
You can change this behavior by setting other Transformers via `Logger.setTransformations`. If you do so, mind the order of the transformers.
|
You can change this behavior by setting other Transformers via `Logger.setTransformations`. If you do so, mind the order of the transformers.
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import {stringify} from 'flatted';
|
import {stringify} from 'flatted';
|
||||||
import {isNodeEnvironment, isProductiveNodeEnvironment} from './common';
|
import {isNodeEnvironment, isProductiveEnvironment, isProductiveNodeEnvironment} from './common';
|
||||||
import {Transformation} from './transformation';
|
import {Transformation} from './transformation';
|
||||||
import {AddLogLevel} from './transformations/add-log-level';
|
import {AddLogLevel} from './transformations/add-log-level';
|
||||||
import {Transport} from './transport';
|
import {Transport} from './transport';
|
||||||
@@ -91,17 +91,24 @@ export class Logger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply transformations to an output
|
* Apply transformations to an output
|
||||||
|
* Will strip newlines in production environment
|
||||||
*
|
*
|
||||||
* @param logLevel Log level of the output
|
* @param logLevel Log level of the output
|
||||||
* @param output Output to apply transformations to
|
* @param output Output to apply transformations to
|
||||||
*/
|
*/
|
||||||
private static applyTransformers(logLevel: LogLevel, output: string): string {
|
private static applyTransformers(logLevel: LogLevel, output: string): string {
|
||||||
|
if (isProductiveEnvironment()) {
|
||||||
|
output = output.replace(/[\n\r]/g, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
if (!Array.isArray(Logger.transformations) || Logger.transformations.length === 0) {
|
if (!Array.isArray(Logger.transformations) || Logger.transformations.length === 0) {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
let transformedOutput = output;
|
let transformedOutput = output;
|
||||||
for (const transformation of Logger.transformations) {
|
for (const transformation of Logger.transformations.filter(transform =>
|
||||||
|
!isProductiveEnvironment() ? true : transform.useInProduction === isProductiveEnvironment(),
|
||||||
|
)) {
|
||||||
transformedOutput = transformation.transform(logLevel, transformedOutput);
|
transformedOutput = transformation.transform(logLevel, transformedOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ import {LogLevel} from './logger';
|
|||||||
* A transformer for log output
|
* A transformer for log output
|
||||||
*/
|
*/
|
||||||
export interface Transformation {
|
export interface Transformation {
|
||||||
|
/**
|
||||||
|
* Indicates if this transformation is stripped in production environments
|
||||||
|
*/
|
||||||
|
useInProduction: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform an output
|
* Transform an output
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ import {Transformation} from '../transformation';
|
|||||||
* Transformation that adds the log level to output
|
* Transformation that adds the log level to output
|
||||||
*/
|
*/
|
||||||
export class AddLogLevel implements Transformation {
|
export class AddLogLevel implements Transformation {
|
||||||
|
/**
|
||||||
|
* Keep this transformation in production environments
|
||||||
|
*/
|
||||||
|
useInProduction = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add log level to output
|
* Add log level to output
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ import {Transformation} from '../transformation';
|
|||||||
* Transformation that colorizes log output
|
* Transformation that colorizes log output
|
||||||
*/
|
*/
|
||||||
export class Colorize implements Transformation {
|
export class Colorize implements Transformation {
|
||||||
|
/**
|
||||||
|
* Skip this transformation in production environments
|
||||||
|
*/
|
||||||
|
useInProduction = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a new colorize transformation
|
* Instantiate a new colorize transformation
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -14,21 +14,15 @@
|
|||||||
*/
|
*/
|
||||||
import {LogLevel} from '../logger';
|
import {LogLevel} from '../logger';
|
||||||
import {Transformation} from '../transformation';
|
import {Transformation} from '../transformation';
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transformation that adds a timestamp to output
|
* Transformation that adds a timestamp to output
|
||||||
*/
|
*/
|
||||||
export class Timestamp implements Transformation {
|
export class Timestamp implements Transformation {
|
||||||
/**
|
/**
|
||||||
* Instantiate a new timestamp transformation
|
* Keep this transformation in production environments
|
||||||
*
|
|
||||||
* @see https://momentjs.com/docs/#/displaying/format/
|
|
||||||
* @param format Format for timestamps
|
|
||||||
*/
|
*/
|
||||||
constructor(private readonly format = 'LLLL') {
|
useInProduction = true;
|
||||||
// noop
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add timestamp to output
|
* Add timestamp to output
|
||||||
@@ -37,8 +31,6 @@ export class Timestamp implements Transformation {
|
|||||||
* @param output Output to add timestamp to
|
* @param output Output to add timestamp to
|
||||||
*/
|
*/
|
||||||
transform(_logLevel: LogLevel, output: string): string {
|
transform(_logLevel: LogLevel, output: string): string {
|
||||||
const now = moment();
|
return `[${new Date().toISOString()}] ${output}`;
|
||||||
|
|
||||||
return `[${now.format(this.format)}] ${output}`;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import chaiSpies from 'chai-spies';
|
|||||||
import {suite, test} from '@testdeck/mocha';
|
import {suite, test} from '@testdeck/mocha';
|
||||||
import {Logger} from '../src/logger';
|
import {Logger} from '../src/logger';
|
||||||
import {AddLogLevel} from '../src/transformations/add-log-level';
|
import {AddLogLevel} from '../src/transformations/add-log-level';
|
||||||
|
import {Colorize} from '../src/transformations/colorize';
|
||||||
import {DummyTransport} from './dummyTransport';
|
import {DummyTransport} from './dummyTransport';
|
||||||
|
|
||||||
chai.should();
|
chai.should();
|
||||||
@@ -236,6 +237,27 @@ export class LoggerSpec {
|
|||||||
process.env.NODE_ENV = nodeEnv;
|
process.env.NODE_ENV = nodeEnv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test
|
||||||
|
'is compatible with log aggregation in productive environment'() {
|
||||||
|
const nodeEnv = process.env.NODE_ENV;
|
||||||
|
process.env.NODE_ENV = 'production';
|
||||||
|
process.env.ALLOW_NO_TRANSPORT = 'true';
|
||||||
|
|
||||||
|
Logger.setTransformations([new AddLogLevel(), new Colorize()]);
|
||||||
|
|
||||||
|
const spy = LoggerSpec.sandbox.on(console, 'log', () => {
|
||||||
|
// noop
|
||||||
|
});
|
||||||
|
|
||||||
|
Logger.log('Foo\nbar');
|
||||||
|
|
||||||
|
expect(spy).to.have.been.called.once;
|
||||||
|
expect(spy.__spy.calls[0][0]).to.equal('[LOG] Foo bar');
|
||||||
|
|
||||||
|
process.env.NODE_ENV = nodeEnv;
|
||||||
|
delete process.env.ALLOW_NO_TRANSPORT;
|
||||||
|
}
|
||||||
|
|
||||||
@test
|
@test
|
||||||
log() {
|
log() {
|
||||||
const spy = LoggerSpec.sandbox.on(console, 'log', () => {
|
const spy = LoggerSpec.sandbox.on(console, 'log', () => {
|
||||||
|
|||||||
@@ -15,21 +15,14 @@
|
|||||||
import {expect} from 'chai';
|
import {expect} from 'chai';
|
||||||
import {suite, test} from '@testdeck/mocha';
|
import {suite, test} from '@testdeck/mocha';
|
||||||
import {Timestamp} from '../../src/transformations/timestamp';
|
import {Timestamp} from '../../src/transformations/timestamp';
|
||||||
import moment = require('moment');
|
|
||||||
|
|
||||||
@suite()
|
@suite()
|
||||||
export class ColorizeSpec {
|
export class TimeStampSpec {
|
||||||
@test
|
@test
|
||||||
'default'() {
|
'default'() {
|
||||||
|
|
||||||
const transformation = new Timestamp();
|
const transformation = new Timestamp();
|
||||||
|
|
||||||
expect(transformation.transform('ERROR', 'Foobar')).to.be.equal(`[${moment().format('LLLL')}] Foobar`);
|
expect(transformation.transform('ERROR', 'Foobar')).to.be.contain(`Z`);
|
||||||
}
|
|
||||||
|
|
||||||
@test
|
|
||||||
'different format'() {
|
|
||||||
const transformation = new Timestamp('DD.MM.YYYY');
|
|
||||||
|
|
||||||
expect(transformation.transform('ERROR', 'Foobar')).to.be.equal(`[${moment().format('DD.MM.YYYY')}] Foobar`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user