Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logger metadata #124

Open
clibu opened this issue Oct 13, 2020 · 4 comments
Open

Logger metadata #124

clibu opened this issue Oct 13, 2020 · 4 comments

Comments

@clibu
Copy link

clibu commented Oct 13, 2020

Various loggers enable metadata to be included in logger output. In Pino etc. this is handled by child loggers. In Consola you can use log.wthTag( name ) to create a logger with a name.

This enables you to know more about the source of log entries. It is especially important when filenames aren't included in the log output, or where filenames are useless such as in the browser when all source files are bundled together in one file.

I can't see a way to accomplish this in caterpillar at present.

My suggestion is to allow a metadata object to be included in Logger( LoggerOptions ). This would then be included in LogEntry and therefore available everywhere.

You would then do new Logger( { metaObj, ... } ) to create the logger instances you needed.

I would also use the metaObj in a Filter() transform to filter out entries matching certain metadata which I'm not interested in at a point in time or only pipe it to a specific target.

@balupton
Copy link
Member

balupton commented Oct 13, 2020

Thanks, some thoughts on this:

  1. we could add a withTags message, however I'm more inclined to do a logWithMetadata(metadata, logLevel, args…) method.
  2. we would add a transform that is piped to, that adds the missing functionality

The idea of having filter also filter this is a good one.

Alternatively, we could extend the Map class with a Metadata class, that when used as the first argument in a log argument, uses that as the metadata. So it would be like:

const { Logger, Metadata } = require('caterpillar')
const logger = new Logger()

logger.pipe(process.stdout)

logger.log(new Metadata({tags: ['something'], level: 'warn', args: ['this is a warning, which is level', 4]}))
logger.log(new Metadata({tags: ['something'], level :'warn'}), 'this is a warning, which is level', 4)
logger.log(new Metadata({tags: ['something']}), 'warn', 'this is a warning, which is level', 4)

logger.warn(new Metadata({tags: ['something'], args: ['this is a warning, which is level', 4]}))
logger.warn(new Metadata({tags: ['something']}), 'this is a warning, which is level', 4)

Could do the same a Tags class that extends a Set class:

const { Logger, Tags } = require('caterpillar')
const logger = new Logger()

logger.pipe(process.stdout)

logger.log(new Tags(['something']), 'warn', 'this is a warning, which is level', 4)

logger.warn(new Tags(['something']), 'this is a warning, which is level', 4)

@clibu
Copy link
Author

clibu commented Oct 14, 2020

Either approach seems fine (or even both) but logWithMetadata() is probably clearer.

I use a separate tag/metaData for each source file. ie. all logger calls in a given source use the same tag. So I'd have a function that wrapped logWithMetadata() and call that throughout the file. In other words I wouldn't want to call logWithMetadata() directly to log stuff.

I've written a child class that extends Logger and adds metaObj to LogEntry. And I create a new MyLogger instance in each source file. So logWithMetadata() would remove this and use less resources. Then in a custom Human class I include this metaObj in it's output. So that works well and does just what I want for now.

I've got some thoughts on improving Human. For example the ability to pass in a template to use. This should remove the need for folks to write their own Human classes.

I have other changes to Human and Browser I want to try and will post more later.

@clibu
Copy link
Author

clibu commented Oct 14, 2020

Thinking about these approaches over night and one thing that came to mind is I wouldn't want to have to create a wrapped logWithMetadata() for each level for different tag/metaObj.

I've also created:

const loggerBlackList = {
    'clibu_sync': 4  // Only show <= warn items. Comment out to remove from list or spec Infinity.
}

Which I use in a Filter and this works a treat.

@clibu
Copy link
Author

clibu commented Oct 15, 2020

Ok, after working on caterpillar most of the day I'm now leaning towards logger.log(new Metadata({..}), .. ) versus introducing a new function. And just your third example:

logger.log(new Metadata({tags: ['something']}), 'warn', 'this is a warning, which is level', 4)

where Metadata is the first and optional parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants