fullstack-build / tslog

📝 tslog - Universal Logger for TypeScript and JavaScript
https://tslog.js.org
MIT License
1.31k stars 62 forks source link

How does this compare to pino, winston and co? #16

Closed geekflyer closed 4 years ago

geekflyer commented 4 years ago

Hi there,

I came across tslog in search of a good logging library and it looks promising! I'm currently mostly using pino but having some issues with it's API and other things.

I was wondering if you could give a quick summary on how this logging library compares to X, what you did differently, why and what's the overall philosophy of it? I'm sort of tasked with defining some best practices wrt to logging and observability at my company.

When I say X, I mostly mean:

Some features that I'm looking for usually:

Appreciate your thoughts!

terehov commented 4 years ago

Hi Christian,

I appreciate your request for such a comparison. Even though I understand your wish, I have to admit that I am not a fan of such an overview. On the one hand, they usually seem biased, so that the selected features are by pure accident exactly the ones that are supported by your own package (all of them are always checked). On the other hand, I don't think it's appropriate, especially in the open-source community to judge someone else's work. Every author of every open-source library invests his (free) time and therefore every library has a right to exist, as long as it helps others. I don't feel being in the position to judge somebody else's work.

I think my job as the author of this library is to maintain it and list all its features in a compact way and leave you to compare and decide which one to use.

I hope you understand my thoughts.

terehov commented 4 years ago

One question though: What exactly is your use-case of having a child logger? tslog supports multiple loggers with different configurations and it's rather easy to achieve having a minLevel for all of them by simply putting this setting into a variable or an ENV. Is there something I'm missing? Thanks!

geekflyer commented 4 years ago

Hi @terehov,

I respect your thought on this, altho personally I have a bit of a different opinion. I think it's quite possible to give an honest comparison to other libraries and mention the main motivation why a new library was built and what limitations one ran into, but also what the new library can't do (yet). Here's a good example of such a comparison: https://foalts.gitbook.io/docs/topic-guides/comparison-with-other-frameworks. This generally just helps people find the library with the right tradeoff for their needs as there's a rarely one single best library for all use-cases out there. I also understand that naturally all such comparisons by a library author have a level of bias (and some have a lot), but I (hope) most people have a healthy awareness of that bias and take that into consideration when reading a comparison from a library author.

Anyways, that aside :) - coming to your other question: The typical case of child logger is to pass around some contextual attribute without repeating oneselves, in some cases many levels deep down the call stack.

For example let's say you have some code that processes a message from a message queue and you want to attach that messageId to every log line. Here's some code to demonstrate this:


type Message { id: string, type: string, payload: any };

function processMessage(message: Message) {
  const logger = rootLogger.child({messageId: messageId, messageType: message.type});

  logger.info('Going to process message');

  try {
    await doExpensiveStuff(message.payload, logger);
    logger.info('Finished processing message');
  } catch (e) {
    logger.error('Failed to process message', {err});
  } 
}

in this example each of the log lines would have messageId and messageType as json attributes, even though I just typed it out in the beginning when the child logger was created. Furthermore even the log lines produced by the operations inside doExpensiveStuff would have those attributes as well. Lastly doExpensiveStuff could internally create a a child logger from the child logger and add another attribute that gets added to the context. In general this is how child loggers work in pino,winston and roarrr.

roarr even allows passing attributes/context to child functions without explicitly passing the logger using roarr.adopt, which leverages JS domains (will be replaced with async_hooks).

As for creating multiple loggers with different configurations: I actually would like to have all logger instances have a single parent (rootLogger called in my example above) and inherit some config from that which I can set / change at runtime. The particular use-case I have in mind is having an application in production whose log level is set to info but by flipping a switch somewhere (i.e. change a param in config file that is being continuously watched or use something like https://cloud.google.com/deployment-manager/runtime-configurator ) one could set the log level to debug temporarily, which is useful to debug issues in production during an incident without requiring a restart of the application. Changing the log level dynamically at runtime is something that is supported by winston (see the "You may also dynamically change the log level of a transport:" section of https://github.com/winstonjs/winston) for example by setting transports.console.level = 'debug' and in this case would automatically propagate to all loggers using this transport incl. their respective child loggers.

Hope that helps to provide some context :)

terehov commented 4 years ago

Thanks, @geekflyer! In our projects, we have a helper LoggerFactory but I see your point that it makes sense to have this inside. I'm a bit busy these days, but I'll give it some thoughts and try to come up with a solution soon 👍

terehov commented 4 years ago

Hey @geekflyer, thanks for hanging in. I have just pre-released a version that tackles this issue 2.3.0-0. https://www.npmjs.com/package/tslog/v/2.3.0-0

I am still working on some more tests and docs, but it would be awesome if you could give it a spin and tell me how you like it.

New features:

npm i tslog@next

Example:


/* Child Logger Example */

const mainLogger: Logger = new Logger({
  name: "MainLogger",
  printLogMessageInNewLine: true,
  prefix: ["main"],
});
mainLogger.info("MainLogger initiated");

const childLogger1 = mainLogger.getChildLogger({
  name: "ChildLogger1",
  prefix: ["child1"],
});
childLogger1.info("ChildLogger1 initiated");

const childLogger1_1 = childLogger1.getChildLogger({
  name: "ChildLogger1-1",
  prefix: ["child1-1"],
});
childLogger1_1.info("ChildLogger1-1 initiated");
childLogger1_1.silly("ChildLogger1-1 silly 1");
childLogger1_1.silly("ChildLogger1-1 silly 2");
childLogger1_1.silly("ChildLogger1-1 silly 3");
mainLogger.setSettings({ minLevel: "debug" });
childLogger1_1.silly("ChildLogger1-1 silly 4");
childLogger1_1.silly("ChildLogger1-1 silly 5");
mainLogger.setSettings({
  minLevel: "silly",
  prefix: ["mainRenamed"],
});
childLogger1_1.silly("ChildLogger1-1 silly 6");
childLogger1.setSettings({ prefix: ["child1Renamed"] });
childLogger1_1.debug("ChildLogger1-1 debug finish");

Output:

image
terehov commented 4 years ago

Available in: https://github.com/fullstack-build/tslog/releases/tag/v2.5.0

Docs: https://github.com/fullstack-build/tslog#child-logger

jakobrosenberg commented 3 years ago

Every author of every open-source library invests his (free) time and therefore every library has a right to exist, as long as it helps others

Clarifying key differences or your motivation to start this project shouldn't conflict with that belief.

A subjective, but respectful comparison to prior arts goes a very long way in helping others pick the right tool for the right job.

cheruvian commented 3 years ago

+1 especially when making claims that this library is ⚡ Small footprint, blazing performance (native V8 integration) I'd love to understand what this means when it comes to logging and if it is still blazing performance when compared to other (optimized) logging libraries. I can't seem to find any performance testing anywhere. Has anyone set up a test?

Features are nice and all but at the end of the day I like to understand how a logging library performs first and then decide if those extra features are worth the performance degradation (if any).

Definitely not trying to argue this library shouldn't exist, it sure looks pretty and feature rich just trying to figure out which library to use ¯_(ツ)_/¯