Skip to content

Instantly share code, notes, and snippets.

@Itsdenty
Created January 22, 2024 13:49
Show Gist options
  • Save Itsdenty/047bb96f4baea2120074cba8f95288f2 to your computer and use it in GitHub Desktop.
Save Itsdenty/047bb96f4baea2120074cba8f95288f2 to your computer and use it in GitHub Desktop.
Server-side Logging in Javascript with Winston Library
Introduction
At local development, you have access to the console. This allows you to;
Recreate errors.
Peruse stack traces.
Interpret cryptic error messages.
and debug.
However, at the production stage, you don’t have access to those console messages because your apps run on users’ machines (i.e. mobile, web, desktop). In this case, having some ways to record your code’s various error messages from the client and to a server, you have access to would be beneficial. There are many tools available for such use cases, typically called logging libraries, but this article won’t cover all of them. The focus of this article is on Winston library. Ready to get started?
Table of contents.
What is Logging
Type of data to save in your log
Types of logging libraries
Why Winston is important
Other Notable libraries for logging in Node.js
Bootstrapping Winston Library
Conclusion
Prerequisites
You must have;
Node.js installed on your machine and
npm installed.
What is logging, and why is it important?
Logging is the process of keeping track of events that occur when certain app is running at production environment. When you don't have any logging records and your program crashes, you have very few chances of discovering what caused the problem.
Logging is essential in software development as it helps in;
Debugging
Profiling:
Performance
Generating statistics.
You've used a type of logging to debug your code if you've ever used a print() statement to output a variable's value while your program is executing. Understanding what is happening in your program and in what order is possible with logging libraries. The logging module in Javascript creates a simple way to keep track of the personalised messages you write. These log messages will list any variables you have provided at that time, as well as when the program execution has reached the logging function call. A missing log message, on the other hand, shows that a section of the code was skipped and never executed.
Logs provide information about who is using your program, how it is used, and how well it serves your users. This enables you to keep track of your app's performance over a longer period. This is crucial for anticipating problems before they occur.
Your app might only log issues. While this is a good start, additional visibility is crucial when operating an app in production. At the very least, you should keep track of the URL, user agent, and response time of each request, etc.
Knowing the scenarios for logs in your program and the type of data you should log is highly important.
Why Winston?
Winston is one of the most popular logging libraries for Node.js. It aims to make logging more flexible and extensible by decoupling different aspects such as log levels, formatting, and storage so that each API is independent and many combinations are supported. It also uses Node.js streams to minimise the performance impact of implementing logging in your application.
Other Notable libraries for logging in Node.js
Logging libraries vary from Language to Language. In Node.js, you can also explore the following libraries.
Pino
Pino offers very similar functionality to Winston. It boasts very little overhead and provides transport as well as log processing. It also offers a pretty-pino module for formatting logs during development using NDJSON (Newline Delimited JSON).
Bunyan
It is a simple and fast JSON logging library. It comes with a CLI tool for browsing and pretty-printing logs. It offers custom log rendering with serialises and logger specialisation with log.child. In addition, it streams for specifying log targets.
What type of data you should log?
Logs are typically used in programs for debugging and troubleshooting purposes. However, logs can be used for many different purposes, such as data mining, researching application systems, enhancing business logic, and making better judgments.
These are some potential events that our application could want to record.
Requests: This records the execution of services in our application. Services like authentication, authorisations, system access, data access, and application access.
Resources: Exhausted resources, exceeded capacities, and connectivity issues are all resource-related issues to log.
Availability: It is recommended to include a log statement to check the application runtime when the application session starts/stops. Availability logs contain faults and exceptions like the system’s availability and stability.
Threats to log include wrong API keys, unsuccessful verification such as; failed authentication, and other alerts brought on by the security elements of the program.
Threats: Invalid inputs and security issues are common threats to logging, such as invalid API keys, failed security verification, failed authentication, and other warnings triggered by the application’s security features.
Events/Changes: Button click, changing context, etc. System or application changes, data changes (creation and deletion). These are all important messages to log out in our applications.
Why logging is important?
Logging is done for the following purposes:
Troubleshooting
Information gathering
Profiling
Auditing
Generating statistics.
Logging is not limited to identifying errors in software development. It is also used in detecting security incidents, monitoring policy violations, providing information in case of problems, finding application bottlenecks, or generating usage data.
Most of the entries in this list deal directly with failure scenarios, such as uncaught exceptions, unhandled rejections, and error events. Signals received from external processes are another interesting situation. However, only one of these has to do with cleanly and intentionally exiting the process.
Getting started with Winston Library
There are many important concepts you need to know about Winston. In this section, you will be familiar with concepts like log levels, transports, and how to write your firsts log functions.
What are Log levels?
Log levels indicate the significance of a particular log message. One of the best practices for application logging is the use of the right log levels.
Winston utilises npm logging levels by default. Here, the severity of all levels is ranked from 0 to 6 in order of importance, starting with the most critical (highest to lowest).
The severity of all levels is ranked in the npm logging level from the most important (zero) to the least important (six):
0 - error: a serious problem or failure that halts current activity but leaves the application in a recoverable state with no effect on other operations. The application can continue working.
1 - warn A non-blocking warning about an unusual system exception. These logs provide context for a possible error. It logs warning signs that should be investigated.
2 - Info: This denotes major events and informative messages about the application’s current state. Useful For tracking the flow of the application.
3 - http: This logs out HTTP request-related messages. HTTP transactions range from the host, path, response, requests, etc.
4 - verbose: Records detailed messages that may contain sensitive information.
5 - debug: Developers and internal teams should be the only ones to see these log messages. They should be disabled in production environments. These logs will help us debug our code.
6 - silly: The current stack trace of the calling function should be printed out when silly messages are called. This information can be used to help developers and internal teams debug problems.
If we do not explicitly state our Winston logging level, npm levels will be used.
When we specify a logging level for our Winston logger, it will only log anything at that level or higher.
For example, looking at our logger.js file, the level there is set to debug. Hence the logger will only output debug and higher levels (info, warn and error).
Any level lower than debug would not be displayed/output when we call our logger method in app.js.
There are two ways to assign levels to log messages.
Provide the logger method with the name of the logging level as a string. logger.log("debug", "Hello, Winston!");
Call the level of the method directly. logger.debug("info","The '/' route.")
When we look at our previous output, we can see that debug level was logged twice, using these different ways.
Log messages are often persisted to some form of storage
Messages frequently include metadata
Winston is one of the best and most widely used Node.js logging options; we are using it because it is very flexible, open-source, and has a great and supportive community, with approximately 4,000,000 weekly downloads.
What is Winston Log transports?
Transport refers to the storage devices for your logs levels. In Winston, you can store your log levels in database, file, or print all logs to the console. Multiple transports can be configured at various levels instance of your Winston.
Importance of Logging
Profiling logs.
Winston assists you in measuring the time it takes for a piece of code to be successfully run.
Forms logging.
Winston offers you several log formats. For instance, the log format must be in JSON when saving it to a Mongo database. Winston finds a solution for you.
Channel logging.
A competent logger will choose the location of your log output in a different way. Winston allows you to deliver and save logs using various methods, including files, databases, emails, and consoles.
Log Levels
Winston offers Logs level priorities. They give you the opportunity to distinguish between logs that need immediate attention and those that can wait. They also give the log precedence. Consider the following code: "error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5". An error log is given precedence over a verbose log in this situation.
How to get started with Winston logging in Node.js
Getting started with Winston is easy, just start by;
Installing Winston
Install via npm
```npm install winston```
import winston
```const winston = require('winston');
```
How do I create custom logs in Winston?
```const logger = winston.createLogger({
level: 'info',
format: winston.format.json(),
transports: [new winston.transports.Console()],
});```
Logging with winston using the logger object
```logger.info('Info message');
logger.error('Error message');
logger.warn('Warning message');
```
Best practices for logging
Consider security, privacy, and compliance requirements when making configuration and endpoint decisions for the data you intend to include in streamed logs.
Also with winston log levels can be customized and formatted with timestamps added for example.
Conclusion
At the end of this tutorial, the reader will understand the essential logging concepts and how it works. A logging library such as Winston will be used to experiment with the practical aspect of logging a node server.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment