Ignition icon indicating copy to clipboard operation
Ignition copied to clipboard

Add plugin architecture for logging

Open gcochard opened this issue 7 years ago • 7 comments

This is a proposal for implementing a custom logger as requested in #50

  1. Add config support for arbitrary log streams
  2. Add API for registering a stream name, and initializing and returning a Bunyan stream
  3. Add support to ghost-cli to install required logging module
  4. When config entry specifies a custom stream type, require the module that sets up and returns the stream.
  5. If the require fails, gracefully warn and do not init the stream
  6. Add a config option to mark a stream as required and throw a fatal error if it is not successfully initialized

Have I missed anything here?

gcochard avatar Oct 04 '17 18:10 gcochard

Additionally we should study the eslint plugin architecture as they have been successful with theirs.

gcochard avatar Oct 04 '17 18:10 gcochard

@gcochard Hey again 👋 Is it possible for you to share some pseudo code here? Just share anything you have in your mind. Thanks 😁

kirrg001 avatar Oct 05 '17 05:10 kirrg001

Here's a quick first draft of my thoughts. Feel free to expand on any of these items, let me know if I'm thinking this through properly, and give me feedback on any potential pitfalls with this.

  1. Configs should be similar to how they are now, add a transport to the array and then have a matching key in the config.
  2. Modules will implement an API with a few required functions: registerLogger, initializeLogger, defaultConfig etc. registerLogger should return true or false, indicating whether it can be used at this time, false would imply the required modules are missing. This should be a fatal error and the logging library should not try to init the logger. initializeLogger should return a bunyan stream. defaultConfig should return a config object with the required fields filled in.
  3. When using ghost-cli to initialize ghost, it should prompt for any custom loggers to add. You should be able to enter the module name, and then it will npm install it, and allow you to edit the configs returned by the module.
  4. This would be similar to the current transports set${transportName}Stream, but require the correct module and call the API functions for registerLogger and initializeLogger.
  5. This is when registerLogger fails, it should stop.
  6. If there is a config saying required: true on the transport, bail and process.exit(1) or similar.

gcochard avatar Oct 05 '17 19:10 gcochard

Here's a hypothetical logging plugin/module that would conform to the API:

'use strict';
var loggerModule;
var loggerInstance;
function registerLogger(name, config){
  try{
    loggerModule = require('logger-name');
  } catch(e){
    if(config.required){
      throw e;
    }
  }
}

function initializeLogger(config){
  loggerInstance = loggerModule(config);
  return loggerInstance.stream();
}

function defaultConfig(){
  return {
    level: 'info',
    raw: true
  };
}

module.exports = { registerLogger, initializeLogger, defaultConfig };

gcochard avatar Oct 06 '17 17:10 gcochard

On the ignition side, it would consume the API basically like this:

const transports = config.get('logger:transports');
transports.forEach(function(transport){
  if(builtinTranpsorts.indexOf(transport) == -1){
    let transportModule = require(transport);
    let defaultConfig = transportModule.defaultConfig();
    let moduleConfig = Object.extend(defaultConfig, config.get(`logger:${transport}`));
    transportModule.registerLogger(transport, moduleConfig);
    let stream = transportModule.initializeLogger(moduleConfig);
    loggers.streams[transport] = stream;
  }
});

gcochard avatar Oct 06 '17 17:10 gcochard

No worries, I have this in my inbox 😬

kirrg001 avatar Oct 09 '17 19:10 kirrg001

I am fine with accepting a PR to be able to install a different stream with Ignition. It's a bit weird that you would have to publish a super small new npm module, which wraps e.g. the bunyan google cloud package. The other alternative is to offer a group of alternative streams in one npm package. The disadvantage is that you as a user would install multiple dependencies, but you might just need a single one. Not 100% sure which way to go here.

So you would have to install e.g. bunyan-ignition-google-cloud on your Ghost blog manually and then you should be able to use logging: {transports: ['google-cloud', 'file']}.

How do you customise a different stream? Maybe like this logging: { 'google-cloud': {}}.

ignition is primary used for Ghost and it was designed for it. The CLI installs Ghost easily. But ignition can be used in any project in theory. So the alternative is to install a different logging stream via the CLI. But that means that a different project has no advantage from that, because it's Ghost specific. I think with a manual install procedure, we can still support installing a different stream via the CLI more easily later on e.g. ghost show logging-streams.

FYI: We only have one community project at a time. So response or review delays are natural, because we have to keep the balance with our daily work and supporting feature requests.

kirrg001 avatar Nov 22 '17 11:11 kirrg001