Typescript loggers with an interface that support composition
npm install @triviality/logger* Installation
* Triviality logger
* LoggerInterface
* Example log level
* Loggers
* console logger
* process logger
* prefix logger
* log from LogLevel logger
* ts-log logger
* null logger
* collection of loggers
* triviality features
* Thanks
* Reads
!Licence   !coverage
To install the stable version:
```
yarn add @triviality/logger
This assumes you are using yarn as your package manager.
or
``
npm install @triviality/logger
Exposes TypeScript Logger interface compatible with:
- Web and node
- ts-log interface
- node-bunyan node-bunyan
- Compatible with triviality ServiceContainer. Pre-configured logger modules, ready to use in your Triviality modules.
- Add composition functionality for combing loggers
Besides the normal log functions each logger has it's log function. The log function that support logging based on LogLevel.
Can be used for easy composition.
`typescript
export enum LogLevel {
trace,
debug,
info,
warn,
error,
}
export interface LoggerInterface {
trace(message?: any, ...optionalParams: any[]): void;
debug(message?: any, ...optionalParams: any[]): void;
info(message?: any, ...optionalParams: any[]): void;
warn(message?: any, ...optionalParams: any[]): void;
error(message?: any, ...optionalParams: any[]): void;
log(level: LogLevel, message: any, ...optionalParams: any[]): void;
}
`
`typescript
import { ConsoleLogger } from '@triviality/logger';
import { LogLevel } from '@triviality/logger';
const logger = new ConsoleLogger(console);
logger.log(LogLevel.info, 'Hallo', 'World');
`
`bash`
./node_modules/.bin/ts-node example/logLevel.ts
Hallo World
`typescript
import { ConsoleLogger } from '@triviality/logger';
const logger = new ConsoleLogger(console);
logger.info('Hallo', 'World');
logger.info('Bye %s', 'World');
`
`bash`
./node_modules/.bin/ts-node example/consoleLogger.ts
Hallo World
Bye World
`typescript
import { ProcessLogger } from '@triviality/logger';
const logger = new ProcessLogger(process);
logger.info('Hallo', 'World');
`
`bash`
./node_modules/.bin/ts-node example/processLogger.ts
Hallo World
`typescript
import { ConsoleLogger } from '@triviality/logger';
import { PrefixLogger } from '@triviality/logger';
const logger = new ConsoleLogger(console);
const withPrefix = new PrefixLogger(logger, 'Hallo: ');
withPrefix.info('World');
`
`bash`
./node_modules/.bin/ts-node example/prefixLogger.ts
Hallo: World
`typescript
import { ConsoleLogger } from '@triviality/logger';
import { FromLogLevelLogger } from '@triviality/logger';
import { LogLevel } from '@triviality/logger';
const logger = new ConsoleLogger(console);
const witPrefix = new FromLogLevelLogger(logger, LogLevel.info);
witPrefix.trace('This will be ignored');
witPrefix.info('Hallo!');
`
`bash`
./node_modules/.bin/ts-node example/fromLogLevelLogger.ts
Hallo!
With this you can also wrap node-bunyan
`typescript
import { TsLogLogger } from '@triviality/logger';
import { Logger } from 'ts-log';
const tsLogger: Logger = console;
const logger = new TsLogLogger(tsLogger);
logger.info('Hallo', 'World');
`
`bash`
./node_modules/.bin/ts-node example/tsLogLogger.ts
Hallo World
`typescript
import { NullLogger } from '@triviality/logger';
const logger = new NullLogger();
logger.info('Hallo', 'Void');
`
Combine loggers into a single one.
`typescript
import { CollectionLogger } from '@triviality/logger';
import { ConsoleLogger } from '@triviality/logger';
import { PrefixLogger } from '@triviality/logger';
const consoleLogger = new ConsoleLogger(console);
const logger = new CollectionLogger([
new PrefixLogger(consoleLogger, 'Hallo '),
new PrefixLogger(consoleLogger, 'Bye '),
]);
logger.info('World');
`
`bash`
./node_modules/.bin/ts-node example/collectionLogger.ts
Hallo World
Bye World
You can extends one of the abstract logger, so you only need to implement some of the log function.
`typescript
import { LoggerInterface, LogLevel } from './LoggerInterface';
export abstract class AbstractLogLevelLogger implements LoggerInterface {
public trace(message?: any, ...optionalParams: any[]): void {
this.log(LogLevel.trace, message, ...optionalParams);
}
public debug(message?: any, ...optionalParams: any[]): void {
this.log(LogLevel.debug, message, ...optionalParams);
}
public info(message?: any, ...optionalParams: any[]): void {
this.log(LogLevel.info, message, ...optionalParams);
}
public warn(message?: any, ...optionalParams: any[]): void {
this.log(LogLevel.warn, message, ...optionalParams);
}
public error(message?: any, ...optionalParams: any[]): void {
this.log(LogLevel.error, message, ...optionalParams);
}
public abstract log(type: LogLevel, message?: any, ...optionalParams: any[]): void;
}
`
`typescript
import { LoggerInterface, LogLevel } from './LoggerInterface';
export abstract class AbstractFunctionLogger implements LoggerInterface {
public abstract trace(message?: any, ...optionalParams: any[]): void;
public abstract debug(message?: any, ...optionalParams: any[]): void;
public abstract info(message?: any, ...optionalParams: any[]): void;
public abstract warn(message?: any, ...optionalParams: any[]): void;
public abstract error(message?: any, ...optionalParams: any[]): void;
public log(level: LogLevel, message?: any, ...optionalParams: any[]): void {
switch (level) {
case LogLevel.trace:
this.trace(message, ...optionalParams);
break;
case LogLevel.debug:
this.debug(message, ...optionalParams);
break;
case LogLevel.info:
this.info(message, ...optionalParams);
break;
case LogLevel.warn:
this.warn(message, ...optionalParams);
break;
case LogLevel.error:
this.error(message, ...optionalParams);
break;
default:
throw new Error(Log level "${level}" not supported);
}
}
}
`
Logger with jest spies for each particular log function.
`typescript
import { LoggerInterface } from './LoggerInterface';
import { AbstractFunctionLogger } from './AbstractFunctionLogger';
export class JestTestLogger extends AbstractFunctionLogger implements LoggerInterface {
public trace = jest.fn();
public info = jest.fn();
public warn = jest.fn();
public debug = jest.fn();
public error = jest.fn();
public mockReset() {
this.trace.mockReset();
this.info.mockReset();
this.warn.mockReset();
this.debug.mockReset();
this.error.mockReset();
}
}
`
Logger reference module, so you can reference your module to a non-concrete implementation.
`typescript
import { Feature } from '@triviality/core';
import { LoggerInterface } from '../LoggerInterface';
abstract class LoggerFeature implements Feature {
public abstract logger(): LoggerInterface;
}
export { LoggerFeature };
`
For example you reference the logger module like:
`typescript
import { Container, Feature } from '@triviality/core';
import { LoggerFeature } from '@triviality/logger';
import { HalloService } from './HalloService';
export class MyFeature implements Feature {
constructor(private container: Container
}
public halloService() {
return new HalloService(this.container.logger());
}
}
`
And build the container like:
`typescript
import { ContainerFactory } from '@triviality/core';
import { DefaultLoggerFeature } from '@triviality/logger';
import { MyFeature } from './Feature/MyFeature';
ContainerFactory
.create()
.add(DefaultLoggerFeature)
.add(MyFeature)
.build()
.then((container) => {
container.halloService().printHallo('Jane');
});
`
`bash``
./node_modules/.bin/ts-node example/defaultLoggerFeature.ts
03/11/2019 9:47:48 AM:Hallo Jane
Special thanks to:
* Eric Pinxteren