Intro to Using Javascript Proxy: Learn to Optimize a Logger
Have you ever used javascript’s Proxy class? I’m going to show you how you can use it wrap objects and optimize a mock logging library.
Table of Contents
Create a Simple Logger
Expose the Logger’s Weakness
Create The Proxy Wrapper
Use the FastLogger
Conclusion
The code is here and the video tutorial is here.
Create a Simple Logger
Create a logger resembling the popular logging library winston. Winston v2 had a performance flaw (which has since been fixed in v3) that we can resolve with a Proxy.
The key thing to note here is that the data being logged in the info and debug methods is first serialized then logged. This means that if we pepper our code base with thousands of debug statements logging large objects like requests, then we're exposing ourselves to a seriously sneaky performance impact.
Expose the Logger’s Weakness
Let’s create an index.ts to use the logger at level INFO and we’ll see that it still takes a really long time even though level DEBUG is not active.
Create The Proxy Wrapper
We can create a Proxy that will wrap the Logger and control how it logs.
The ProxyHandler is an object with a get method that will be called any time a property is accessed on the target object.
In the get method, we first check if this is a call to a log method. Then we check if the getLogLevelOfMethod() is less than our currently configured target.level. If so, instead of calling the logger’s log method, for example the debug method, we simply return a no-op method.
This ensures that we skip the Logger function to serialize the crazy large object. By default always return the original property being accessed!
Use the FastLogger
Now update index.ts to use the FastLogger.
Witness the speeeeed. Switch the level of the logger to see that debug still works and is still slow. At least now, it's only in debug.
Conclusion
What other use cases can you think of? Perhaps our next example will be using the Proxy class to switch between two completely different instances of an object in order to manage context. It's quite the advanced use case, but turned out to be a useful one for us.
At Jemini.io we love finding hacks like this that can quickly and easily unlock gains in our apps. Reach out to find out what we can do for your projects!