Logging in transpiled environments using newer JavaScript language constructs
Why use a transpiler?
One of the most important reasons that developers use transpilers, for example Babel, is so they can use new or planned features such as async/await, native promise support, rest and spread operators, or simply to have an easy way to make sure their app works with older browsers or Node.js versions. It’s not uncommon to see a business app with the requirement to support IE8+ and a long-term support version of Node.js (version 6 at the time of posting this article). If you are not tied to an older version of Node.js, async/await (one of the most popular features) has been available out of the box since Node.js v7.6.
A second common reason is to be able to fully utilise the latest tools and techniques for maintaining a code base. Tools like Browserify or Webpack allow for much more flexibility and developer-friendly features and customizations in contrast to having a bunch of files in directories and using shell scripts to prepare the code for a production release.
In the context of logging, it is interesting and very beneficial to know that transpilers usually work with your logging libraries and aggregators out of the box. However, it’s still up to you (as a responsible developer or architect) to make sure that you log the right things and create the least impact to your application. In practice, this usually means checking the generated code and testing the logging applied to your application.
Babel
Babel is one of the pioneers and the most used tool for transpilation in the JavaScript world. It is a tool for JavaScript-to-JavaScript transpilation (put simply, we can think of it as a transformation from a future version to an older one).
Imagine we need to support Node.js version 4 (not ES6 compatible) and have the ability to use ES6 features like rest/spread to perform some logging to Loggly. How would we easily achieve that?
Let’s start by using babel-cli to set up our project. First, we need to install Babel using npm:
npm install --save-dev babel-cli babel-preset-env
Next, we need to create a .babelrc file in the root of our project:
Now, let’s install some Bunyan and Loggly files and create our logging example using rest and spread syntax using ES6:
npm install --save-dev bunyan bunyan-loggly
Let’s say we have the above code in a file named index.js. Now we need to start the transpilation process and we can do it with this command:
./node_modules/.bin/babel index.js -d lib
If all went well, there should be no error, and a transpiler index.js file should be generated inside the lib directory looking like this:
It looks a bit different than our starting example but is still both readable and Node.js v4 compliant. Note that this is a simple example. More complex code with more of the latest features can look much different, so it is good to inspect the generated file in more detail and even use source-maps for more efficient debugging.
Now if we run our example using Node.js v4 from the terminal by running:
node lib/index.js
Our information should be logged to Loggly and should look like this:
Note that sometimes, depending on your target of transpilation, you will need to intervene with your build system and some other Babel plugins to make everything work as you expect. Luckily the tools are mature and there is a large, evolved ecosystem around them, so finding or developing what you need shouldn’t be a problem.
TypeScript
TypeScript, a superset of JavaScript, is becoming a very popular choice among developers, especially those doing business- and data-oriented web apps. There is a significant chance that it will become the predominant choice for development in new, non-trivial enterprise systems based on Node.js. Enterprise applications often have very strict and detailed logging requirements, which put existing logging libraries and log aggregation tool (and platform) vendors to the test.
New language constructs like async/await, destructuring or rest and spread operators often make it simpler to satisfy your logging needs with easier implementation. As you evaluate logging libraries and vendors, take time to carefully consider what you should log. (For more tips, you might want to check out Loggly’s Pragmatic Logging Handbook.)
Here is a quick example of how to use Loggly in TypeScript:
To use async/await we need to utilise promises. And since the Loggly client uses callbacks, we need to do a bit of a different setup to promisify the callback. Then we can use it with async and await keywords out of the box. We can see it in the example below:
And this logs our data to the Loggly interface as seen in the image below:
Conclusion
As we can see from the Loggly output and translated code examples, either Babel or TypeScript can help us have good, synchronous, feature-rich simple code. This, in turn, allows us to be more rigorous on the data we log and its format. I hope that my examples can help answer your questions about what to log, how much, and how to do it easily in your code.
The Loggly and SolarWinds trademarks, service marks, and logos are the exclusive property of SolarWinds Worldwide, LLC or its affiliates. All other trademarks are the property of their respective owners.
Mihovil Rister