[Coldbox 6.3.0][Logbox] Appenders/Categories Question

What’s the best way to configure logbox if you want to have some appenders respond to different logging levels based on the logging category?

For example, let’s say I have two appenders, coldboxTracer and emailLog. Under normal circumstances, I want to have coldboxTracer fire all the time, and I only want emailLog to fire when the levelMax is ERROR or higher. However, under some circumstances, like when I’m troubleshooting a particular model, I want to have emailLog appender fire with a levelMax of INFO.

Here’s an example configuration in a coldbox.cfc for reference:

logBox = {
	// Define Appenders
	appenders = {
        coldboxTracer = { class="coldbox.system.logging.appenders.ConsoleAppender" },
        emailLog = {
            class="coldbox.system.logging.appenders.EmailAppender",
            layout="logging.emailLayout",
            properties = {
                from = settings.emailFrom,
                to = settings.logEmail,
                subject = coldbox.appname
            },
            levelMax = "ERROR" // 0=Fatal, Error=1, warn=2, 3=Info 4=debug etc...
        }
	},
	// Root Logger
	root = { levelmax="INFO", appenders="*" },
    categories = {
        "coldbox.system" = { levelmax="WARN", appenders="*" },
        "models.users.userService" = { levelmax="INFO", appenders="*" }, // I'd like this category to override emailAppender's default levelMax
    }
};

The only thing I can think right now would be to duplicate the emailLog appender and call it something else like emailLog2 and configure it with a levelMax of INFO. Then I would need to replace the * in every other logging category to ensure that it doesn’t use that appender like this:

logBox = {
	// Define Appenders
	appenders = {
        coldboxTracer = { class="coldbox.system.logging.appenders.ConsoleAppender" },
        emailLog = {
            class="coldbox.system.logging.appenders.EmailAppender",
            layout="logging.emailLayout",
            properties = {
                from = settings.emailFrom,
                to = settings.logEmail,
                subject = coldbox.appname
            },
            levelMax = "ERROR" // 0=Fatal, Error=1, warn=2, 3=Info 4=debug etc...
        },
        emailLog2 = {
            class="coldbox.system.logging.appenders.EmailAppender",
            layout="logging.emailLayout",
            properties = {
                from = settings.emailFrom,
                to = settings.logEmail,
                subject = coldbox.appname
            },
            levelMax = "INFO" // 0=Fatal, Error=1, warn=2, 3=Info 4=debug etc...
        }
	},
	// Root Logger
	root = { levelmax="INFO", appenders="coldboxTracer,emailLog" },
    categories = {
        "coldbox.system" = { levelmax="WARN", appenders="coldboxTracer,emailLog" },
        "models.users.userService" = { levelmax="INFO", appenders="coldboxTracer,emailLog2" }, 
    }
};

Am I going about this correctly or is there a better/easier way to accomplish this type of logbox configuration?

I’m pretty certain the path you’re taking is the correct (only really) way to accomplish this.

When a log event is passed to logbox, it has a severity baked into it. First the event is passed through the named logger, or logger category if you will. the max/min levels of that category have the ability to filter out the log message right there. Then, it gets passed to all the appenders configured for that category. The max/min of each appender also has the ability to filter out the log message based on its severity. The filtering the appender does however, is without any regard to the logging category who passed it the message. So if you want to have a specific appender and specific category combination who have different logging levels, you’d need to create a one-off configuration for that category and a one-off appender for it to use, which is what you have done.

1 Like

Thanks Brad. It’s good to know I wasn’t going down the wrong path.

I’m not sure if it would be helpful to anyone else or not, but I will spend some time in the future and create a PR for Logbox which would add an additional configuration property like excludeAppenders which would override the list of appenders. Something like that might give a little extra flexibility similarly to how Mementifier allows for defaultExcludes/defaultIncludes.

In theory, it would allow you to do something like this:

categories = {
        "coldbox.system" = { levelmax="WARN", appenders="*", excludeAppenders="emailLog2" }
}

Thanks again. :slight_smile: