It can often be useful to have a centralized point where to keep an eye on the events that occur on our site. Today we’ll create a simple logging system for Angular, to manage everything in one place.
To start, we create the enum that takes care of ordering the log levels that we want.
export enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3
}
Start our logging system
Then we take care of setting up the service that will be the heart of our logging system. We will call it up throughout the application.
// logger.service.ts
import {Injectable} from '@angular/core';
import {LogLevel} from './log-level.enum';
import {environment} from '../../environments/environment';
/**
* @description Logger service for environment logging.
*/
@Injectable({
providedIn: 'root'
})
export class LoggerService {
private static level: LogLevel = LogLevel.DEBUG;
public static debug(...message: any): void {
LoggerService.writeToLog(LogLevel.DEBUG, ...message);
}
public static log(...message: any) {
LoggerService.writeToLog(LogLevel.INFO, ...message);
}
public static warn(...message: any) {
LoggerService.writeToLog(LogLevel.WARN, ...message);
}
public static error(...message: any) {
LoggerService.writeToLog(LogLevel.ERROR, ...message);
}
private static shouldLog(level: LogLevel): boolean {
return (level >= LogLevel[environment.LOG_LEVEL]);
}
private static writeToLog(level: LogLevel, ...message: any) {
if (this.shouldLog(level)) {
if (level <= LogLevel.INFO) {
console.log(LoggerService.getLogDate(), ...message);
} else if (level === LogLevel.ERROR) {
console.error(LoggerService.getLogDate(), ...message);
} else if (level === LogLevel.WARN) {
console.warn(LoggerService.getLogDate(), ...message);
}
}
}
// ...continues...
}
Also within our service we could insert a prefix for the date of the error that occurred, information that we can use to understand the density of errors over time.
// logger.service.ts
private static getLogDate(): string {
const date = new Date();
return '[' +
date.getUTCFullYear() + '/' +
(date.getUTCMonth() + 1) + '/' +
date.getUTCDate() + ' ' +
date.getUTCHours() + ':' +
date.getUTCMinutes() + ':' +
date.getUTCSeconds() + '.' +
date.getMilliseconds() + ']';
}
Everything is decided within the writeToLog()
function which is called and which takes care of writing the logs or not.
In this case, to simplify things, we will trivially write the logs via the console.log()
or console.error()
functions but nothing prevents us from creating more sophisticated versions of the software that aggregate our client logs and allow us to control them online.
For example, we could also asynchronously send the retrieved information to a service that can store it. This is to check for any malfunctions that otherwise we would not see, because they would occur in the dark on the user’s PC.
Another great aspect of this approach is security. Instead of sending error logs and information to the user’s browser we can send them to a server. Some attacker could use those console errors and that information to discover the flaws in our site. Instead, in this way we could comfortably collect those errors, grouping them and making queries to understand if everything is working as expected.
For an environment configuration we are going to add a constant inside the two specific files.
// environment.ts
export const environment = {
production: false,
LOG_LEVEL: 'DEBUG'
};
// environment.prod.ts
export const environment = {
production: true,
LOG_LEVEL: 'ERROR'
};
Conclusion
And to use the newly created service we just need to import it and use it as we would do with the classic console.log.
import { Component } from '@angular/core';
import { LoggerService as Logger } from './services/logger.service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Logger';
ngOnInit() {
Logger.debug('logger DEBUG message', { message: 'message'});
Logger.log('logger INFO message', { message: 'message'});
Logger.warn('logger WARN message', { message: 'message'});
Logger.error('logger ERROR message', { message: 'message'});
}
}
Below is an example of what we have seen:
That’s all on our simple logging system for Angular.
Try it at home!