megahertz / electron-log

Simple logging module Electron/Node.js/NW.js application. No dependencies. No complicated configuration.
MIT License
1.3k stars 127 forks source link

Add ability to configure electron-log via a config object #426

Closed IsmaelMartinez closed 2 months ago

IsmaelMartinez commented 2 months ago

Hi! Thanks for creating electron-log!

I am about to include this library into an app I maintain (teams-for-linux). The app, does allow to configure multiple settings via "config" options and it would be great to be able to provide a config object into electron-log, so that users can just configure it as they please.

Putting this feature request as What/Why/Alternative format. Hopefully it provides enough information.


What

I would like to be able to configure the electron-log via a config file (or object) that can be provided to the electron-log on initialisation.

Why

I would like to use electron-log but provide to my users with the ability to configure the many features this logger provides

Alternative

Create an object in the application that then parses to the multiple options electron-log provides. This would require a lot of mapping work that then might break if the options in electron-log change.

I suspect that by adding this as a config object, then you would be able to add other options like providing a config file, etc.


Thanks in advance!

megahertz commented 2 months ago

Unfortunately, it doesn't support central configuration since any transport is configured independently. The only way of applying config at once is using something like lodash merge. Haven't tried it yet, but it should work:

_.merge(log, {
  transports: {
    file: {
      maxSize: 2_000_000,
    },
    console: {
      format: '[{h}:{i}:{s}.{ms}] {text}'
    }
  }
}
IsmaelMartinez commented 2 months ago

Thanks for the suggestion. I will have a play and see if that works and report back. Thanks!

IsmaelMartinez commented 2 months ago

Hi, I found something interesting when trying this and I don't know if it is a bugger or an intended feature.

function applyElectronLogConfig(config) {
        console.debug(`Initialising logger with config.transports: ${JSON.stringify(config.transports)}`);
        console.debug(`log.transports.console.level = ${log.transports.console.level}`);
        console.debug(`log.transports.file.level = ${log.transports.file.level}`);
        _.merge(log, config);
        console.debug(`log.transports.console.level = ${log.transports.console.level}`);
        console.debug(`log.transports.file.level = ${log.transports.file.level}`);
        console.debug(`Logger initialised with transports: ${JSON.stringify(log.transports)}`);
        Object.assign(console, log.functions);
        log.initialize();
        if (log.transports?.file?.level) {
            console.debug(`File logging with level ${log.transports.file.level}`);
        }
        if (log.transports?.console?.level) {
            console.debug(`Console logging enabled with level ${log.transports.console.level}`);
        }
}

If I use this config, it works fine (disables the file transport)

transports: {
    file: {
        level: false
    }
}

However, if I also modify the console property it gets a bit confused, and disables the console and apply the formatting to the file.

transports: {
    console: {
        level: 'debug'
    },
    file: {
        level: false
    }
}

The same happens if I make those changes directly on the code (without lodash). Am I missing something and/or doing something odd?

The logs that prints in the console are:

Initialising logger with config.transports: {"console":{"level":"debug"},"file":{"level":false}}
log.transports.console.level = silly
log.transports.file.level = silly
log.transports.console.level = debug
log.transports.file.level = false

The it stops logging anything in here.

In the file I get logs, but I would have expected that setting the level as false would mean no file logging:

[2024-07-12 10:09:36.912] [debug] File logging with level silly
[2024-07-12 10:09:36.915] [debug] Console logging enabled with level debug
...

Similar if I only change the level in the console, I just stop getting logs in the console

transports: {
    console: {
    level: 'info'
    }
}

Happy to create another ticket with this as an issue if you find it better to track it, and I might have a wee look to see if I find the why and I can put a PR to fix it.

megahertz commented 2 months ago

Yep, you're right. It looks like the _.merge function considers a function as a nonobject and overwrites it.

So you need a workaround like

_.mergeWith(
  log,
  {
    transports: {
      file: { level: false },
      console: { level: 'info' },
    },
  },
  (obj, src) => typeof obj === 'function' ? Object.assign(obj, src) : undefined,
);
IsmaelMartinez commented 2 months ago

It works! Thanks a lot!

My function now looks like this:

function setLoggerConfig(config) {
  _.mergeWith(log, config,
      (obj, src) => typeof obj === 'function' ? Object.assign(obj, src) : undefined,
  );
  console.debug(`Logger initialised with transports: ${JSON.stringify(log.transports)}`);
  log.initialize();
  Object.assign(console, log.functions);
}

I will play with a few examples to see if I get any "limitations" but does closes this issue. Thanks again for the info/help (and logger)!