> --
> Job Board: http://jobs.nodejs.org/
> Posting guidelines:
> https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com
> To unsubscribe from this group, send email to
> nodejs+un...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en?hl=en
A few suggestions:
The API should return null when there is no logging registered for the
module and people should be encouraged to use the following pattern:
var log = require('logging')('mymodulename');
// ...
module.exports = fancy (options) {
log && log('new fancy %method for %url', options)
}
This is better than setting log to function() {} when no logger has
been registered because it avoids useless (and potentially costly)
formatting of messages.
Also, I see a risk of confusion with application level logging /
auditing (which needs severity levels BTW). So I would rather call it
trace/tracing rather than log/logging to make it clear that this is
for traces that the developer will turn on and off during debugging.
Bruno
I would like to be able to run this in the browser too.
log( '%message', { message: "Everything is ruined forever", level:
"fatal" });
Assuming the spec ignores extra properties, you could totally use the
object argument to pass metadata. Then, in your globally-accessible
logger, you can handle it however you'd like.
Also, regarding the whole "why does this need to be global" thing: I
think for most 'traditional' logging, it's almost exclusively at the
application level. That could be either because there's no canonical
module/api for easily doing this sort of thing, or because you don't
actually want logging at that level. I'm not sure.
Either way, being able to hook onto this api would be *awesome* if you
wanted said instrumentation.
--Josh
--
Joshua Holbrook
Engineer
Nodejitsu Inc.
jo...@nodejitsu.com
but i think the same api as for console would be nice, because it's
already documented.
also using the module namespace could make it more readable:
module.log("something happen.")
module.error("fatal!")
also an integration into the current module system could enable the
ability to use logging
in modules without spamming all the time, unless you want it:
require('request').on('logging', console.log)
this is just an idea. because it came to my mind that monitoring
specific modules or
dependencies of specific modules would be easily solvable with this:
require('express/node_modules/connect').on('logging', console.log)
i hope you got the point, because about the syntax i'm not 99% sure
this is wise idea to
introduce an event system for _every_ module, but maybe somebody else
has an option
on that too.
That is also why the logger returns a function. A module level function is limited a little more than a returned function might be, this is more extensible.
On severity as a property on context. This is totally doable, the context can take any arbitrary properties you like.
On unique UUIDs. The context is usually an object that is actually being used in code. A logger could easily if (!obj.uuid) obj.uuid = blah. And track that uuid through other log messages. Doing dynamic stuff like this is the main point of just passing the whole context.
This has to be global. When i want to send the messages for my application somewhere, I want ALL the messages. There is not way to insure that a third party module is global for a process, which is why we must use process.logging.
-Mikeal
{ "tl;dr":
"Don't know whether you want to here stories about the Java ecosystem?
Java runtime in early days didn't provide standardized logging
capabilities.
Then came along Log4J and almost everybody used it. Of course not all,
older frameworks created their own logging. When combining libraries
and frameworks, configuring logging was a nightmare.
It was too late when Java delivered its own standardized logging
(java.util.logging). It missed very valuable features of Log4J and
most projects just don't use it, until today.
Now there is a zoo of logging-bridges, logging facades and logging
libraries. It is very confusing and of course there are a lot of
problems (class-loader, log-formats, transports, ...)."
}
IMHO node.js should provide feature-rich and extensible logging
capabilities, probably as a core module, because logging can become a
real performance bottleneck.
- support for log levels
- support for log categories / modules
- transports / appenders as plug-ins (stdout, stderr, file, syslog,
socket, mail, redis, mongo, ...)
- configurable log formats (date-format, pid, context-info)
- configuration changeable during runtime (w/o restarting -> watchdog)
- check if category/level is logged before calling log-method e.g. if
(log.isDebug()) { log.debug({...})
- support for correlation ids (e.g. UUID) would be plus but could be
handled outside as well
If no standard or de-facto standard is set, we will have that silly
zoo of incompatible loggers like in Java.
+1
I'm in for the process.log(ging) idea. But for that to work, I would
like to have some common methods there similar to console (warn, error,
..).
---
Diogo R.
Why not enhance console? In my opinion this be'd a more logical place for that.
console.nlog(); or something like that. which has a richer API than
simple console.log, behaves more like util.log and requires for
example a log category and log level. Or enhance util.log and let it
call console.dolog as global backsolution. and console.loglevel and
console.logcats to filter logging.
console.nlog('db', 3, 'message', someobject, 'futhermessage');
--
>> The traditional log4j approach is kind of ridiculous to instrument as a module developer, you don't really have a need for log levels for instance.i'm curious as to why you think that? you don't think being able to distinguish between log levels is useful?
My approach (as inspired by http://www.12factor.net/):* stdout / stderr are the *only* methods used for logging (via console, or the process streams)* library code *never* actively logs, it emits passive 'log' events that I may hook up to console.log / console.error
That's it. If you are doing one of the following, then IMO you're doing it wrong:* Writing logs to disk/network from within your program (Unix has pipes, use them!)* Treating your logs like structured data (they are not)
* Choosing what to log at program runtime (you can filter this with grep, seriously)* Adding timestamps to your log within your program (again, should be done from the outside)
--fg
I thought about this. The problem of course is that some APIs are purely functional so the only thing they can do is expose a global emitter just for logs which lack context :(
I found that a better method was actually to make the logger purely functional and pass in a context to each call, this allowed for much more dynamic handling of log messages across both evented and functional libraries.
On Dec 16, 11:06 pm, Mikeal Rogers <mikeal.rog...@gmail.com> wrote:
> What I'm focusing on is *only* the portion of the API used by module developers that want to log messages.
Exactly, and I think my idea is closely related to yours, and it's an
alternative and better view on logging. A logger function has the
properties transports and traits (both arrays), and you can just
change them and so change the behavior of the logger.
Code example: https://gist.github.com/1488297
Possibly because it moved? https://github.com/mikeal/logref
> Code example: https://gist.github.com/1488297
How about some api examples? Maybe I'm just being lazy, but I really
don't want to have to decipher a coffeescript implementation to know
how to use the api in javascript.
As a module developer, I have *no* idea who or what is going to be
consuming my logging messages. All I know is that there may or may not
be a "process.logging" defined, which hopefully takes predictable
arguments. I can accept a type signature of (text, obj) because it
should be able to cover multiple styles of logging (text-based or
object-based) without exploding.
Obviously, we all have varying opinions of the "right" way to log
messages (logref, winston, text vs. objects, the role of metadata and
log levels or lack thereof, appropriate log storage backends, etc),
but this is precisely why the "process.logging" api should be simple
and predictable (to allow for use by multiple opinionated logging
mechanisms)!
As I said earlier, I think the second argument should be used to pass
metadata (such as log level) if desired, such that the process.logging
implementation can take or leave properties that aren't interpolated
into the string.
(Speaking of: A separate interpolation library to use with the
"%thing" substitution would be handy for implementing process.logging
imo.)
--Josh
--
Joshua Holbrook
Engineer
Nodejitsu Inc.
jo...@nodejitsu.com
Your idea has nothing to do with Mikeal's. Let's face it, you just read
the
mails in fast forward and didn't get the point. Mikeal is pointing in a
standard
way of *ACCESSING* logging tools. Your talking about what to log
(context, not text).
I think that is important too, but that should be the second part. You
should both
just do a freaking module and publish here so people can start to use
and love :)
I'm +1:
- process.log(context[, context, .. ])
- process.log.info(text)
- process.log.warn(text)
- process.log.whatever(text)
---
Diogo R.
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
> the entire purpose of this thread is to avoid a "blessed global logging implementation"
I think your proposal handles this well in terms of what's passed to
the function (a string and object covers most bases), but you're still
suggesting a global method on process and I can understand why that
would upset people. We've all been trained to approach global
variables with the attitude of, "there has to be a better way," and I
don't not thoroughly convinced that logging is an exception.
> Rather than have some blessed global logging implementation, modules can emit events which you can choose to log or not in your application
This could work!
module.emit('log', "%thing is %verb", { thing: "Josh", verb: "awesome!" });
module.on('log', process.logging);
Not that you'd need a global .logging anymore, but the point is that
you can expose logging over an event emitter instead of calling a
global function this way, and that's kinda cool.
I do think this thread brought out a lot of discussion on what the
"right way" to do logs (and about how all others are obviously wrong),
but I also think there's been some good advice and discussion here.
Just because we disagree doesn't mean we're talking in circles...yet.
--Josh
--
> I for one think all logging should involve flow control with fibers
> because calling functions is far too difficult.
>
>> the entire purpose of this thread is to avoid a "blessed global logging implementation"
>
> I think your proposal handles this well in terms of what's passed to
> the function (a string and object covers most bases), but you're still
> suggesting a global method on process and I can understand why that
> would upset people. We've all been trained to approach global
> variables with the attitude of, "there has to be a better way," and I
> don't not thoroughly convinced that logging is an exception.
>
>> Rather than have some blessed global logging implementation, modules can emit events which you can choose to log or not in your application
>
> This could work!
>
> module.emit('log', "%thing is %verb", { thing: "Josh", verb: "awesome!" });
>
> module.on('log', process.logging);
>
> Not that you'd need a global .logging anymore, but the point is that
> you can expose logging over an event emitter instead of calling a
> global function this way, and that's kinda cool.
>
> I do think this thread brought out a lot of discussion on what the
> "right way" to do logs (and about how all others are obviously wrong),
> but I also think there's been some good advice and discussion here.
> Just because we disagree doesn't mean we're talking in circles...yet.
My answer to both your comments is the same answer.
A user running a service in production wants to attach a truly global handler for logging. As much as we like to think that require('module') returns something global, it doesn't. That's why the user needs to attach a function to process, which is truly global, before importing any other modules.
For instance, let's say that I add log events to the watch module.
I do require('watch').on('log', logger.handler('watch'))
Then I import a module that uses watch, like node-couchapp. But node-couchapp bundled that dependency, or it required a different version. And it doesn't add logging. Now I'm screwed as the person running the service, i can't get logging events out of watch where it counts.
Yes, I did think about this problem before I wrote this spec. I've been one of the biggest advocates against *anything* global in node and treating modules as global in any context. It turns out, for module developers, that is almost always true, but for people developing applications and services, they need to add global hooks in to their application for debugging. If you look at the current debugging tools available (node-inspector, dtrace) they all hook in globally in to node, we need the same for logging.
It seems like the "right thing" for node-couchapp to do would be to
forward the events up the chain, something like:
watch.on('log', myModule.emit.bind(myModule, 'log') );
The problem I can foresee with this approach is that you can't always
trust module authors to forward the logs in any meaningful way. Then
again, can you also trust them to not define their own
process.logging? I think we could, but I've had discussions in
meatspace with people that disagree. Given Murphy's Law, someone will
eventually mess this up, so I suppose the real chore is finding a way
that minimizes opportunities to screw up. Perhaps process.logging has
a lower chance of screw-up than re-emitting log events. Who knows? I
sure don't.
> Yes, I did think about this problem before I wrote this spec.
I believe you, but that doesn't mean you aren't going to be fighting
an uphill battle. ;) Fwiw, I think process.logging is at least a good
enough idea to try out regardless of these implementation details.
> this week i'll be adding logging to request
Cool! I'd definitely be interested in seeing how it works out in practice.
--Josh
>> But node-couchapp bundled that dependency, or it required a different version. And it doesn't add logging.
>
> It seems like the "right thing" for node-couchapp to do would be to
> forward the events up the chain, something like:
>
> watch.on('log', myModule.emit.bind(myModule, 'log') );
>
> The problem I can foresee with this approach is that you can't always
> trust module authors to forward the logs in any meaningful way. Then
> again, can you also trust them to not define their own
> process.logging? I think we could, but I've had discussions in
> meatspace with people that disagree. Given Murphy's Law, someone will
> eventually mess this up, so I suppose the real chore is finding a way
> that minimizes opportunities to screw up. Perhaps process.logging has
> a lower chance of screw-up than re-emitting log events. Who knows? I
> sure don't.
If someone overwrites a global in their module they should be shot. We can enforce this as a community.
There are lots of cases where foolish or malicious overwriting will break stuff in node, we don't really have an enforcement mechanism other than convention and community.
thank your very much for this interesting discussion - nice read :-).
Like you said some lines earlier, logging and what to log depends
pretty much on the user reading the log.
# process.logging vs console.log
I fully agree, that logging is a global thing. This would be the case
with Felix's approach on using the stdout+stderr for log output, same
for process.logging and so on. Why not use console.log and replace it
with your implementation?
What's the full difference in using (from your example):
if (process.logging) var log = process.logging('mymodule')
log("what i want to log");
to:
console.logPrefix = 'mymodule';
console.log("what i want to log");
I actually would go so far, that console.log for each module could be
implemented in such way, that it's already logging with a logPrefix
which reflects the module name.
Resulting in a simple:
console.log("what i want to log");
Overriding the Logger would be something like:
console = require("my-own-logging-implementation");
at the top of your run_server.js/run_console.js script.
# Log Levels
I understand your 404-example from couchdb. This is a valid point.
Though when you are debugging a case with couchdb and a reverseproxy
in front, you may want to log anywhere if the 404 is retrieved by
couchdb or the reverseproxy. Thus having the option to turn at least
verbosity level to ON would be great. It's completely difficult to
explain the difference between debug, trace and info to somebody who
is new to this stuff. Thus having only error (something is wrong:
stderr), log (something to log: stdout, so to say) and some kind of
verbose logging (turned on on request in case of debugging or
maintaining the module).
Have fun coding,
Jan
--
For instance:
var logger = require("logger");
logger.error(String message, Error error) // logger.error("this is an
error message") would output something like this (maybe with bash
color codes surrounding the message ;) ) [2011-12-23 13:37] [ERROR]
"This is an error message"
logger.warn(String message)
logger.notice(String message)
logger.info(String message)
logger.debug(String message)
Maybe the date format logging format and other options like using bash
colors should be configurable (Where?).
Just my 2 cents
What do you think?
Kind regards
---
Thomas FRITZ
web http://fritzthomas.com
twitter http://twitter.com/thomasf
2011/12/23 Charlie Robbins <charlie...@gmail.com>:
logger should be an EventEmitter so you can hook into log events like
"error", "warn", "notice", "info", "debug"
And the logging output should contain the log source (module name or
file path) and the line number additional to the date and log level.
Kind regards
---
Thomas FRITZ
web http://fritzthomas.com
twitter http://twitter.com/thomasf
2011/12/23 Thomas Fritz <frit...@gmail.com>: