Metadata for users such as name, email, etc are not always present for users. For example, I am running express and I want to log the %x{company}%x{username} so that when I look at my logs I can immediately understand which user this affects. Or for example, I could log %x{payingOrTial} the type of user.
This works well when the user is logged in. However, my logger encompasses everything. I log when the server boots up. I log during the login screen where a user is not yet logged in. In these circumstances there is no way to retrieve this metadata.
So for example
```
"username": function () {
var session = require('continuation-local-storage').getNamespace('api.callinize');
if(!session) session = require('continuation-local-storage').getNamespace('dashboard.callinize');
var username = session && session.get('user') && session.get('user').username;
if(!username) return "";
return " " + username + " ";
}
```
I try to get the metadata. If I get no metdata I return a blank string. Unfortunately, in the current implementation, due to the OR operator, even if I have a replacement of "" || matchedString,
```
replaceToken(conversionCharacter, loggingEvent, specifier) ||
matchedString;
```
the blank string equals false and puts the token in the log instead of the blank string. This makes the log lines get long with information that is not relevant. The better thing to do is simply allow for blank strings. This lets the user have control over their logs and also allows for more metadata to go in the logs, without having to pick only metadata that is always present.
In the original version, the following operation looks synchronic, however it is not:
```
res.end = end;
res.end(data,enc);
//emit the log entry
```
In fact, it starts a series of async operations, in which the request may yet be changed after the request log has already been emitted
(in our case - a change on request headers was observed, probably by some low level hook or hacky wrap of some http.ServerResponse method that's involved on the process - but called asynchronously)
what leads to situation that the request log does not capture valid data.
(observed by us:
- request headers
- calculated end time, when concerning big content
)
The fix just used `setTimeout(function() { /*emit the log entry*/ }, 1)`, but I'm afraid it may not hold true for big contents.
Well. maybe the headers part will, but the response time calculation will lie.
The fix relays on: http://nodejs.org/api/http.html#http_event_finish
This function should be useful when you need to log during async
parallel operations, without having a mess in logs.
For example when you walk asynchronously a directory and you want logs
to be grouped by file.
It returns the same getLogger() object but messages are stored
internally and sent to appenders only when you call the flush() method
on it.
According to the GELF spec v1.1 [1], the full_message field in GELF is
optional. The log4js implemention until now has sent identitical
short_message and full_message fields. Since this does not add any new
information to the log message, I suggest that full_message be dropped
from GELF.
--
[1] http://graylog2.org/gelf#specs
It turns out that whenever the clusterred appender is used the log event is passed to all actual appenders.
The actual appender's category is ignored.
Signed-off-by: Vladimir Mitev <idalv@users.noreply.github.com>
Updated logger.js to support disabling all log writes.
Updated log4js.js shutdown function to disable log writes.
Added tests.
Update gitignore to ignore rolling date stream's test output.
loadAppender will check for a shutdown function exposed by
a loaded appender. If present, it will be cached so that the
shutdown function can execute it.
The intent here is that a Node application would not invoked
process.exit until after the log4js shutdown callback returns.
Previously, appenders could only be added by specifying the filepath
to the appender. This required the appender's path to be specified
either relative to the log4js installation, relative to a NODE_PATH
token, or absolute. This creates a coupling between the log4js
configurer and the log4js installation location, or a coupling between
the log4js configurer and the global NODE_PATH. This commit removes
the coupling by allowing the loading of appenders to be done relative
to the log4js configurer.
using levels.toLevel and this.isLevelEnabled prior to emiting the event will prevent the appenders from being notified if the log level provided is below the loggers level.