Logging
When working with any application, the necessity for logging is there and nothing is worse then missing or bad logging. Core provides developers with the ability to specify what should be logged and if necessary, to create their own logger for things like remote log storage.
The default logger that ships with ARK Core is an implementation of pino with support for console and file streams.
Prerequisites
Before we start, we need to establish what a few recurring variables and imports in this document refer to when they are used.
1import { app } from "@arkecosystem/core-kernel";
- The
app
import refers to the application instance which grants access to the container, configurations, system information and more.
Usage
The application logger is accessible through the log
property of the app
instance. The logger contract that is provided by ARK Core follows the log levels defined in the RFC 5424 specification .
Get an instance of the Logger
1const logger: Contracts.Kernel.Log.Logger = app.get<Contracts.Kernel.Log.Logger>(Container.Identifiers.LogService)
emergency
message
Logging an 1logger.emergency('Hello World');
alert
message
Logging an 1logger.alert('Hello World');
critical
message
Logging a 1logger.critical('Hello World');
error
message
Logging an 1logger.error('Hello World');
warning
message
Logging a 1logger.warning('Hello World');
notice
message
Logging a 1logger.notice('Hello World');
info
message
Logging an 1logger.info('Hello World');
debug
message
Logging a 1logger.debug('Hello World');
Extending
As explained in a previous article, it is possible to extend Core services due to the fact that a Manager pattern is used. Lets go over a quick example of how you could implement your own logger.
Implementing the Driver
Implementing a new driver is as simple as importing the logger contract that needs to be satisfied and implement the methods specified in it.
1import { Contracts } from "@arkecosystem/core-kernel"; 2 3export class ConsoleLogger implements Contracts.Logger { 4 protected logger: Console; 5 6 public async make(): Promise<Contracts.Logger> { 7 this.logger = console; 8 9 return this;10 }11 12 public emergency(message: any): void {13 this.logger.error(message);14 }15 16 public alert(message: any): void {17 this.logger.error(message);18 }19 20 public critical(message: any): void {21 this.logger.error(message);22 }23 24 public error(message: any): void {25 this.logger.error(message);26 }27 28 public warning(message: any): void {29 this.logger.warn(message);30 }31 32 public notice(message: any): void {33 this.logger.info(message);34 }35 36 public info(message: any): void {37 this.logger.info(message);38 }39 40 public debug(message: any): void {41 this.logger.debug(message);42 }43}
Implementing the service provider
Now that we have implemented our console driver for the log service, we can create a service provider to register it.
1import { Container, Contracts, Providers, Services } from "@arkecosystem/core-kernel"; 2 3export class ServiceProvider extends Providers.ServiceProvider { 4 public async register(): Promise<void> { 5 const logManager: Services.Log.LogManager = this.app.get<Services.Log.LogManager>( 6 Container.Identifiers.LogManager, 7 ); 8 9 await logManager.extend("console", async () =>10 this.app.resolve<Contracts.Log.Logger>(ConsoleLogger).make(this.config().all()),11 );12 13 logManager.setDefaultDriver("console");14 }15}
- We retrieve an instance of the log manager that is responsible for managing log drivers.
- We call the
extend
method with an asynchronous function which is responsible for creating the logger instance. - We call the
setDefaultDriver
method which will tell Core to useconsole
as the new default logger.
If you do not call
setDefaultDriver
you’ll need to manually retrieve the console logger instance viaapp.get<LogManager>(LogManager).driver("console")
.