4

I'm using node-log4js. (it's log4JS, not log4J!) I thought of the loggers 'categories' to be just like the Strings you put in Log4J into the constructor of a logger (normally you put your fqn class name there), so that log4j can put logged things to the right location.

I got the following config:

{
    "appenders": [
        {
            "type": "console",
        },
        {
            "type": "file",
            "absolute": true,
            "filename": "/tmp/app.log",
            "maxLogSize": 20480,
            "backups": 10     
        },
        {
            "type": "console",
            "category": "app.access"
        }
    ]
}

The desired behaviour would be that all "app.access" stuff only goes to the last appender (which is, at the moment, the console, too, but could change in future). At the moment, all loggings with the category 'app.access' will be logged twice to console and once to file.

Is there a way to give those other two appenders a "all but app.access"-category? How?

Thank you very much in advance

sampathsris
  • 21,564
  • 12
  • 71
  • 98
Mitja
  • 1,969
  • 30
  • 35

3 Answers3

6

I had a similar requirement. I wanted to exclude a bunch of categories from the console logger.

I wrote something based on the logLevelFilter, which I called categoryFilter.

categoryFilter.js:

"use strict";
var log4js = require('log4js');

function categoryFilter (excludeCategories, appender) {
  return function(logEvent) {
    if (excludeCategories.every(function(x){return (x!=logEvent.category);})) {
      appender(logEvent);
    }
  };
}

function configure(config) {
  log4js.loadAppender(config.appender.type);
  var appender = log4js.appenderMakers[config.appender.type](config.appender);
  return categoryFilter(config.exclude, appender);
}

exports.appender = categoryFilter;
exports.configure = configure;

To use it, I have this snippet near the beginning of my app:

  var log4js = require('log4js');
  log4js.loadAppender('categoryFilter',require('./src/categoryFilter'));
  log4js.configure('log4js-conf.js');

My configuration file has the following:

{
  "appenders": [
    {
      "type": "file",
      "filename": "logs/logfile.log",
      "maxLogSize": 20480,
      "backups": 3
    },
    {
      "type": "categoryFilter",
      "exclude":["results"],
      "appender":{
        "type": "console"
      }
    },
  ],
  "replaceConsole":true
}

I'd be interested in your thoughts.

John
  • 6,701
  • 3
  • 34
  • 56
  • Please put in a pull request with that -- it is such very basic functionality of Log4* that Log4js really ought to support it! – Lee Goddard Apr 01 '16 at 08:03
  • 1
    It seems to be there already. The "excludes" entry can be a single string or an array of strings. See https://github.com/nomiddlename/log4js-node/blob/master/lib/appenders/categoryFilter.js – John Apr 03 '16 at 00:35
  • Thank you John. For future googlers, this is now [included in log4js](https://github.com/nomiddlename/log4js-node/blob/master/lib/appenders/categoryFilter.js), and you can use it just by following John's configuration file example, or looking at [this other example](https://github.com/nomiddlename/log4js-node/blob/master/test/with-categoryFilter.json). `categoryFilter` wraps your appender. – Steve Kehlet Apr 29 '16 at 16:42
1

I faced a similar problem and here's how I resolved it - using the levels. Used the following config file:

{
    "appenders": [
        {
            "type": "logLevelFilter",
            "level": "INFO",
            "appender": { 
                "type": "console",
                "layout": {
                    "type": "colored",
                    "pattern": "[%d] %-5p <%c> %m"
                }
            }
        },
        {
            "type": "console",
            "layout": {
                "type": "messagePassThrough"
            },
            "category": "raw"
        }
    ]
}

The use 2 different log4js instances as follows:

var path = require('path');
var log4js = require('log4js');
log4js.configure('log4js.json');
var log = log4js.getLogger(path.basename(__filename));
var raw = log4js.getLogger('raw');

In your code use log.info(), log.warn(), log.error() or log.fatal() to have standard logs such as:

[2015-01-12 19:37:19.931] [INFO] app.js - app started
[2015-01-12 19:38:52.484] [ERROR] other.js - Error. failed to open file

Same logs above would look like this using raw.trace():

app started
Error. failed to open file

I'm using it to highlight different situations in the console. It is important to me to have it look totally different so I will notice these events. But when it is logged to a file, I don't mind if it has the timestamp (since it actually helps when looking back in time). Therefore I also have the following appender in the log4js.json file:

{
    "type": "file",
    "filename": "app.log",
    "maxLogSize": 1048576,
    "backups": 10,
    "layout": {
        "type": "pattern",
        "pattern": "[%d] %-5p <%c> %m"
    }
}

Hope this help! :)

Ozk
  • 181
  • 11
0

Just assign top two appenders to a different category than "app.access" and use that category in getLogger.

RaSi
  • 470
  • 5
  • 8
  • 2
    I know that i could do that. But then i would lose the possibility of giving each node module its own category. E.g. if I have a user registration and one user login module, i give them the categories app.user.registration and app.user.login respectively, thus leading to the issue that i'm required to name each category explicitly in the log4js config. This is not suitable since i got 40 and growing modules until now. – Mitja Apr 08 '14 at 07:00