mirror of
https://gitlab.com/openstapps/openstapps.git
synced 2026-01-08 06:22:53 +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`.
|
||||
|
||||
If you want to use logger in production (`NODE_ENV=production`) and allow all transports to fail set
|
||||
`ALLOW_NO_TRANSPORT` to `true`.
|
||||
If you want to use logger in production (`NODE_ENV=production`) and allow all transports to fail set `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.
|
||||
|
||||
@@ -52,7 +51,7 @@ Environment variables are:
|
||||
|
||||
## 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.
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import {stringify} from 'flatted';
|
||||
import {isNodeEnvironment, isProductiveNodeEnvironment} from './common';
|
||||
import {isNodeEnvironment, isProductiveEnvironment, isProductiveNodeEnvironment} from './common';
|
||||
import {Transformation} from './transformation';
|
||||
import {AddLogLevel} from './transformations/add-log-level';
|
||||
import {Transport} from './transport';
|
||||
@@ -91,17 +91,24 @@ export class Logger {
|
||||
|
||||
/**
|
||||
* Apply transformations to an output
|
||||
* Will strip newlines in production environment
|
||||
*
|
||||
* @param logLevel Log level of the output
|
||||
* @param output Output to apply transformations to
|
||||
*/
|
||||
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) {
|
||||
return 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ import {LogLevel} from './logger';
|
||||
* A transformer for log output
|
||||
*/
|
||||
export interface Transformation {
|
||||
/**
|
||||
* Indicates if this transformation is stripped in production environments
|
||||
*/
|
||||
useInProduction: boolean;
|
||||
|
||||
/**
|
||||
* Transform an output
|
||||
*
|
||||
|
||||
@@ -19,6 +19,11 @@ import {Transformation} from '../transformation';
|
||||
* Transformation that adds the log level to output
|
||||
*/
|
||||
export class AddLogLevel implements Transformation {
|
||||
/**
|
||||
* Keep this transformation in production environments
|
||||
*/
|
||||
useInProduction = true;
|
||||
|
||||
/**
|
||||
* Add log level to output
|
||||
*
|
||||
|
||||
@@ -20,6 +20,11 @@ import {Transformation} from '../transformation';
|
||||
* Transformation that colorizes log output
|
||||
*/
|
||||
export class Colorize implements Transformation {
|
||||
/**
|
||||
* Skip this transformation in production environments
|
||||
*/
|
||||
useInProduction = false;
|
||||
|
||||
/**
|
||||
* Instantiate a new colorize transformation
|
||||
*
|
||||
|
||||
@@ -14,21 +14,15 @@
|
||||
*/
|
||||
import {LogLevel} from '../logger';
|
||||
import {Transformation} from '../transformation';
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
* Transformation that adds a timestamp to output
|
||||
*/
|
||||
export class Timestamp implements Transformation {
|
||||
/**
|
||||
* Instantiate a new timestamp transformation
|
||||
*
|
||||
* @see https://momentjs.com/docs/#/displaying/format/
|
||||
* @param format Format for timestamps
|
||||
* Keep this transformation in production environments
|
||||
*/
|
||||
constructor(private readonly format = 'LLLL') {
|
||||
// noop
|
||||
}
|
||||
useInProduction = true;
|
||||
|
||||
/**
|
||||
* Add timestamp to output
|
||||
@@ -37,8 +31,6 @@ export class Timestamp implements Transformation {
|
||||
* @param output Output to add timestamp to
|
||||
*/
|
||||
transform(_logLevel: LogLevel, output: string): string {
|
||||
const now = moment();
|
||||
|
||||
return `[${now.format(this.format)}] ${output}`;
|
||||
return `[${new Date().toISOString()}] ${output}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import chaiSpies from 'chai-spies';
|
||||
import {suite, test} from '@testdeck/mocha';
|
||||
import {Logger} from '../src/logger';
|
||||
import {AddLogLevel} from '../src/transformations/add-log-level';
|
||||
import {Colorize} from '../src/transformations/colorize';
|
||||
import {DummyTransport} from './dummyTransport';
|
||||
|
||||
chai.should();
|
||||
@@ -236,6 +237,27 @@ export class LoggerSpec {
|
||||
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
|
||||
log() {
|
||||
const spy = LoggerSpec.sandbox.on(console, 'log', () => {
|
||||
|
||||
@@ -15,21 +15,14 @@
|
||||
import {expect} from 'chai';
|
||||
import {suite, test} from '@testdeck/mocha';
|
||||
import {Timestamp} from '../../src/transformations/timestamp';
|
||||
import moment = require('moment');
|
||||
|
||||
@suite()
|
||||
export class ColorizeSpec {
|
||||
export class TimeStampSpec {
|
||||
@test
|
||||
'default'() {
|
||||
|
||||
const transformation = new Timestamp();
|
||||
|
||||
expect(transformation.transform('ERROR', 'Foobar')).to.be.equal(`[${moment().format('LLLL')}] Foobar`);
|
||||
}
|
||||
|
||||
@test
|
||||
'different format'() {
|
||||
const transformation = new Timestamp('DD.MM.YYYY');
|
||||
|
||||
expect(transformation.transform('ERROR', 'Foobar')).to.be.equal(`[${moment().format('DD.MM.YYYY')}] Foobar`);
|
||||
expect(transformation.transform('ERROR', 'Foobar')).to.be.contain(`Z`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user