mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Make LazyLoggerFactory buffer messages.
This commit is contained in:
committed by
Joachim Van Herwegen
parent
2c6167e0cb
commit
238570b3d2
@@ -1,53 +0,0 @@
|
||||
import { LazyLogger } from '../../../src/logging/LazyLogger';
|
||||
import { LazyLoggerFactory } from '../../../src/logging/LazyLoggerFactory';
|
||||
|
||||
describe('LazyLogger', (): void => {
|
||||
let lazyLoggerFactory: LazyLoggerFactory;
|
||||
let logger: LazyLogger;
|
||||
beforeEach(async(): Promise<void> => {
|
||||
lazyLoggerFactory = LazyLoggerFactory.getInstance();
|
||||
lazyLoggerFactory.resetLoggerFactory();
|
||||
logger = new LazyLogger(lazyLoggerFactory, 'MyLabel');
|
||||
});
|
||||
|
||||
it('throws when no logger factory is set in the lazy logger factory.', async(): Promise<void> => {
|
||||
expect((): any => logger.log('debug', 'my message', { abc: true }))
|
||||
.toThrow('No logger factory has been set. Can be caused by logger invocation during initialization.');
|
||||
});
|
||||
|
||||
it('creates a new logger using the factory.', async(): Promise<void> => {
|
||||
const dummyLogger: any = {
|
||||
log: jest.fn((): any => dummyLogger),
|
||||
};
|
||||
const dummyLoggerFactory: any = {
|
||||
createLogger: jest.fn((): any => dummyLogger),
|
||||
};
|
||||
lazyLoggerFactory.loggerFactory = dummyLoggerFactory;
|
||||
|
||||
expect(logger.log('debug', 'my message')).toBe(dummyLogger);
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledTimes(1);
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledWith('MyLabel');
|
||||
expect(dummyLogger.log).toHaveBeenCalledTimes(1);
|
||||
expect(dummyLogger.log).toHaveBeenCalledWith('debug', 'my message');
|
||||
});
|
||||
|
||||
it('reuses the logger for repeated calls.', async(): Promise<void> => {
|
||||
const dummyLogger: any = {
|
||||
log: jest.fn((): any => dummyLogger),
|
||||
};
|
||||
const dummyLoggerFactory: any = {
|
||||
createLogger: jest.fn((): any => dummyLogger),
|
||||
};
|
||||
lazyLoggerFactory.loggerFactory = dummyLoggerFactory;
|
||||
|
||||
expect(logger.log('debug', 'my message 1')).toBe(dummyLogger);
|
||||
expect(logger.log('debug', 'my message 2')).toBe(dummyLogger);
|
||||
expect(logger.log('debug', 'my message 3')).toBe(dummyLogger);
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledTimes(1);
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledWith('MyLabel');
|
||||
expect(dummyLogger.log).toHaveBeenCalledTimes(3);
|
||||
expect(dummyLogger.log).toHaveBeenNthCalledWith(1, 'debug', 'my message 1');
|
||||
expect(dummyLogger.log).toHaveBeenNthCalledWith(2, 'debug', 'my message 2');
|
||||
expect(dummyLogger.log).toHaveBeenNthCalledWith(3, 'debug', 'my message 3');
|
||||
});
|
||||
});
|
||||
@@ -1,65 +1,89 @@
|
||||
import { LazyLogger } from '../../../src/logging/LazyLogger';
|
||||
import { LazyLoggerFactory } from '../../../src/logging/LazyLoggerFactory';
|
||||
import type { Logger } from '../../../src/logging/Logger';
|
||||
import type { LoggerFactory } from '../../../src/logging/LoggerFactory';
|
||||
|
||||
describe('LazyLoggerFactory', (): void => {
|
||||
let dummyLogger: any;
|
||||
let dummyLoggerFactory: any;
|
||||
let lazyLoggerFactory: LazyLoggerFactory;
|
||||
let dummyLoggerFactory: jest.Mocked<LoggerFactory>;
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
LazyLoggerFactory.getInstance().resetLoggerFactory();
|
||||
dummyLogger = {
|
||||
log: jest.fn((): any => dummyLogger),
|
||||
};
|
||||
lazyLoggerFactory = new LazyLoggerFactory();
|
||||
dummyLoggerFactory = {
|
||||
createLogger: jest.fn((): any => dummyLogger),
|
||||
};
|
||||
createLogger: jest.fn((): jest.Mocked<Logger> => ({
|
||||
log: jest.fn((): any => null),
|
||||
}) as any),
|
||||
} as any;
|
||||
});
|
||||
|
||||
it('is a singleton.', async(): Promise<void> => {
|
||||
expect(LazyLoggerFactory.getInstance()).toBeInstanceOf(LazyLoggerFactory);
|
||||
it('does not allow reading the internal factory before it is set.', (): void => {
|
||||
expect((): void => {
|
||||
expect(lazyLoggerFactory.loggerFactory).toBeNull();
|
||||
}).toThrow('Logger factory not yet set.');
|
||||
});
|
||||
|
||||
it('allows LazyLoggers to be created before an inner factory was set.', async(): Promise<void> => {
|
||||
const logger = LazyLoggerFactory.getInstance().createLogger('MyLabel');
|
||||
expect(logger).toBeInstanceOf(LazyLogger);
|
||||
it('allows setting the internal factory.', (): void => {
|
||||
lazyLoggerFactory.loggerFactory = dummyLoggerFactory;
|
||||
expect(lazyLoggerFactory.loggerFactory).toBe(dummyLoggerFactory);
|
||||
});
|
||||
|
||||
it('allows LazyLoggers to be created after an inner factory was set.', async(): Promise<void> => {
|
||||
LazyLoggerFactory.getInstance().loggerFactory = dummyLoggerFactory;
|
||||
const logger = LazyLoggerFactory.getInstance().createLogger('MyLabel');
|
||||
expect(logger).toBeInstanceOf(LazyLogger);
|
||||
it('creates loggers with the right labels.', (): void => {
|
||||
lazyLoggerFactory.createLogger('LoggerA');
|
||||
lazyLoggerFactory.createLogger('LoggerB');
|
||||
|
||||
lazyLoggerFactory.loggerFactory = dummyLoggerFactory;
|
||||
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledTimes(2);
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenNthCalledWith(1, 'LoggerA');
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenNthCalledWith(2, 'LoggerB');
|
||||
|
||||
lazyLoggerFactory.createLogger('LoggerC');
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledTimes(3);
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenNthCalledWith(3, 'LoggerC');
|
||||
});
|
||||
|
||||
it('throws when retrieving the inner factory if none has been set.', async(): Promise<void> => {
|
||||
expect((): any => LazyLoggerFactory.getInstance().loggerFactory)
|
||||
.toThrow('No logger factory has been set. Can be caused by logger invocation during initialization.');
|
||||
it('emits logged messages after a logger is set.', (): void => {
|
||||
const loggerA = lazyLoggerFactory.createLogger('LoggerA');
|
||||
const loggerB = lazyLoggerFactory.createLogger('LoggerB');
|
||||
loggerA.warn('message1');
|
||||
loggerB.warn('message2');
|
||||
loggerB.error('message3');
|
||||
loggerA.error('message4');
|
||||
|
||||
lazyLoggerFactory.loggerFactory = dummyLoggerFactory;
|
||||
|
||||
const wrappedA = dummyLoggerFactory.createLogger.mock.results[0].value as jest.Mocked<Logger>;
|
||||
expect(wrappedA.log).toHaveBeenCalledTimes(2);
|
||||
expect(wrappedA.log).toHaveBeenNthCalledWith(1, 'warn', 'message1');
|
||||
expect(wrappedA.log).toHaveBeenNthCalledWith(2, 'error', 'message4');
|
||||
|
||||
const wrappedB = dummyLoggerFactory.createLogger.mock.results[1].value as jest.Mocked<Logger>;
|
||||
expect(wrappedB.log).toHaveBeenCalledTimes(2);
|
||||
expect(wrappedB.log).toHaveBeenNthCalledWith(1, 'warn', 'message2');
|
||||
expect(wrappedB.log).toHaveBeenNthCalledWith(2, 'error', 'message3');
|
||||
});
|
||||
|
||||
it('Returns the inner factory if one has been set.', async(): Promise<void> => {
|
||||
LazyLoggerFactory.getInstance().loggerFactory = dummyLoggerFactory;
|
||||
expect(LazyLoggerFactory.getInstance().loggerFactory).toBe(dummyLoggerFactory);
|
||||
});
|
||||
it('does not store more messages than the buffer limit.', (): void => {
|
||||
lazyLoggerFactory = new LazyLoggerFactory({ bufferSize: 100 });
|
||||
const loggerA = lazyLoggerFactory.createLogger('LoggerA');
|
||||
const loggerB = lazyLoggerFactory.createLogger('LoggerB');
|
||||
|
||||
it('allows LazyLoggers to be invoked if a factory has been set beforehand.', async(): Promise<void> => {
|
||||
LazyLoggerFactory.getInstance().loggerFactory = dummyLoggerFactory;
|
||||
const logger = LazyLoggerFactory.getInstance().createLogger('MyLabel');
|
||||
logger.log('debug', 'my message', { abc: true });
|
||||
for (let i = 0; i < 50; i++) {
|
||||
loggerA.info('info');
|
||||
}
|
||||
for (let i = 0; i < 50; i++) {
|
||||
loggerB.info('info');
|
||||
}
|
||||
|
||||
expect(dummyLogger.log).toHaveBeenCalledTimes(1);
|
||||
expect(dummyLogger.log).toHaveBeenCalledWith('debug', 'my message', { abc: true });
|
||||
});
|
||||
lazyLoggerFactory.loggerFactory = dummyLoggerFactory;
|
||||
|
||||
it('allows LazyLoggers to be invoked if a factory has been after lazy logger creation.', async(): Promise<void> => {
|
||||
const logger = LazyLoggerFactory.getInstance().createLogger('MyLabel');
|
||||
LazyLoggerFactory.getInstance().loggerFactory = dummyLoggerFactory;
|
||||
logger.log('debug', 'my message', { abc: true });
|
||||
expect(dummyLoggerFactory.createLogger).toHaveBeenCalledTimes(3);
|
||||
const wrappedA = dummyLoggerFactory.createLogger.mock.results[0].value as jest.Mocked<Logger>;
|
||||
const wrappedB = dummyLoggerFactory.createLogger.mock.results[1].value as jest.Mocked<Logger>;
|
||||
const warningLogger = dummyLoggerFactory.createLogger.mock.results[2].value as jest.Mocked<Logger>;
|
||||
|
||||
expect(dummyLogger.log).toHaveBeenCalledTimes(1);
|
||||
expect(dummyLogger.log).toHaveBeenCalledWith('debug', 'my message', { abc: true });
|
||||
});
|
||||
|
||||
it('errors on invoking LazyLoggers if a factory has not been set yet.', async(): Promise<void> => {
|
||||
const logger = LazyLoggerFactory.getInstance().createLogger('MyLabel');
|
||||
expect((): any => logger.log('debug', 'my message', { abc: true }))
|
||||
.toThrow('No logger factory has been set. Can be caused by logger invocation during initialization.');
|
||||
expect(wrappedA.log).toHaveBeenCalledTimes(50);
|
||||
expect(wrappedB.log).toHaveBeenCalledTimes(49);
|
||||
expect(warningLogger.log).toHaveBeenCalledTimes(1);
|
||||
expect(warningLogger.log).toHaveBeenCalledWith('warn', 'Memory-buffered logging limit of 100 reached');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
import { LazyLogger } from '../../../src/logging/LazyLogger';
|
||||
import { LazyLoggerFactory } from '../../../src/logging/LazyLoggerFactory';
|
||||
import { getLoggerFor, resetGlobalLoggerFactory, setGlobalLoggerFactory } from '../../../src/logging/LogUtil';
|
||||
import { VoidLogger } from '../../../src/logging/VoidLogger';
|
||||
import { VoidLoggerFactory } from '../../../src/logging/VoidLoggerFactory';
|
||||
import { resetInternalLoggerFactory, getLoggerFor, setGlobalLoggerFactory } from '../../../src/logging/LogUtil';
|
||||
|
||||
let currentFactory: any;
|
||||
|
||||
class Dummy {
|
||||
private readonly label = 'dummy';
|
||||
}
|
||||
|
||||
describe('LogUtil', (): void => {
|
||||
beforeEach(async(): Promise<void> => {
|
||||
resetGlobalLoggerFactory();
|
||||
beforeAll((): void => {
|
||||
resetInternalLoggerFactory();
|
||||
resetInternalLoggerFactory({
|
||||
get loggerFactory(): any {
|
||||
return currentFactory;
|
||||
},
|
||||
set loggerFactory(value: any) {
|
||||
currentFactory = value;
|
||||
},
|
||||
createLogger: jest.fn((label: string): any => ({ label })),
|
||||
} as any);
|
||||
});
|
||||
|
||||
it('allows creating a lazy logger for a string label.', async(): Promise<void> => {
|
||||
expect(getLoggerFor('MyLabel')).toBeInstanceOf(LazyLogger);
|
||||
expect((getLoggerFor('MyLabel') as any).label).toBe('MyLabel');
|
||||
expect(getLoggerFor('MyLabel')).toEqual({ label: 'MyLabel' });
|
||||
});
|
||||
|
||||
it('allows creating a lazy logger for a class instance.', async(): Promise<void> => {
|
||||
expect(getLoggerFor(new VoidLogger())).toBeInstanceOf(LazyLogger);
|
||||
expect((getLoggerFor(new VoidLogger()) as any).label).toBe('VoidLogger');
|
||||
expect(getLoggerFor(new Dummy())).toEqual({ label: 'Dummy' });
|
||||
});
|
||||
|
||||
it('reuses loggers for instances of the same class.', async(): Promise<void> => {
|
||||
expect(getLoggerFor(new Dummy())).toBe(getLoggerFor(new Dummy()));
|
||||
});
|
||||
|
||||
it('allows setting the global logger factory.', async(): Promise<void> => {
|
||||
setGlobalLoggerFactory(new VoidLoggerFactory());
|
||||
expect(LazyLoggerFactory.getInstance().loggerFactory).toBeInstanceOf(VoidLoggerFactory);
|
||||
});
|
||||
|
||||
it('allows unsetting the global logger factory.', async(): Promise<void> => {
|
||||
setGlobalLoggerFactory(new VoidLoggerFactory());
|
||||
resetGlobalLoggerFactory();
|
||||
expect((): any => LazyLoggerFactory.getInstance().loggerFactory)
|
||||
.toThrow('No logger factory has been set. Can be caused by logger invocation during initialization.');
|
||||
const factory = {} as any;
|
||||
setGlobalLoggerFactory(factory);
|
||||
expect(currentFactory).toBe(factory);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user