A presentation on the logging library Winston for node.jSTL.
The presentation is built with Reveal.js and hosted on GitHub Pages: http://paulzerkel.github.io/pres-winston/
Edit the root index.html
file to change the presentation. All of the files for Reveal.js are in /reveal
. The master branch contains the live site.
All examples are in /examples
. Run npm install
to install Winston.
loggers.js
- examples of using the default logger and creating custom loggerslogmessages.js
- examples of logging strings, formatting, and metadatacontainers.js
- examples of using Winston's containers feature which is a good example of granular log control and color output
Notes for the presentation follows.
- Node.js logging with Winston
- 3/16/2016
- This presentation will cover what logging is, why you probably want it, and how the library Winston will make logging very easy.
- My name is Paul Zerkel and I run the tech side of the local startup Manufacturers’ Inventory. We use node.js for parts of our backend systems
- I also work as a software consultant where my focus is development and system architecture.
- A fact about the state of a program or system, such as what function is currently being executed, values passed into a function, responses from calls to external systems, number of items in a queue, time takes to perform an operation, etc
- Often the act of logging includes some form of storage, such as writing to a file, saving to a database, pushing to a specialized logging or monitoring system.
- The log message itself often contains useful metadata such as the time the log was generated or the severity of the message
- Logging in QA helps developers and testers recreate errors in applications
- Logging in production can be used for “Exception Driven Development”, performance troubleshooting, and long term event tracking
- Logging in development can help developers learn how an application works and reason through a system by watching in real time
- Console.log and console.error exist, but are pretty limited compared to other options
- The console object in node only handles two outputs - a standard out and an error out
- A console can be created that handles a user defined stream, but it’s up to the developer to manage those streams. ie is it a file? A network stream? Something else?
- There is no built in concept of logging levels; info is an alias to log and warn is an alias to error.
- Per the docs: “A multi-transport async logging library for node.js.”
- Open source / MIT licensed
- Node >= 0.10.0
- Designed to have a minimal number of dependencies but it is open for extension to customize to your specific need
- From a high level, Winston is comprised of Logs, Loggers, and Transports
- A Log is the message that is created plus some optional metadata
- A Logger is the object responsible for handling a log
- A Transport is a destination for a log message - sometimes other logging frameworks call these appenders
- Winston uses these three concepts to separate the contents of a log, from the action of saving it, from where the log goes
- Another core concept to Winston and shared with many other logging systems
- A level is a way to assign a log message a priority and also a way to further refine how log messages are processed
- When you log a message you specify a level and Transports can optionally only respond to certain levels
- Levels have a numeric value and Loggers have a level that specifies the maximum level that they will respond to
- Default: error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5
- You can create your own levels but you may want to really think twice about this. The default log levels give you a fair bit of flexibility. The more levels you have the more you have to consider which one to actually use.
- It gives you the ability to programmatically control when a log is actually saved and how it is actually saved
- Both the Logger object and the available Transports will only act on logs that match or are more important than their current level
- Examples would be:
- Only save certain messages in the DEV and TEST environments
- Send all errors to a central database or monitoring system
- Display logs on the console and save them to a file
- Loggers are the object that is used to actually log a message
- Winston provides a default logger and also allows you to build a custom logger
- The default logger has a level of “Info” and only a Console transport
- Custom loggers let you specify the level and transports
- The logger lets you specify the level but also allows you to call a method version
- Containers let you create and recall loggers
- It’s totally fair to have many loggers in your application
- Configuring your logger based on the environment is a great idea
- One possibility is to use node_env or other environmental variables
- Log messages are strings
- Can be passed in with a util.format style
- Great use for ES6 template literals
- Messages can also contain metadata
- Any object or a literal you create
- How metadata is handled is dependent on the transport
- The Transport documentation will cover how metadata is saved
- Ex: console and file run util.inspect on the object - though docs seem a little incorrect here. Looks like it defaults to the internal serializer.
- No need to include the time with metadata, Winston will handle that for you
- The destination for a log message
- The mechanism that consumes a log message
- Loggers can have one or more transports
- Transports can also have their own Level
- A Transport’s level is the maximum it will respond to so it can filter out messages that the parent logger may otherwise pass on
- This is optional and will just follow the logger if it is not set
- You can add in new transports to Winston
- Core, More, and 3rd Party
- Build your own too
- The transports that Winston ships with and are built into the lib
- They are built by and supported by the Winston team
- Based on IO that is provided by Node.js
- Console
- Similar to console.log and writes to stdout and stderr
- File
- Persists logs to disks with lots of nice options
- HTTP
- Generic way to send a log to an HTTP endpoint - winstond is an existing project for the server side of this
- Memory
- Not sure why this is not mentioned in the docs, however it just saves to two in memory arrays - one for errors and other
- Gut feeling is that this should not be used
- These used to be part of Winston but were removed in an effort to trim down dependencies
- These are supported by the Winston Team
- Covers many common centralized logging options
- CouchDB
- Redis
- Loggly (commercial logging service)
- Logz.io (commercial logging service based on ELK)
- Riak
- MongoDB
- Community contributions
- Covers many potential destinations
- Message queues
- Cloud storage services
- Databases
- Chat services
- Desktop notifications (Growl)
- Windows events
npm search winston
to see available transports
- Profiling
- If you want to profile your code, you can use the .profile method. This will start and stopped a named profiling test. When the test stops the test name and duration will be printed
- Query
- Allows you to query Winston logs by date. The transport with the log must support it.
- Stream
- Streams the contents of a log back. Once again, the transport must support it.
- Standardize when you log and how you use log levels
- This is more important when you have > 1 developer on a project.
- It’s frustrating when something goes wrong but critical information hasn’t been logged. This is almost guaranteed to happen, but a little thought up front can prevent many cases of this.
- Great idea to add an overall logging strategy to your project’s readme.
- Certainly worth pointing out how logging is being used as part of code reviews.
- How are you going to retrieve the logs?
- If your logs are stored locally you may want to consider some method of pushing some (or all) to a central location. This could be just errors.
- This becomes more important as the number of processes logging for a system grows.
- Are you already using some central log storage? If so, look for an existing Winston plugin or consider writing your own.
- Critical for Exception Driven Development
- Plan out what transports and logger / transport settings you need per environment
- You may wish to be significantly more aggressive with logging in a development or testing environment
- Think through a purge policy early
- It’s worth knowing how quickly the volume of logs grows
- It’s also worth knowing how useful logs are as time goes on
- You may need to use filters or rewriters to mask sensitive data
- Use file writer options to save space - running out of space on a production server is never a good time!
- Beware Not Invented Here syndrome
- There are valid reasons to build your own logger, but it’s easy to miss corner cases or lose flexibility that is already accounted for in libraries such as Winston