How To Log NestJS Applications in A Distributed System - Part 1 - Winston - by Itchimonji - CP Massive Programming - Medium
How To Log NestJS Applications in A Distributed System - Part 1 - Winston - by Itchimonji - CP Massive Programming - Medium
Nowadays it is important to log your applications for better monitoring, debugging and
failure handling (for example, in a Kubernetes cluster), and to ensure centralized logging
for a better overview of a distributed system.
There are numerous applications and frameworks that make this possible. But in this series
I want to focus on NestJS, winston, and the Loki Stack combined with Grafana.
A Distributed System of Microservices
On many platforms we can see how a system of dependent microservices is developed to
satisfy the customer (e.g. Ebay TECH, Facebook). The biggest challenge is to ensure that all
microservices can reached each other and thus to provide fail-safety to keep the customer
happy. If a service is not available (e.g. network problems) or even failed, a responsible
person would have to get notified and the service would have to restart itself if necessary.
For this the applications need to be monitored. To read more about this, check out the guide
on How To Monitor a Distributed System with a NestJS Application
For me, the main advantage is that it can be easily integrated into a Kubernetes cluster via
helm.
winston is designed to be a simple and universal logging library with support for multiple
transports. A transport is essentially a storage device for your logs. Each winston logger
can have multiple transports (see: Transports) configured at different levels
(see: Logging levels). For example, one may want error logs to be stored in a persistent
remote location (like a database), but all logs output to the console or a local file.
We always prefer decoupled and isolated implementations, so in general, we can also build
a simple initialisation function initWinston(…) for the winston logger. There are log levels,
formats, default meta, and different handlers, e.g. for exception or rejections, with storage
paths defined.
As a parameter, we enter a service/api name, which will be visible in the logs. This can then
be used as a Singleton in our application. A Singleton is more of an anti-pattern in
today’s generation. We could also build a NestJS service by creating the instance of
the winston logger in the constructor and making the log function available via
Dependency Injection in each individual NestJS module.
Logs by winston
We can create the instance of the logger at the top in the bootstrap function:
In the end, we can log various things everywhere in our application. And the logs are also
saved as file in the environment.
In the next part I will show you how to create a local Kubernetes cluster with kind, and how
to deploy the Loki Stack via Helm charts in it. Also, I show the use case for
a Sidecar container to collect custom logs.
Github Project
You can find the practical part of this series on GitHub.