Discussion:
Review of Jose Armando Garcia Sancio's std.log
David Nadlinger
2012-02-13 15:50:04 UTC
Permalink
There are several modules in the review queue right now, and to get
things going, I have volunteered to manage the review of Jose's std.log
proposal. Barring any objections, the review period starts now and ends
in three weeks, on March 6th, followed by a week of voting.

---
Code:
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html

Known remaining issues:
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.

Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---

Earlier drafts of this library were discussed last year, just search the
NG and ML archives for "std.log".

I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus,
I'd warmly encourage everyone to actively try out the module or compare
it with any logging solution you might already be using in your project.

Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!

David
David Nadlinger
2012-02-13 16:49:49 UTC
Permalink
Post by David Nadlinger
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
A few small points from a first pass through the docs:

Spelling nits:
- potion -> position
- enviroment -> environment
- arguements -> arguments
- explictly -> explicitly
- fileter -> filter
- persiste -> persist
- genereated -> generated
- brakets -> brackets
- paramater -> parameter
- compuration -> computation

The introductory section needs some copy editing, e.g.:
- In the first paragraph, every sentence starts with ?The module?
- disabled/enabled -> disable/enable
- ?In the other? -> ?in the order?

You define the Severity enum members starting with fatal as 0. Why not
the other way round ? so that severityA < severityB would do what you
(or at least I) would expect?

Include a cross-reference to log() in the Severity comment?

Maybe clarify the meaning of ?can be logged? (i.e. the severity level is
not completely disabled) in the LogFilter docs?

Are the explicit to!string calls in the first LogFilter example required?

config.logger: First line is missing a full stop, ?The default value a
FileLogger.?, ?change and configure? (where is the difference?)

?Create a configuration object based on the passed parameter.? is
slightly misleading, because parseCommandLine() doesn't actually create
an object.


I'll post a more in-depth review later.

David
Jonathan M Davis
2012-02-13 18:19:23 UTC
Permalink
Post by David Nadlinger
You define the Severity enum members starting with fatal as 0. Why not
the other way round ? so that severityA < severityB would do what you
(or at least I) would expect?
syslog defines 0 (LOG_EMERG) as the strongest and 7 (LOG_DEBUG) as the weakest.
The greater the number, the more logging output, you're going to see. So, he's
following syslog in that respect, though he doesn't have as many log levels.
He should probably add at least debug. He also aliases them to module-level
symbols for some reason, which is a big no-no IMHO.

- Jonathan M Davis
Andrej Mitrovic
2012-02-13 19:06:03 UTC
Permalink
I'd like to see a simple example of how to specify the filename of the log file.
Jose Armando Garcia
2012-02-14 02:24:32 UTC
Permalink
On Mon, Feb 13, 2012 at 5:06 PM, Andrej Mitrovic
Post by Andrej Mitrovic
I'd like to see a simple example of how to specify the filename of the log file.
Fair enough...
Jose Armando Garcia
2012-02-14 01:58:38 UTC
Permalink
Post by Jonathan M Davis
Post by David Nadlinger
You define the Severity enum members starting with fatal as 0. Why not
the other way round ? so that severityA < severityB would do what you
(or at least I) would expect?
syslog defines 0 (LOG_EMERG) as the strongest and 7 (LOG_DEBUG) as the weakest.
The greater the number, the more logging output, you're going to see. So, he's
following syslog in that respect, though he doesn't have as many log levels.
He should probably add at least debug. He also aliases them to module-level
symbols for some reason, which is a big no-no IMHO.
I am trying to minimize the number of predefined log levels. One of
the big problems I see with having too many log levels is that the
programmer never knows which one to use. I think std.log makes this
very clear:

1. Log at fatal if you want the application to assert
2. Log at critical if you want the thread to throw
3. Log at error if you detect a programming bug (invariant violation)
but you wish to continue and cross your finger
4. Log at warning if you detected peculiar condition yet the program
was coded to handle it.
5. Log at info if you want to document an action/state.
6. verbose log for trace/debugging specific parts of a program.

I think it would help me that instead of suggesting another level we
instead state what we think the user would like to do or log but the
framework as defined doesn't let the user do.

Thanks,
-Jose
Post by Jonathan M Davis
- Jonathan M Davis
Jonathan M Davis
2012-02-14 02:02:06 UTC
Permalink
Post by Jose Armando Garcia
Post by Jonathan M Davis
Post by David Nadlinger
You define the Severity enum members starting with fatal as 0. Why not
the other way round ? so that severityA < severityB would do what you
(or at least I) would expect?
syslog defines 0 (LOG_EMERG) as the strongest and 7 (LOG_DEBUG) as the
weakest. The greater the number, the more logging output, you're going
to see. So, he's following syslog in that respect, though he doesn't
have as many log levels. He should probably add at least debug. He also
aliases them to module-level symbols for some reason, which is a big
no-no IMHO.
I am trying to minimize the number of predefined log levels. One of
the big problems I see with having too many log levels is that the
programmer never knows which one to use. I think std.log makes this
1. Log at fatal if you want the application to assert
2. Log at critical if you want the thread to throw
3. Log at error if you detect a programming bug (invariant violation)
but you wish to continue and cross your finger
4. Log at warning if you detected peculiar condition yet the program
was coded to handle it.
5. Log at info if you want to document an action/state.
6. verbose log for trace/debugging specific parts of a program.
I think it would help me that instead of suggesting another level we
instead state what we think the user would like to do or log but the
framework as defined doesn't let the user do.
Personally, I'd just copy what syslog does in terms of log levels. Then
std.log can use syslog and everything maps wonderfully.

- Jonathan M Davis
Jose Armando Garcia
2012-02-14 03:16:29 UTC
Permalink
Post by Jonathan M Davis
On Mon, Feb 13, 2012 at 4:19 PM, Jonathan M Davis <jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by David Nadlinger
You define the Severity enum members starting with fatal as 0. Why not
the other way round ? so that severityA < severityB would do what you
(or at least I) would expect?
syslog defines 0 (LOG_EMERG) as the strongest and 7 (LOG_DEBUG) as the
weakest. The greater the number, the more logging output, you're going
to see. So, he's following syslog in that respect, though he doesn't
have as many log levels. He should probably add at least debug. He also
aliases them to module-level symbols for some reason, which is a big
no-no IMHO.
I am trying to minimize the number of predefined log levels. One of
the big problems I see with having too many log levels is that the
programmer never knows which one to use. I think std.log makes this
1. Log at fatal if you want the application to assert
2. Log at critical if you want the thread to throw
3. Log at error if you detect a programming bug (invariant violation)
but you wish to continue and cross your finger
4. Log at warning if you detected peculiar condition yet the program
was coded to handle it.
5. Log at info if you want to document an action/state.
6. verbose log for trace/debugging specific parts of a program.
I think it would help me that instead of suggesting another level we
instead state what we think the user would like to do or log but the
framework as defined doesn't let the user do.
Personally, I'd just copy what syslog does in terms of log levels. Then
std.log can use syslog and everything maps wonderfully.
Do you think that our users will really want to send "debug" message
to syslog? Either way I don't think that is a reason to add debug
level. If we used the common denominator to determine the set of
features that set would be quite large. The implementation of the
Logger interface can do its best to map the severity from std.log to
something syslog likes.

This is exactly what SLF4J does with Log4J, java.util.logger, syslog, etc.
Post by Jonathan M Davis
- Jonathan M Davis
Jonathan M Davis
2012-02-14 03:22:54 UTC
Permalink
Post by Jose Armando Garcia
Post by Jonathan M Davis
On Mon, Feb 13, 2012 at 4:19 PM, Jonathan M Davis <jmdavisProg at gmx.com>
Post by Jonathan M Davis
Post by David Nadlinger
You define the Severity enum members starting with fatal as 0. Why not
the other way round ? so that severityA < severityB would do what you
(or at least I) would expect?
syslog defines 0 (LOG_EMERG) as the strongest and 7 (LOG_DEBUG) as the
weakest. The greater the number, the more logging output, you're going
to see. So, he's following syslog in that respect, though he doesn't
have as many log levels. He should probably add at least debug. He also
aliases them to module-level symbols for some reason, which is a big
no-no IMHO.
I am trying to minimize the number of predefined log levels. One of
the big problems I see with having too many log levels is that the
programmer never knows which one to use. I think std.log makes this
1. Log at fatal if you want the application to assert
2. Log at critical if you want the thread to throw
3. Log at error if you detect a programming bug (invariant violation)
but you wish to continue and cross your finger
4. Log at warning if you detected peculiar condition yet the program
was coded to handle it.
5. Log at info if you want to document an action/state.
6. verbose log for trace/debugging specific parts of a program.
I think it would help me that instead of suggesting another level we
instead state what we think the user would like to do or log but the
framework as defined doesn't let the user do.
Personally, I'd just copy what syslog does in terms of log levels. Then
std.log can use syslog and everything maps wonderfully.
Do you think that our users will really want to send "debug" message
to syslog? Either way I don't think that is a reason to add debug
level. If we used the common denominator to determine the set of
features that set would be quite large. The implementation of the
Logger interface can do its best to map the severity from std.log to
something syslog likes.
This is exactly what SLF4J does with Log4J, java.util.logger, syslog, etc.
Where I work, we log debug messages to syslog all the time when the product is
under development. It's incredibly useful. And on Linux, syslog is _the_
logging facility. It's where all log messages should go. Then syslog can be
configured to split up log files per program or log level or whatever else you
want to do on that particular system. But regardless, all logging goes to
syslog. That's what it's for.

- Jonathan M Davis
Johannes Pfau
2012-02-14 09:16:15 UTC
Permalink
Am Mon, 13 Feb 2012 19:22:54 -0800
Post by Jonathan M Davis
Where I work, we log debug messages to syslog all the time when the
product is under development. It's incredibly useful. And on Linux,
syslog is _the_ logging facility.
Right now. But once systemd took over the world:
https://docs.google.com/document/pub?id=1IC9yOXj7j6cdLLxWEBAGRL6wl97tFxgjLUEHIX3MSTs&pli=1
HeiHon
2012-02-16 11:42:55 UTC
Permalink
On Tuesday, 14 February 2012 at 01:58:50 UTC, Jose Armando Garcia
Post by Jose Armando Garcia
I am trying to minimize the number of predefined log levels.
One of
the big problems I see with having too many log levels is that
the
programmer never knows which one to use. I think std.log makes
this
1. Log at fatal if you want the application to assert
2. Log at critical if you want the thread to throw
3. Log at error if you detect a programming bug (invariant
violation)
but you wish to continue and cross your finger
4. Log at warning if you detected peculiar condition yet the
program
was coded to handle it.
5. Log at info if you want to document an action/state.
6. verbose log for trace/debugging specific parts of a program.
I think it would help me that instead of suggesting another
level we
instead state what we think the user would like to do or log
but the
framework as defined doesn't let the user do.
In my applications I want my logs to be human readable by users
and/or admins.
I tend to have different kinds of what you call warnings.

Say my app uploads a file by FTP. It would be something like:

info("sending file to host")
and then
case a:
info("file sent successfully - took time x")

case b:
warning("encountered some FTP problems") info("file sent
successfully - took time x")

case c:
warning("encountered severe FTP problems - could not send file")

The program can handle all three cases.
But I want to clearly communicate to the user the different
severity of the problems the program handled. BTW I normally call
case c "error" (from the users perspective).
Jose Armando Garcia
2012-02-14 01:47:50 UTC
Permalink
Post by David Nadlinger
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
?- potion -> position
?- enviroment -> environment
?- arguements -> arguments
?- explictly -> explicitly
?- fileter -> filter
?- persiste -> persist
?- genereated -> generated
?- brakets -> brackets
?- paramater -> parameter
?- compuration -> computation
Thanks. I cleaned this up. I'll pass the rest through a spellchecker.
?- In the first paragraph, every sentence starts with ?The module?
?- disabled/enabled -> disable/enable
?- ?In the other? -> ?in the order?
I fix it some what. Still not a big fan of the current introductory
section. My current thinking for introductory section is to write
something small that every developer should read. Probably something
example driven. If they need details into how to configure the module
then they can read the rest of the document. Thoughts?
You define the Severity enum members starting with fatal as 0. Why not the
other way round ? so that severityA < severityB would do what you (or at
least I) would expect?
Internally I wanted to use the same representation for severity as I
would use for verbosity. I wanted 0 to represent the highest
importance and increasing numbers to have lower severity/importance.
This would allow users freely pick lower and lower verbose message as
they develop their application without having to worry how the
application is configured in the deployment/production environment.
Include a cross-reference to log() in the Severity comment?
Done
Maybe clarify the meaning of ?can be logged? (i.e. the severity level is not
completely disabled) in the LogFilter docs?
Thanks. This part of the document was some what confusing. It should
be a little better now.
Are the explicit to!string calls in the first LogFilter example required?
config.logger: First line is missing a full stop, ?The default value a
FileLogger.?, ?change and configure? (where is the difference?)
No, it is not. Fixed.
?Create a configuration object based on the passed parameter.? is slightly
misleading, because parseCommandLine() doesn't actually create an object.
Good catch. Fixed. I have been thinking of changing the signature of
the Configuration classes to look more like a builder by using the
"with..." pattern in the method signature. Thoughts?
I'll post a more in-depth review later.
David
Thanks a lot. Your comments were helpful.
jdrewsen
2012-02-13 20:44:05 UTC
Permalink
A first quick observation:

I vote for a debug severity level. Then make that default to the
template parameter for log:

template log(Severity severity = Severity.debug)

That would make it nice for good old print debugging.

log("This is a dbg message");

/Jonas
Sean Kelly
2012-02-13 20:47:03 UTC
Permalink
Post by jdrewsen
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
I think that's what vlog is for, it just isn't particularly well documented.
Jose Armando Garcia
2012-02-14 02:26:30 UTC
Permalink
Post by Sean Kelly
Post by jdrewsen
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
I think that's what vlog is for, it just isn't particularly well documented.
I agree. Let me know how I can improve this...
Jose Armando Garcia
2012-02-14 02:28:01 UTC
Permalink
I vote for a debug severity level. Then make that default to the template
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
log("This is a dbg message");
I like the idea of having a default. Not sure about adding debug. What
are you trying to do with default that log!info and vlog(#) doesn't
let you do?
/Jonas
Andrei Alexandrescu
2012-02-14 03:18:44 UTC
Permalink
Post by Jose Armando Garcia
I vote for a debug severity level. Then make that default to the template
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
log("This is a dbg message");
I like the idea of having a default. Not sure about adding debug. What
are you trying to do with default that log!info and vlog(#) doesn't
let you do?
Let's not forget we could always do

debug log(stuff);


Andrei
jdrewsen
2012-02-14 10:42:06 UTC
Permalink
On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando Garcia
On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen <jdrewsen at nospam.com>
Post by jdrewsen
I vote for a debug severity level. Then make that default to
the template
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
log("This is a dbg message");
I like the idea of having a default. Not sure about adding
debug. What
are you trying to do with default that log!info and vlog(#)
doesn't
let you do?
As Sean mentioned the vlog function may be the one I want. Maybe
it is okey not to have a debug severity but then a default on the
vlog level parameter would be nice. That would make quick debug
prints a tad simpler

vlog("This is a dbg message");

I know this is a small thing... but to prevent death by a 1000
cuts.

/Jonas
Jose Armando Garcia
2012-02-14 16:21:30 UTC
Permalink
Post by Jose Armando Garcia
I vote for a debug severity level. Then make that default to the template
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
log("This is a dbg message");
I like the idea of having a default. Not sure about adding debug. What
are you trying to do with default that log!info and vlog(#) doesn't
let you do?
As Sean mentioned the vlog function may be the one I want. Maybe it is okey
not to have a debug severity but then a default on the vlog level parameter
would be nice. That would make quick debug prints a tad simpler
If we do set a default what should it be? It is not clear to me what
value we should pick so if you have any suggestions let me know.
vlog("This is a dbg message");
I know this is a small thing... but to prevent death by a 1000 cuts.
/Jonas
so
2012-02-14 17:48:05 UTC
Permalink
On Tuesday, 14 February 2012 at 16:21:42 UTC, Jose Armando Garcia
On Tue, Feb 14, 2012 at 8:42 AM, jdrewsen <jdrewsen at nospam.com>
Post by jdrewsen
On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando
On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen
Post by jdrewsen
I vote for a debug severity level. Then make that default to
the template
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
log("This is a dbg message");
I like the idea of having a default. Not sure about adding
debug. What
are you trying to do with default that log!info and vlog(#)
doesn't
let you do?
As Sean mentioned the vlog function may be the one I want.
Maybe it is okey
not to have a debug severity but then a default on the vlog
level parameter
would be nice. That would make quick debug prints a tad simpler
If we do set a default what should it be? It is not clear to me
what
value we should pick so if you have any suggestions let me know.
IMO a default severity level is not a good idea, not explicit to
begin with.
As i suggested on another reply, getting rid of the
instantiations solve it.

We lose nothing and gain a common keyword. I used to have
severity levels for my logging library in c++. As soon as i got
the C++0x options i thrashed them all.

Now instead of:

txt(error) << "this is: " << it;

i just got:

error("this is: ", it);

Win win for every aspect of it. And got rid of the keyword "txt".
jdrewsen
2012-02-14 18:33:42 UTC
Permalink
Post by so
On Tuesday, 14 February 2012 at 16:21:42 UTC, Jose Armando
On Tue, Feb 14, 2012 at 8:42 AM, jdrewsen
Post by jdrewsen
On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando
On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen
Post by jdrewsen
I vote for a debug severity level. Then make that default
to the template
template log(Severity severity = Severity.debug)
That would make it nice for good old print debugging.
log("This is a dbg message");
I like the idea of having a default. Not sure about adding
debug. What
are you trying to do with default that log!info and vlog(#)
doesn't
let you do?
As Sean mentioned the vlog function may be the one I want.
Maybe it is okey
not to have a debug severity but then a default on the vlog
level parameter
would be nice. That would make quick debug prints a tad
simpler
If we do set a default what should it be? It is not clear to
me what
value we should pick so if you have any suggestions let me
know.
IMO a default severity level is not a good idea, not explicit
to begin with.
As i suggested on another reply, getting rid of the
instantiations solve it.
We lose nothing and gain a common keyword. I used to have
severity levels for my logging library in c++. As soon as i got
the C++0x options i thrashed them all.
txt(error) << "this is: " << it;
error("this is: ", it);
Win win for every aspect of it. And got rid of the keyword
"txt".
I also like your proposal better. In the end I just want a simple
to type function call syntax or it will be tempting to fallback
to writeln(...).

/Jonas
Sönke Ludwig
2012-02-13 21:17:35 UTC
Permalink
Log levels "debug" and maybe also "trace" would be useful, but I see
that vlog(n)() is meant for that purpose. I would just prefer explicit
names instead of just numbers.

Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the
only overhead would be searching once through the format string in the
case of format placeholders.

A predefined logger for OutputDebugString on Windows would be useful -
or maybe it could be used instead of stdout at least for non-console
applications.

One kind of log writer that I have in my code is one that outputs a
nicely formatted HTML file with built-in JavaScript to be able to filter
messages by priority or module. Maybe this is too much for a standard
library implementation though.

Support for multiple log writers can be useful (e.g. logging to a file +
logging to stdout or to a log control inside of the running
application). Of course, one can also simply write a
"MultiDispatchLogger"...

A format option to log the thread name instead of just the ID.
James Miller
2012-02-13 23:12:16 UTC
Permalink
On 14 February 2012 10:17, S?nke Ludwig
Log levels "debug" and maybe also "trace" would be useful, but I see that
vlog(n)() is meant for that purpose. I would just prefer explicit names
instead of just numbers.
Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the only
overhead would be searching once through the format string in the case of
format placeholders.
A predefined logger for OutputDebugString on Windows would be useful - or
maybe it could be used instead of stdout at least for non-console
applications.
One kind of log writer that I have in my code is one that outputs a nicely
formatted HTML file with built-in JavaScript to be able to filter messages
by priority or module. Maybe this is too much for a standard library
implementation though.
Support for multiple log writers can be useful (e.g. logging to a file +
logging to stdout or to a log control inside of the running application). Of
course, one can also simply write a "MultiDispatchLogger"...
A format option to log the thread name instead of just the ID.
I agree that there needs to be an easy to use format-based logger,
even if its just logf template that calls format on the filter, since
writing `log!(info).format("my string %s", s);` looks bad compared to
`logf!info("my string %s", s);`

Looking through the docs, there needs to be a better indication of
configuration in the primary example, since you don't even mention it,
I thought it might not exist.

A built-in console logger should probably be available, one that
writes to stdout at the very least, since I often need log messages
for debugging, other loggers can be build on top of the Logger
interface, separate from the library, but I imagine that many people
would want a console logger and doing it in the standard library will
prevent too much repeated work. It would also be an idea to make it
the default, but at this point I can't really separate out my
practices from what I think most people do.

A debug-level log would be nice, but I don't really care either way.

A built-in MultiDispatchLogger (or similar) would be nice, but I don't
think it really matters.

Otherwise, I think it all looks good; fairly simple to use and
configure, ability to override the defaults if needed, ability to swap
out backends at runtime. The docs need work, but docs always need work
:P.

It might not mean much, but this gets my approval.

James Miller
Jose Armando Garcia
2012-02-14 02:52:51 UTC
Permalink
Post by James Miller
On 14 February 2012 10:17, S?nke Ludwig
Log levels "debug" and maybe also "trace" would be useful, but I see that
vlog(n)() is meant for that purpose. I would just prefer explicit names
instead of just numbers.
Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the only
overhead would be searching once through the format string in the case of
format placeholders.
A predefined logger for OutputDebugString on Windows would be useful - or
maybe it could be used instead of stdout at least for non-console
applications.
One kind of log writer that I have in my code is one that outputs a nicely
formatted HTML file with built-in JavaScript to be able to filter messages
by priority or module. Maybe this is too much for a standard library
implementation though.
Support for multiple log writers can be useful (e.g. logging to a file +
logging to stdout or to a log control inside of the running application). Of
course, one can also simply write a "MultiDispatchLogger"...
A format option to log the thread name instead of just the ID.
I agree that there needs to be an easy to use format-based logger,
even if its just logf template that calls format on the filter, since
writing `log!(info).format("my string %s", s);` looks bad compared to
`logf!info("my string %s", s);`
Looking through the docs, there needs to be a better indication of
configuration in the primary example, since you don't even mention it,
I thought it might not exist.
At the top of the documentation I wanted information on how to use the
module for the common developer. To me the common developer is going
to write log message not configure the log module/framework.

The user that is going to configure the library can read the whole
document or the Configuration classes.

Thoughts?
Post by James Miller
A built-in console logger should probably be available, one that
writes to stdout at the very least, since I often need log messages
for debugging, other loggers can be build on top of the Logger
interface, separate from the library, but I imagine that many people
would want a console logger and doing it in the standard library will
prevent too much repeated work. It would also be an idea to make it
the default, but at this point I can't really separate out my
practices from what I think most people do.
The default FileLogger can do this. See --logtostderr,
--alsologtostderr and --stderrthreshold.
Post by James Miller
A debug-level log would be nice, but I don't really care either way.
A built-in MultiDispatchLogger (or similar) would be nice, but I don't
think it really matters.
Yeah. We could use a few other loggers. But we should think of this as
a living module. The most important thing I think is that we can make
this future improvements without breaking existing users.
Post by James Miller
Otherwise, I think it all looks good; fairly simple to use and
configure, ability to override the defaults if needed, ability to swap
out backends at runtime. The docs need work, but docs always need work
:P.
It might not mean much, but this gets my approval.
James Miller
Jose Armando Garcia
2012-02-14 02:43:28 UTC
Permalink
On Mon, Feb 13, 2012 at 7:17 PM, S?nke Ludwig
Log levels "debug" and maybe also "trace" would be useful, but I see that
vlog(n)() is meant for that purpose. I would just prefer explicit names
instead of just numbers.
Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the only
overhead would be searching once through the format string in the case of
format placeholders.
No, no reason. I guess making the opCall an alias to format is better.
That means the concatenate call will be:

log!info.write(...)

Not that great looking. Suggestions?
A predefined logger for OutputDebugString on Windows would be useful - or
maybe it could be used instead of stdout at least for non-console
applications.
Never used OutputDebugString. Do you mind sending a patch if std.log
gets commit to phobos? Thanks.
One kind of log writer that I have in my code is one that outputs a nicely
formatted HTML file with built-in JavaScript to be able to filter messages
by priority or module. Maybe this is too much for a standard library
implementation though.
What I would really like is to eventually write a backend logger that
sends the message to elasticsearch. That would make this usable in a
data center environment. For that I first need to extend the
LogMessage class.
Support for multiple log writers can be useful (e.g. logging to a file +
logging to stdout or to a log control inside of the running application). Of
course, one can also simply write a "MultiDispatchLogger"...
FileLogger can write to a set of files and/or stderr.
A format option to log the thread name instead of just the ID.
Good idea.
Jacob Carlborg
2012-02-14 07:44:40 UTC
Permalink
Post by Sönke Ludwig
Log levels "debug" and maybe also "trace" would be useful, but I see
that vlog(n)() is meant for that purpose. I would just prefer explicit
names instead of just numbers.
Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the
only overhead would be searching once through the format string in the
case of format placeholders.
A predefined logger for OutputDebugString on Windows would be useful -
or maybe it could be used instead of stdout at least for non-console
applications.
One kind of log writer that I have in my code is one that outputs a
nicely formatted HTML file with built-in JavaScript to be able to filter
messages by priority or module. Maybe this is too much for a standard
library implementation though.
It would be nice to be able to plug in different formatters.
Post by Sönke Ludwig
Support for multiple log writers can be useful (e.g. logging to a file +
logging to stdout or to a log control inside of the running
application). Of course, one can also simply write a
"MultiDispatchLogger"...
A format option to log the thread name instead of just the ID.
--
/Jacob Carlborg
Jose Armando Garcia
2012-02-14 16:19:52 UTC
Permalink
Post by Jacob Carlborg
Post by Sönke Ludwig
Log levels "debug" and maybe also "trace" would be useful, but I see
that vlog(n)() is meant for that purpose. I would just prefer explicit
names instead of just numbers.
Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the
only overhead would be searching once through the format string in the
case of format placeholders.
A predefined logger for OutputDebugString on Windows would be useful -
or maybe it could be used instead of stdout at least for non-console
applications.
One kind of log writer that I have in my code is one that outputs a
nicely formatted HTML file with built-in JavaScript to be able to filter
messages by priority or module. Maybe this is too much for a standard
library implementation though.
It would be nice to be able to plug in different formatters.
What do you mean by formatter? For example the default Logger
(FileLogger) allow you to specify the format line see
FileLogger.Configuration.lineFormat

If you want to do the HTML stuff S?nke mentioned then you need to
inherit Logger and overwrite config.logger. Mind you that the Logger
API should be view almost like a journaling API and HTML is a document
so the differences need to be reconciled in the implementation of
Logger.

Thanks,
-Jose
Post by Jacob Carlborg
Post by Sönke Ludwig
Support for multiple log writers can be useful (e.g. logging to a file +
logging to stdout or to a log control inside of the running
application). Of course, one can also simply write a
"MultiDispatchLogger"...
A format option to log the thread name instead of just the ID.
--
/Jacob Carlborg
Jacob Carlborg
2012-02-14 19:44:34 UTC
Permalink
Post by Jose Armando Garcia
Post by Jacob Carlborg
Post by Sönke Ludwig
Log levels "debug" and maybe also "trace" would be useful, but I see
that vlog(n)() is meant for that purpose. I would just prefer explicit
names instead of just numbers.
Is there a compelling reason why formatted logging is not the default? I
find that most logging calls in practice use formatted output, and the
only overhead would be searching once through the format string in the
case of format placeholders.
A predefined logger for OutputDebugString on Windows would be useful -
or maybe it could be used instead of stdout at least for non-console
applications.
One kind of log writer that I have in my code is one that outputs a
nicely formatted HTML file with built-in JavaScript to be able to filter
messages by priority or module. Maybe this is too much for a standard
library implementation though.
It would be nice to be able to plug in different formatters.
What do you mean by formatter? For example the default Logger
(FileLogger) allow you to specify the format line see
FileLogger.Configuration.lineFormat
If you want to do the HTML stuff S?nke mentioned then you need to
inherit Logger and overwrite config.logger. Mind you that the Logger
API should be view almost like a journaling API and HTML is a document
so the differences need to be reconciled in the implementation of
Logger.
Yeah, I was referring to something like outputting HTML. Ok, I see.
--
/Jacob Carlborg
so
2012-02-13 23:37:53 UTC
Permalink
On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger
Post by David Nadlinger
There are several modules in the review queue right now, and to
get things going, I have volunteered to manage the review of
Jose's std.log proposal. Barring any objections, the review
period starts now and ends in three weeks, on March 6th,
followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just
search the NG and ML archives for "std.log".
I think getting this right is vitally important so that we can
avoid an abundance of partly incompatible logging libraries
like in Java. Thus, I'd warmly encourage everyone to actively
try out the module or compare it with any logging solution you
might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments
are very welcome as well!
David
Good work.

One suggestion. Instantiating a template for each log rather
verbose for such common thing. I suggest:

(Just to demonstrate)
alias global_logger!sev_info info;
alias global_logger!sev_warning warning;
alias global_logger!sev_error error;
alias global_logger!sev_critical critical;
alias global_logger!sev_dfatal dfatal;
alias global_logger!sev_fatal fatal;

As we are pulling severity levels to global namespace anyway,
this will save us some verbosity and the keyword "log".
Jose Armando Garcia
2012-02-14 02:55:50 UTC
Permalink
Post by so
There are several modules in the review queue right now, and to get things
going, I have volunteered to manage the review of Jose's std.log proposal.
Barring any objections, the review period starts now and ends in three
weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the
NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus, I'd
warmly encourage everyone to actively try out the module or compare it with
any logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
David
Good work.
One suggestion. Instantiating a template for each log rather verbose for
(Just to demonstrate)
alias global_logger!sev_info info;
alias global_logger!sev_warning warning;
alias global_logger!sev_error error;
alias global_logger!sev_critical critical;
alias global_logger!sev_dfatal dfatal;
alias global_logger!sev_fatal fatal;
As we are pulling severity levels to global namespace anyway, this will save
us some verbosity and the keyword "log".
I like it! I think I tried this before but I thought "compiled time"
instantiation of the templates was not working properly with alias.
Let me try it again and report back...
Jacob Carlborg
2012-02-14 07:47:03 UTC
Permalink
Post by so
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things going, I have volunteered to manage the review of Jose's
std.log proposal. Barring any objections, the review period starts now
and ends in three weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
https://github.com/D-Programming-Language/druntime/pull/141 (will be
part of 2.058)
---
Earlier drafts of this library were discussed last year, just search
the NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid
an abundance of partly incompatible logging libraries like in Java.
Thus, I'd warmly encourage everyone to actively try out the module or
compare it with any logging solution you might already be using in
your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are
very welcome as well!
David
Good work.
One suggestion. Instantiating a template for each log rather verbose for
(Just to demonstrate)
alias global_logger!sev_info info;
alias global_logger!sev_warning warning;
alias global_logger!sev_error error;
alias global_logger!sev_critical critical;
alias global_logger!sev_dfatal dfatal;
alias global_logger!sev_fatal fatal;
As we are pulling severity levels to global namespace anyway, this will
save us some verbosity and the keyword "log".
It would then be possible to use renamed imports to have something like
this:

import log = std.log;

log.info("foo");

Which looks quite nice I think.
--
/Jacob Carlborg
Andrei Alexandrescu
2012-02-14 06:50:49 UTC
Permalink
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
Thanks Jose and David. I made a pass, here are a few thoughts:

* "different verbose level" -> "different verbosity levels"

* "functionality to disabled and enabled" -> "functionality to disable
and enable"

* "enviroment variables, and their meaning see" -> "enviroment variables
and their meaning, see"

* In code example: "Every nine" -> "Write every 9 passes"

* In code example: unbraced try statement is odd. We should use our own
conventions in examples.

* In code example: plant an assert(false, "Never reached") after log!fatal.

* first() and every() are quite useful. I'm thinking of complementing
them with after(). "Once" is first(1).

* "Descripton of the supported severities." -> "Description of supported
severities." (notice the typo too)

* vlog should take uint, not int.

* When passing multiple parameters to log, they must be stringized
automatically. So

log!error("Log an ", to!string(Severity.error), " message!");

becomes

log!error("Log an ", Severity.error, " message!");

* The examples right inside LogFilter don't mention it at all. I assume
log!xyz has type LogFilter or something. That must be stated in writing.

* log!info.when(first())("Only log this the first time in the loop")
should really be log!info.when(first())("Only log this one time per
application run").

* No examples include durations.

* There might be a better name for Rich.

* assert(value == true); => assert(value);


Andrei
Jose Armando Garcia
2012-02-14 15:58:11 UTC
Permalink
On Tue, Feb 14, 2012 at 4:50 AM, Andrei Alexandrescu
Post by Andrei Alexandrescu
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
* "different verbose level" -> "different verbosity levels"
* "functionality to disabled and enabled" -> "functionality to disable and
enable"
* "enviroment variables, and their meaning see" -> "enviroment variables and
their meaning, see"
* In code example: "Every nine" -> "Write every 9 passes"
* In code example: unbraced try statement is odd. We should use our own
conventions in examples.
* In code example: plant an assert(false, "Never reached") after log!fatal.
Fixed all of the above comments.
Post by Andrei Alexandrescu
* first() and every() are quite useful. I'm thinking of complementing them
with after(). "Once" is first(1).
We do have after(). It should be the second to last document block in
std_log.html. Yep, "Once is first(1) or just first() as the default
value for first is 1. The rest (every and after) don't have default
values because I couldn't find one that made sense to me.
Post by Andrei Alexandrescu
* "Descripton of the supported severities." -> "Description of supported
severities." (notice the typo too)
Fixed.
Post by Andrei Alexandrescu
* vlog should take uint, not int.
There is a subtle reason why I decided to use int and not unit. I
suspect that most user will use non-negative values when using vlog.
They will probably start by using either vlog(0) and/or vlog(1).

To enable vlog(0) and vlog(1) they need to config.maxVerboseLevel(1),
config.maxVerboseLevel(2), etc. To enable vlog(0) and disable vlog(1)
they need to config.maxVerboseLevel(0). What if they want to disable
vlog(0)? They can't if we use uint. By using int instead of uint they
can always specify -1. Now, you can say that you can apply the same
logic to int.min. They will never be able to disable vlog(int.min). My
argument is that most user will not log using vlog(int.min) and the
ones that do are very familiar with the implementation and are aware
of the consequences. Thoughts?
Post by Andrei Alexandrescu
* When passing multiple parameters to log, they must be stringized
automatically. So
log!error("Log an ", to!string(Severity.error), " message!");
becomes
log!error("Log an ", Severity.error, " message!");
Fixed.
Post by Andrei Alexandrescu
* The examples right inside LogFilter don't mention it at all. I assume
log!xyz has type LogFilter or something. That must be stated in writing.
Yes, but technically "template log" can either alias to LogFilter or
NoopLogFilter (used for compiled time disabling). But yes they have
structurally the same set of public methods.

Fixed.
Post by Andrei Alexandrescu
* log!info.when(first())("Only log this the first time in the loop") should
really be log!info.when(first())("Only log this one time per application
run").
It is actually per thread run. Change it to:
info.when(first())("Only log this one time per thread run")
Post by Andrei Alexandrescu
* No examples include durations.
Not sure it if help but a copied the unittest for duration. I should
be readable.
Post by Andrei Alexandrescu
* There might be a better name for Rich.
Suggestions?
Post by Andrei Alexandrescu
* assert(value == true); => assert(value);
Fixed.

Thanks!
-Jose
Post by Andrei Alexandrescu
Andrei
jdrewsen
2012-02-14 10:59:42 UTC
Permalink
On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger
Post by David Nadlinger
There are several modules in the review queue right now, and to
get things going, I have volunteered to manage the review of
Jose's std.log proposal. Barring any objections, the review
period starts now and ends in three weeks, on March 6th,
followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just
search the NG and ML archives for "std.log".
I think getting this right is vitally important so that we can
avoid an abundance of partly incompatible logging libraries
like in Java. Thus, I'd warmly encourage everyone to actively
try out the module or compare it with any logging solution you
might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments
are very welcome as well!
David
Updated wiki: http://prowiki.org/wiki4d/wiki.cgi?ReviewQueue

/Jonas
Jacob Carlborg
2012-02-14 13:14:33 UTC
Permalink
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things going, I have volunteered to manage the review of Jose's std.log
proposal. Barring any objections, the review period starts now and ends
in three weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the
NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus,
I'd warmly encourage everyone to actively try out the module or compare
it with any logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
David
Is it possible to log to other locations, i.e. to the standard location
for the given platform.
--
/Jacob Carlborg
David Nadlinger
2012-02-14 13:24:27 UTC
Permalink
Post by Jacob Carlborg
Is it possible to log to other locations, i.e. to the standard location
for the given platform.
While the current proposal only includes a file backend, my
understanding is that this could easily be added by providing an
appropriate implementation of the Logger interface. Generally useful
implementations (e.g. syslog, ?) would probably be a good candidate for
inclusion into Phobos.

David
Jacob Carlborg
2012-02-14 14:12:11 UTC
Permalink
Post by David Nadlinger
Post by Jacob Carlborg
Is it possible to log to other locations, i.e. to the standard location
for the given platform.
While the current proposal only includes a file backend, my
understanding is that this could easily be added by providing an
appropriate implementation of the Logger interface. Generally useful
implementations (e.g. syslog, ?) would probably be a good candidate for
inclusion into Phobos.
David
Ok, I see. I don't think it would be necessary with different backends,
as long as there's an interface available, at least not at the first stage.
--
/Jacob Carlborg
Jose Armando Garcia
2012-02-14 16:27:08 UTC
Permalink
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things going, I have volunteered to manage the review of Jose's std.log
proposal. Barring any objections, the review period starts now and ends
in three weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the
NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus,
I'd warmly encourage everyone to actively try out the module or compare
it with any logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
David
Is it possible to log to other locations, i.e. to the standard location for
the given platform.
What do you mean by location? If you mean file system directory then:
@property string logDirectory(string logDirectory);
const const @property string logDirectory();
Specifies the directory where log files are created.

The default value for this property is the value in the
environment variable LOGDIR. If LOGDIR is not set, then TEST_TMPDIR is
used. If TEST_TMPDIR is not set, then it logs to the current
directory.

If you mean file name, you have 'fileNamePrefixes' and 'fileNameExtension'.

If you mean syslog then for now the user needs to implement this but I
foresee us implementing this in phobos in the near future.

Thanks,
-Jose
--
/Jacob Carlborg
Jacob Carlborg
2012-02-14 19:47:18 UTC
Permalink
Post by Jose Armando Garcia
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things going, I have volunteered to manage the review of Jose's std.log
proposal. Barring any objections, the review period starts now and ends
in three weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the
NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus,
I'd warmly encourage everyone to actively try out the module or compare
it with any logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
David
Is it possible to log to other locations, i.e. to the standard location for
the given platform.
@property string logDirectory(string logDirectory);
Specifies the directory where log files are created.
The default value for this property is the value in the
environment variable LOGDIR. If LOGDIR is not set, then TEST_TMPDIR is
used. If TEST_TMPDIR is not set, then it logs to the current
directory.
If you mean file name, you have 'fileNamePrefixes' and 'fileNameExtension'.
If you mean syslog then for now the user needs to implement this but I
foresee us implementing this in phobos in the near future.
I meant something like a general interface one could implement to be
able to log to basically anywhere, not only files. Say that I would want
to output the log in a window in a GUI application, for example.
--
/Jacob Carlborg
Jose Armando Garcia
2012-02-14 16:12:44 UTC
Permalink
There are several modules in the review queue right now, and to get things
going, I have volunteered to manage the review of Jose's std.log proposal.
Barring any objections, the review period starts now and ends in three
weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
Updated the document an implementation to reflect every suggest for I
replied to with the exception of providing a format parameter for
thread name. Should have that ready later today. Let me know if I
missed anything. API changes:

1. Dropped log!info("message"), etc. Use info("message), etc.
2. opCall now alias to format. Ie. info("Format %s message", Severity.info).
this means that to concatenate strings you need to
info.write("Hello ", "world");
?- Proof-reading of the docs is required.
?- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the NG
and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus, I'd
warmly encourage everyone to actively try out the module or compare it with
any logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
David
Jose Armando Garcia
2012-02-14 17:03:26 UTC
Permalink
There are several modules in the review queue right now, and to get things
going, I have volunteered to manage the review of Jose's std.log proposal.
Barring any objections, the review period starts now and ends in three
weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
It is better if we use this:
https://github.com/D-Programming-Language/phobos/pull/432/files
That link will stay up to date as I make changes to the code.
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
?- Proof-reading of the docs is required.
?- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the NG
and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an
abundance of partly incompatible logging libraries like in Java. Thus, I'd
warmly encourage everyone to actively try out the module or compare it with
any logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
David
jdrewsen
2012-02-14 18:44:58 UTC
Permalink
On Tuesday, 14 February 2012 at 16:12:57 UTC, Jose Armando Garcia
On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger
Post by David Nadlinger
There are several modules in the review queue right now, and
to get things
going, I have volunteered to manage the review of Jose's
std.log proposal.
Barring any objections, the review period starts now and ends
in three
weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std log.html
Updated the document an implementation to reflect every suggest
for I
replied to with the exception of providing a format parameter
for
thread name. Should have that ready later today. Let me know if
I
1. Dropped log!info("message"), etc. Use info("message), etc.
2. opCall now alias to format. Ie. info("Format %s message",
Severity.info).
this means that to concatenate strings you need to
info.write("Hello ", "world");
In the introduction text the references to Configuration etc.
should be made into links.

/Jonas
Jose Armando Garcia
2012-02-14 18:51:10 UTC
Permalink
On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger <see at klickverbot.at>
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things
going, I have volunteered to manage the review of Jose's std.log
proposal.
Barring any objections, the review period starts now and ends in three
weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std log.html
Updated the document an implementation to reflect every suggest for I
replied to with the exception of providing a format parameter for
thread name. Should have that ready later today. Let me know if I
1. Dropped log!info("message"), etc. Use info("message), etc.
2. opCall now alias to format. Ie. info("Format %s message",
Severity.info).
?this means that to concatenate strings you need to
info.write("Hello ", "world");
In the introduction text the references to Configuration etc. should be made
into links.
I would love to do that. How do you do that with ddoc?
/Jonas
jdrewsen
2012-02-14 19:10:47 UTC
Permalink
On Tuesday, 14 February 2012 at 18:51:20 UTC, Jose Armando Garcia
On Tue, Feb 14, 2012 at 4:44 PM, jdrewsen <jdrewsen at nospam.com>
Post by jdrewsen
On Tuesday, 14 February 2012 at 16:12:57 UTC, Jose Armando
On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger
<see at klickverbot.at>
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things
going, I have volunteered to manage the review of Jose's
std.log
proposal.
Barring any objections, the review period starts now and
ends in three
weeks, on March 6th, followed by a week of voting.
---
https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std log.html
Updated the document an implementation to reflect every
suggest for I
replied to with the exception of providing a format parameter
for
thread name. Should have that ready later today. Let me know
if I
1. Dropped log!info("message"), etc. Use info("message), etc.
2. opCall now alias to format. Ie. info("Format %s message",
Severity.info).
?this means that to concatenate strings you need to
info.write("Hello ", "world");
In the introduction text the references to Configuration etc.
should be made
into links.
I would love to do that. How do you do that with ddoc?
For example: $(LREF Configuration)

The LREF macro is defined in
https://github.com/D-Programming-Language/d-programming-language.org/blob/master/std.ddoc#L293
along with other useful macros.

/Jonas
bls
2012-02-13 04:58:54 UTC
Permalink
Post by David Nadlinger
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141
(will be part of 2.058)
This is somehow bad. Review a piece of library-software by using a beta
compiler and beta-library.
so
2012-02-15 12:02:43 UTC
Permalink
Post by bls
This is somehow bad. Review a piece of library-software by
using a beta compiler and beta-library.
Indeed, never happened such thing in whole compiler/language
development history.
David Nadlinger
2012-02-15 13:36:35 UTC
Permalink
Post by bls
This is somehow bad. Review a piece of library-software by
using a beta compiler and beta-library.
I don't quite see where the problem is with that. Besides, 2.058
is already out now (and was scheduled to be released on Feb 13).

David
Jonathan M Davis
2012-02-16 09:21:37 UTC
Permalink
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
Why does vlog even exist? It's a needless complication IMHO. Let the log
levels manage what does and doesn't get logged. I see no reason to add the
concept of verbosity on top of that. It's a needless complication.

Also, _please_ add a debug level. Personally, I'd argue for simply copying
syslog's levels and matching them, since ideally any logging on Linux would be
going to syslog anyway. But there are good reasons to have messages beyond
info. I sure wouldn't want _all_ messages which don't indicate a problem in
the app to be marked as info. For instance, what if I want to have info
displayed in release mode but want greater verbosity in debug mode? I'd need
another log level which isn't there. Using the concept of verbosity to try and
handle this is a needless complication. syslog has

#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */

And I'd like to at least see notice and debug added.

While we're at it, what's the point of dfatal? Why on earth would a _fatal_
condition not be fatal if it were in release mode if it were fatal in debug
mode? Is it fatal or not? It seems to me like another needless complication.

If you're going to have write, then have writef, not format. Then it's
actually consistent with our normal I/O functions. Also, do writef and format
automatically append a newline? If so, then they should be writeln and
writefln.

Rich is a horrible name IMHO. It says nothing about what it actually is or
does. I'm not sure what a good name would be (BoolMessage?, LogResult?), but
Rich by itself is very confusing and utterly uninformative.

And why does Configuration's logger property throw if you set it after a
logging call has been made. Is it really that inconceivable that someone would
swap out loggers at runtime? Or is the idea that you'd swap out the
Configuration?

- Jonathan M Davis
Jose Armando Garcia
2012-02-17 17:53:06 UTC
Permalink
Post by Jonathan M Davis
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
Why does vlog even exist? It's a needless complication IMHO. Let the log
levels manage what does and doesn't get logged. I see no reason to add the
concept of verbosity on top of that. It's a needless complication.
Needless? Man, you really make some "strange" comments. I believe that
this is better served by you asking for the motivation for vlog
instead of make a useless comment like the one above. The reason why
vlog exist is to provide users with the ability to enable/disable
logging at a package or module level. Lets say that for a particular
load you are seeing that module X is not behaving correctly. The next
time you run your application (or you can do this at runtime if you
have coded your application correctly) you can enable verbose logging
in this module by using the --v and --vmodule command line options. I
have tried to explain this in the properties
Configuration.maxVerboseLevel and Configuration.verboseFilter. Let me
know if it still no clear and if I should expand the documentation.
Post by Jonathan M Davis
Also, _please_ add a debug level. Personally, I'd argue for simply copying
syslog's levels and matching them, since ideally any logging on Linux would be
going to syslog anyway. But there are good reasons to have messages beyond
info. I sure wouldn't want _all_ messages which don't indicate a problem in
the app to be marked as info. For instance, what if I want to have info
displayed in release mode but want greater verbosity in debug mode?
debug info("More information in debug mode");

I think it is very helpful that instead of just suggestion more level
we try to see how we can use this module and the power of D to do what
you want. If we find that it is not possible or clunky then we can
talk about adding more functionality.
Post by Jonathan M Davis
I'd need
another log level which isn't there. Using the concept of verbosity to try and
handle this is a needless complication. syslog has
#define LOG_EMERG ? ? ? 0 ? ? ? /* system is unusable */
#define LOG_ALERT ? ? ? 1 ? ? ? /* action must be taken immediately */
#define LOG_CRIT ? ? ? ?2 ? ? ? /* critical conditions */
#define LOG_ERR ? ? ? ? 3 ? ? ? /* error conditions */
#define LOG_WARNING ? ? 4 ? ? ? /* warning conditions */
#define LOG_NOTICE ? ? ?5 ? ? ? /* normal but significant condition */
#define LOG_INFO ? ? ? ?6 ? ? ? /* informational */
#define LOG_DEBUG ? ? ? 7 ? ? ? /* debug-level messages */
And I'd like to at least see notice and debug added.
While we're at it, what's the point of dfatal? Why on earth would a _fatal_
condition not be fatal if it were in release mode if it were fatal in debug
mode? Is it fatal or not? It seems to me like another needless complication.
Barely a complication. dfatal looks as follow:

debug alias log!(Severity.fatal) dfatal; /// ditto
else alias log!(Severity.critical) dfatal; /// ditto
Post by Jonathan M Davis
If you're going to have write, then have writef, not format. Then it's
actually consistent with our normal I/O functions.
Good suggestion. Will do.
Post by Jonathan M Davis
Also, do writef and format
automatically append a newline? If so, then they should be writeln and
writefln.
Technically, no. The module was abstracted with a frontend and a
backend. At a very high-level the front does filtering based on
compile time and run time configuration options. The backend is
basically responsible for persisting messages. It just happens that
the only backend implementation that we have writes to a human
consumable file hence the newline but it is possible that users are
going to want to store this data in persistent storage where each
logging event is not separated by a newline.
Post by Jonathan M Davis
Rich is a horrible name IMHO. It says nothing about what it actually is or
does. I'm not sure what a good name would be (BoolMessage?, LogResult?), but
Rich by itself is very confusing and utterly uninformative.
Yeah. I don't like Rich. Let me think about a better name. Thanks for
the suggestions!
Post by Jonathan M Davis
And why does Configuration's logger property throw if you set it after a
logging call has been made. Is it really that inconceivable that someone would
swap out loggers at runtime? Or is the idea that you'd swap out the
Configuration?
The idea is not to swap out the Configuration but to instead be able
to reset each property. There is no technical reason why you can't
replace the Logger. I just didn't think this is something the users
would want to do in practice. Again this goes beyond technical reason
is more of the operational consequence if you allow this. For example:

1. You started logging to /tmp/application/...log...
2. You swapped the logger at runtime to start logging to syslog

You have a bunch of important data in /tmp/application/...log... what
are you going to do with it? Think of this like a stream flowing into
a lake and at some point you want to route the stream to the ocean.
What is the state of the lake after the routing change?

I would also like to add that this is a restriction that we can remove
in the future. I am honestly a little hesitant to remove it now
without giving it a little bit of more thought. Thoughts?

Thanks!
-Jose
Post by Jonathan M Davis
- Jonathan M Davis
Sönke Ludwig
2012-02-16 09:57:11 UTC
Permalink
Post by Jonathan M Davis
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
Why does vlog even exist? It's a needless complication IMHO. Let the log
levels manage what does and doesn't get logged. I see no reason to add the
concept of verbosity on top of that. It's a needless complication.
Also, _please_ add a debug level. Personally, I'd argue for simply copying
syslog's levels and matching them, since ideally any logging on Linux would be
going to syslog anyway. But there are good reasons to have messages beyond
info. I sure wouldn't want _all_ messages which don't indicate a problem in
the app to be marked as info. For instance, what if I want to have info
displayed in release mode but want greater verbosity in debug mode? I'd need
another log level which isn't there. Using the concept of verbosity to try and
handle this is a needless complication. syslog has
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
And I'd like to at least see notice and debug added.
Well in addition to Debug I would also like to see Trace but it's f. ex.
hard for me to tell the difference between Info and Notice and their
names do not imply that certain severity order IMO. So I see a point in
the argument that vlog() allows everyone to be happy without endless
numbers of predefined log levels.. however I'm also not quite convinced.
Post by Jonathan M Davis
While we're at it, what's the point of dfatal? Why on earth would a _fatal_
condition not be fatal if it were in release mode if it were fatal in debug
mode? Is it fatal or not? It seems to me like another needless complication.
If you're going to have write, then have writef, not format. Then it's
actually consistent with our normal I/O functions. Also, do writef and format
automatically append a newline? If so, then they should be writeln and
writefln.
I think the names should be as short as possible for the common 99%
case. As this is not a general purpose stream, I think it is fine to
drop the 'ln'. And the current version that defines info("") as the
version that can format and info.write("") as the plain string version
seems to be quite optimal in this regard.

In my optinion, more descriptive names would just impair readability
here instead of helping. They will be written endless number of times
but do not influence the program flow and should immediately
understandable by anyone who sees them. But something like
log.warn/logf.warn or log.warn/log.warnf might also work if you really
want the consistency...
Post by Jonathan M Davis
Rich is a horrible name IMHO. It says nothing about what it actually is or
does. I'm not sure what a good name would be (BoolMessage?, LogResult?), but
Rich by itself is very confusing and utterly uninformative.
And why does Configuration's logger property throw if you set it after a
logging call has been made. Is it really that inconceivable that someone would
swap out loggers at runtime? Or is the idea that you'd swap out the
Configuration?
- Jonathan M Davis
Jacob Carlborg
2012-02-16 12:15:40 UTC
Permalink
Post by Sönke Ludwig
Post by Jonathan M Davis
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
Why does vlog even exist? It's a needless complication IMHO. Let the log
levels manage what does and doesn't get logged. I see no reason to add the
concept of verbosity on top of that. It's a needless complication.
Also, _please_ add a debug level. Personally, I'd argue for simply copying
syslog's levels and matching them, since ideally any logging on Linux would be
going to syslog anyway. But there are good reasons to have messages beyond
info. I sure wouldn't want _all_ messages which don't indicate a problem in
the app to be marked as info. For instance, what if I want to have info
displayed in release mode but want greater verbosity in debug mode? I'd need
another log level which isn't there. Using the concept of verbosity to try and
handle this is a needless complication. syslog has
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
And I'd like to at least see notice and debug added.
Well in addition to Debug I would also like to see Trace but it's f. ex.
hard for me to tell the difference between Info and Notice and their
names do not imply that certain severity order IMO. So I see a point in
the argument that vlog() allows everyone to be happy without endless
numbers of predefined log levels.. however I'm also not quite convinced.
I think this is way too many levels. Why not just define few levels
(around three) and let the user define new levels when needed.
--
/Jacob Carlborg
Jonathan Stephens
2012-02-17 01:49:41 UTC
Permalink
I think this is way too many levels. Why not just define few levels (around three) and let the user define new levels when needed.
I agree this is too many level, though I think letting the user define
their own levels is a needless complication.
- CRIT - the application cannot continue
- ERROR - the application cannot carry out the requested task
- WARN - the requested task cannot be completed normally, but we can
work around it
- INFO - FYI. Things sysadmins would like to know.
- DEBUG - For developers debugging.
- TRACE (maybe) - also sometimes called fine or verbose - for
developers debugging.

If an application needs separate channels of logging, I would using a
separate logger instance for different logging categories.
H. S. Teoh
2012-02-17 06:41:06 UTC
Permalink
Post by Jonathan Stephens
Post by Jacob Carlborg
I think this is way too many levels. Why not just define few levels
(around three) and let the user define new levels when needed.
I agree this is too many level, though I think letting the user define
their own levels is a needless complication.
- CRIT - the application cannot continue
- ERROR - the application cannot carry out the requested task
- WARN - the requested task cannot be completed normally, but we can
work around it
- INFO - FYI. Things sysadmins would like to know.
- DEBUG - For developers debugging.
- TRACE (maybe) - also sometimes called fine or verbose - for
developers debugging.
[...]
Post by Jonathan Stephens
From my experience, such a proliferation of log levels is rarely used
correctly. Most people, sadly to say, can't be bothered to read the
definitions of what each level is supposed to be, and will just
copy-n-paste the first instance they find. Of course, copying CRIT or
ERROR will quickly get a high-priority bug filed against it, but besides
CRIT and ERROR, the rest of the levels are rarely used properly.

I've seen people use WARN just because they think it's appropriate for
"warning" the developer that a certain condition has happened that might
trigger the bug they're hunting for. Then afterwards they forget to turn
that off, and the log fills up with irrelevant messages.

Similarly, INFO tends to be interpreted as "garbage dump for anything I
might want to know while writing this code, who cares what happens to
those messages afterwards". DEBUG and TRACE are rarely ever used after 4
or 5 developers have had their hands on it, because turning those on
will usually flood the logs with reams and reams of irrelevant messages
from unrelated modules, so most people would stop using it after the
first time.

Bottomline: reduce the number of channels, and let the programmer define
their own channels if they need to. Module-specific channels are the
best, so that you don't get reams of messages from completely unrelated
code. But only the user knows what modules they have, so let them make
that decision.


T
--
Those who don't understand Unix are condemned to reinvent it, poorly.
David Nadlinger
2012-02-18 18:21:54 UTC
Permalink
[?] DEBUG and TRACE are rarely ever used after 4
or 5 developers have had their hands on it, because turning
those on
will usually flood the logs with reams and reams of irrelevant
messages
from unrelated modules, so most people would stop using it
after the
first time.
I think avoiding this problem is one of the major benefits of the
proposed std.log design (because vlog output can be filtered on a
per-module basis).

David
Sönke Ludwig
2012-02-17 10:59:52 UTC
Permalink
Post by Jonathan Stephens
I think this is way too many levels. Why not just define few levels (around three) and let the user define new levels when needed.
I agree this is too many level, though I think letting the user define
their own levels is a needless complication.
- CRIT - the application cannot continue
- ERROR - the application cannot carry out the requested task
- WARN - the requested task cannot be completed normally, but we can
work around it
- INFO - FYI. Things sysadmins would like to know.
- DEBUG - For developers debugging.
- TRACE (maybe) - also sometimes called fine or verbose - for
developers debugging.
Thats also exactly my experience (and what I use).
Jose Armando Garcia
2012-02-17 18:06:01 UTC
Permalink
On Thu, Feb 16, 2012 at 7:57 AM, S?nke Ludwig
Post by Sönke Ludwig
Post by Jonathan M Davis
Post by David Nadlinger
Please post all feedback in this thread, and remember: Although
comprehensive reviews are obviously appreciated, short comments are very
welcome as well!
Why does vlog even exist? It's a needless complication IMHO. Let the log
levels manage what does and doesn't get logged. I see no reason to add the
concept of verbosity on top of that. It's a needless complication.
Also, _please_ add a debug level. Personally, I'd argue for simply copying
syslog's levels and matching them, since ideally any logging on Linux would be
going to syslog anyway. But there are good reasons to have messages beyond
info. I sure wouldn't want _all_ messages which don't indicate a problem in
the app to be marked as info. For instance, what if I want to have info
displayed in release mode but want greater verbosity in debug mode? I'd need
another log level which isn't there. Using the concept of verbosity to try and
handle this is a needless complication. syslog has
#define LOG_EMERG ? ? ? 0 ? ? ? /* system is unusable */
#define LOG_ALERT ? ? ? 1 ? ? ? /* action must be taken immediately */
#define LOG_CRIT ? ? ? ?2 ? ? ? /* critical conditions */
#define LOG_ERR ? ? ? ? 3 ? ? ? /* error conditions */
#define LOG_WARNING ? ? 4 ? ? ? /* warning conditions */
#define LOG_NOTICE ? ? ?5 ? ? ? /* normal but significant condition */
#define LOG_INFO ? ? ? ?6 ? ? ? /* informational */
#define LOG_DEBUG ? ? ? 7 ? ? ? /* debug-level messages */
And I'd like to at least see notice and debug added.
Well in addition to Debug I would also like to see Trace but it's f. ex.
hard for me to tell the difference between Info and Notice and their names
do not imply that certain severity order IMO.
Yes. I would really like to avoid adding more severities because it
complicates the decision the developer needs to make when deciding at
which log level to log. This reminds of a situation that came up at a
previous employer. A bunch of smart people tried to come up with a
policy for deciding at which log level to log a particular message.
Let just say that the discussion lasted days and no decision was made.
I believe that the only reason why this subject even came up at my
previous job is because most logging framework provide hard-coded
levels that don't have any semantic difference between them.
Interesting talk on the subject:
http://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice.html
Post by Sönke Ludwig
So I see a point in the
argument that vlog() allows everyone to be happy without endless numbers of
predefined log levels.. however I'm also not quite convinced.
Post by Jonathan M Davis
While we're at it, what's the point of dfatal? Why on earth would a _fatal_
condition not be fatal if it were in release mode if it were fatal in debug
mode? Is it fatal or not? It seems to me like another needless complication.
If you're going to have write, then have writef, not format. Then it's
actually consistent with our normal I/O functions. Also, do writef and format
automatically append a newline? If so, then they should be writeln and
writefln.
I think the names should be as short as possible for the common 99% case. As
this is not a general purpose stream, I think it is fine to drop the 'ln'.
And the current version that defines info("") as the version that can format
and info.write("") as the plain string version seems to be quite optimal in
this regard.
In my optinion, more descriptive names would just impair readability here
instead of helping. They will be written endless number of times but do not
influence the program flow and should immediately understandable by anyone
who sees them. But something like log.warn/logf.warn or log.warn/log.warnf
might also work if you really want the consistency...
As of right now (or in the immediate future) we have:
info("%s message", Severity.info);
info.write(Severity.info, " message);
info.writef("%s message", Severity.info);

Thanks!
-Jose
Post by Sönke Ludwig
Post by Jonathan M Davis
Rich is a horrible name IMHO. It says nothing about what it actually is or
does. I'm not sure what a good name would be (BoolMessage?, LogResult?), but
Rich by itself is very confusing and utterly uninformative.
And why does Configuration's logger property throw if you set it after a
logging call has been made. Is it really that inconceivable that someone would
swap out loggers at runtime? Or is the idea that you'd swap out the
Configuration?
- Jonathan M Davis
Andrei Alexandrescu
2012-02-17 20:48:57 UTC
Permalink
Post by Jose Armando Garcia
info("%s message", Severity.info);
I think defaulting to formatted stuff may be confusing.

Andrei
Jose Armando Garcia
2012-02-17 21:15:15 UTC
Permalink
On Fri, Feb 17, 2012 at 6:48 PM, Andrei Alexandrescu
Post by Andrei Alexandrescu
Post by Jose Armando Garcia
info("%s message", Severity.info);
I think defaulting to formatted stuff may be confusing.
Even if we document this? I mean:

info("Info message");

Just works. The one place where is wont just work is with:

info("This is an ", Severity.info, " message);

But do we think users will do with this without reading one bit of the
documentation? And even then we can say RTFM ;).

I don't have a strong argument or preference for one over the other.
Post by Andrei Alexandrescu
From my experience I tend to write or log using a format string mainly
because it is more readable to me and plays nicer with localization
frameworks like gettext.

Thoughts?
-Jose
Post by Andrei Alexandrescu
Andrei
Sönke Ludwig
2012-03-03 11:51:11 UTC
Permalink
Post by Andrei Alexandrescu
Post by Jose Armando Garcia
info("%s message", Severity.info);
I think defaulting to formatted stuff may be confusing.
Andrei
Do you often log static messages? In my experience the majority of
logging calls contains dynamic information and using a format string is
the most convenient and readable form (compared to concatenating using
multiple arguments).

An additional infof(), warnf() etc. would be an acceptable alternative,
although not very pretty. But if you'd always have to write
info.format() or something similar, then this would be a real turn-off,
at least for me.
Andrei Alexandrescu
2012-03-03 22:17:06 UTC
Permalink
Post by Sönke Ludwig
Post by Andrei Alexandrescu
Post by Jose Armando Garcia
info("%s message", Severity.info);
I think defaulting to formatted stuff may be confusing.
Andrei
Do you often log static messages? In my experience the majority of
logging calls contains dynamic information and using a format string is
the most convenient and readable form (compared to concatenating using
multiple arguments).
An additional infof(), warnf() etc. would be an acceptable alternative,
although not very pretty. But if you'd always have to write
info.format() or something similar, then this would be a real turn-off,
at least for me.
I think it's fine to default to formatted. Also, it just occurred to me
that we can adjust the formatting primitives to leave any "%"s alone if
there are no matching arguments. Consider:

log.info("100% done!");

This is technically an error, but since D has static knowledge there are
no variadics, it could simply output the string. That's faster, too,
because no validation of the string is necessary.

Thoughts?


Andrei
Dmitry Olshansky
2012-03-04 09:17:10 UTC
Permalink
Post by Andrei Alexandrescu
Post by Sönke Ludwig
Post by Andrei Alexandrescu
Post by Jose Armando Garcia
info("%s message", Severity.info);
I think defaulting to formatted stuff may be confusing.
Andrei
Do you often log static messages? In my experience the majority of
logging calls contains dynamic information and using a format string is
the most convenient and readable form (compared to concatenating using
multiple arguments).
An additional infof(), warnf() etc. would be an acceptable alternative,
although not very pretty. But if you'd always have to write
info.format() or something similar, then this would be a real turn-off,
at least for me.
I think it's fine to default to formatted. Also, it just occurred to me
that we can adjust the formatting primitives to leave any "%"s alone if
log.info("100% done!");
This is technically an error, but since D has static knowledge there are
no variadics, it could simply output the string. That's faster, too,
because no validation of the string is necessary.
Thoughts?
I would say just separate them please. Let it work as writeln/writefln
and nobody is hurt.

With all manner of magic rules the innocent will catch a bullet sooner
or latter. And it's always happens kind of point-blank, when the code is
shipped & forgotten.
Turning on imagination, e.g. for rarely used stuff:
log.warn("100%done for task %s, yet the client timed out", taskName);
--
Dmitry Olshansky
Andrei Alexandrescu
2012-03-04 18:30:42 UTC
Permalink
Post by Dmitry Olshansky
I would say just separate them please. Let it work as writeln/writefln
and nobody is hurt.
With all manner of magic rules the innocent will catch a bullet sooner
or latter. And it's always happens kind of point-blank, when the code is
shipped & forgotten.
log.warn("100%done for task %s, yet the client timed out", taskName);
Yah, agreed. Probably calls with no extra arguments should be safe.

Andrei
Walter Bright
2012-02-17 21:12:41 UTC
Permalink
Please post all feedback in this thread, and remember: Although comprehensive
reviews are obviously appreciated, short comments are very welcome as well!
This is a general comment, not specific to std.log:

All new library submissions need to be reviewed for applicability of:

@safe
const
pure
nothrow

for all user-facing API functions.
Jose Armando Garcia
2012-02-17 21:20:51 UTC
Permalink
On Fri, Feb 17, 2012 at 7:12 PM, Walter Bright
Post by Walter Bright
Please post all feedback in this thread, and remember: Although comprehensive
reviews are obviously appreciated, short comments are very welcome as well!
@safe
const
pure
nothrow
for all user-facing API functions.
Yep. I have been following that thread and your commits. I have a TODO for this.

Thanks.
-Jose
Kalle Svensson
2012-02-27 18:10:14 UTC
Permalink
Since I'm D n00b I'll just post a couple of observations:

* I agree that it is a good idea just to use few log levels.

* I think is it is a misstake not to let formatting of the whole
log message be pluggable (i.e. not the free text message the
programmer writes). If I have created a special RFC5424 formatter
(with MSGID and STRUCTURED-DATA fields set according to the will
of my corporate masters) I want to resuse it in both the
FileLogger and a future TcpLogger without having to use
inheritance. Your "line format" formatter in FileLogger is a good
default formatter though.

///Kalle
Mikael Lindsten
2012-03-01 09:09:28 UTC
Permalink
Post by Kalle Svensson
* I agree that it is a good idea just to use few log levels.
* I think is it is a misstake not to let formatting of the whole
log message be pluggable (i.e. not the free text message the
programmer writes). If I have created a special RFC5424
formatter
(with MSGID and STRUCTURED-DATA fields set according to the will
of my corporate masters) I want to resuse it in both the
FileLogger and a future TcpLogger without having to use
inheritance. Your "line format" formatter in FileLogger is a
good
default formatter though.
I second what Kalle Svensson is saying.

My belief is that when there are many log levels, people don't
use them as intended or only use a subset of them, often a
combination.


/ Mikael
H. S. Teoh
2012-03-01 14:38:57 UTC
Permalink
Post by Mikael Lindsten
Post by Kalle Svensson
* I agree that it is a good idea just to use few log levels.
[...]
Post by Mikael Lindsten
I second what Kalle Svensson is saying.
My belief is that when there are many log levels, people don't use
them as intended or only use a subset of them, often a combination.
[...]

I used to think that the more log levels, the better. But later, based
on what I observe in real-life projects, I see that most people don't
bother trying to figure out what each log level means (they are too lazy
/ busy to read the docs) so they just randomly pick one that "sounds
right" (which usually is equal to "totally wrong"). Let this happen for
a few iterations of the software, and you end up with so many wrong
level messages that the whole log level system basically becomes
useless. This problem gets worse proportionally to the number of people
on the project.


T
--
What's a "hot crossed bun"? An angry rabbit.
Jose Armando Garcia
2012-03-06 17:09:26 UTC
Permalink
Post by H. S. Teoh
Post by Mikael Lindsten
Post by Kalle Svensson
* I agree that it is a good idea just to use few log levels.
[...]
Post by Mikael Lindsten
I second what Kalle Svensson is saying.
My belief is that when there are many log levels, people don't use
them as intended or only use a subset of them, often a combination.
[...]
I used to think that the more log levels, the better. But later, based
on what I observe in real-life projects, I see that most people don't
bother trying to figure out what each log level means (they are too lazy
/ busy to read the docs) so they just randomly pick one that "sounds
right" (which usually is equal to "totally wrong"). Let this happen for
a few iterations of the software, and you end up with so many wrong
level messages that the whole log level system basically becomes
useless. This problem gets worse proportionally to the number of people
on the project.
Agreed. I have recently extended this to hierarchy. Most of the time
you don't want to deal with the complexity of using and configuring a
hierarchical logger. Most programs/system want to enable logging
across the board. From my experience is only in very critical areas
where you want to increase and decrease logging for that component.

An example that comes to mind are inputs and outputs to a
system/program. Which may be expensive to log in production but which
you want to record during testing. This is why the library includes
vlog. To allow the developer and system admin to increase logging for
a specific module.

Thanks,
-Jose
Post by H. S. Teoh
T
--
What's a "hot crossed bun"? An angry rabbit.
Jose Armando Garcia
2012-03-06 16:49:24 UTC
Permalink
Post by Kalle Svensson
* I agree that it is a good idea just to use few log levels.
* I think is it is a misstake not to let formatting of the whole
log message be pluggable (i.e. not the free text message the
programmer writes). If I have created a special RFC5424 formatter
(with MSGID and STRUCTURED-DATA fields set according to the will
of my corporate masters) I want to resuse it in both the
FileLogger and a future TcpLogger without having to use
inheritance. Your "line format" formatter in FileLogger is a good
default formatter though.
I agree but I am some what hesitant to add this now as it will just
prolongs everything. I think we can add this in the future without
breaking compatibility with code that was written against it.
Post by Kalle Svensson
? ?///Kalle
Richard van Scheijen
2012-03-01 00:13:30 UTC
Permalink
When logging the severity level should convey a certain insight
that the developer has about the code. This can be done with a 3
bit field. These are: known-cause, known-effect and breaks-flow.

This creates the following matrix:

KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal

A known cause is when the developer knows why a log event is
made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after.
Basically, you can tell if it is a catch-all by this flag.

When a severity should only be handled by a debugger, the normal
debug statement should be used. This is in essence a 4th bit.

I hope this helpful in the search for a good level system.
Sean Kelly
2012-03-02 00:59:51 UTC
Permalink
When logging the severity level should convey a certain insight that the developer has about the code. This can be done with a 3 bit field. These are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal
A known cause is when the developer knows why a log event is made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after. Basically, you can tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal debug statement should be used. This is in essence a 4th bit.
This is a really great breakdown of the log levels. I've never seen it explained so clearly. As a counterpoint, the important distinction I've found is primarily regarding what person should see a particular log line, and then only differentiated between INFO and ERROR messages. Roughly:

* Developer-Trace
* Developer-Info
* Developer-Error
* Admin-Info
* Admin-Error
* All-Fatal

Typically, the Developer and Admin logs go to different locations, in which case the Admin log lines may be duplicated in the Developer logs to provide added context. In any case, what I've found is that with more than a few log levels, people typically don't know how to classify things, severity becomes arbitrary, and log-levels are rendered largely useless. So from the above, we have four severities: Trace, Info, Error, and Fatal, with flags to indicate what type of message is being logged: Developer or Admin (aka. User).
Jose Armando Garcia
2012-03-06 17:31:47 UTC
Permalink
Post by Sean Kelly
When logging the severity level should convey a certain insight that the developer has about the code. This can be done with a 3 bit field. These are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 ?1 ?0 ?Trace
0 ?1 ?0 ?Info
1 ?0 ?0 ?Notice
0 ?0 ?0 ?Warning
1 ?1 ?1 ?Error
0 ?1 ?1 ?Critical
1 ?0 ?1 ?Severe
0 ?0 ?1 ?Fatal
A known cause is when the developer knows why a log event is made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after. Basically, you can tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal debug statement should be used. This is in essence a 4th bit.
* Developer-Trace
* Developer-Info
* Developer-Error
* Admin-Info
* Admin-Error
* All-Fatal
Typically, the Developer and Admin logs go to different locations, in which case the Admin log lines may be duplicated in the Developer logs to provide added context. ?In any case, what I've found is that with more than a few log levels, people typically don't know how to classify things, severity becomes arbitrary, and log-levels are rendered largely useless. ?So from the above, we have four severities: Trace, Info, Error, and Fatal, with flags to indicate what type of message is being logged: Developer or Admin (aka. User).
I liked Richard analysis but the truth is that I never needed that may
knobs for my logging needs. My thought process goes as follow:

I observed a interesting state:
1. Is the program observing external input for which the program can
execute around. E.g. parsing error with known default. If this is the
case the log warning.
2. Is the program observing a state that can do harm to the
system/computer/user. Log error and abort (std.log's fatal level) or
throw (std.log's critical level)
3. Is the program observing a state that would be interesting to
record for forensic. Log at info.

Think of a compiler parsing and generating CPU instructions for a
piece of code. If the compiler encounters an error in the code for
which it has no way to recover (missing symbol, etc), it logs an error
and aborts (exception or assert). If the compiler encounters a type
mismatch for which it can implicitly convert then maybe the compiler
will log a warning and continue. If the compiler wants to document
that it generated objects x, y and z then it can log at info.

Thanks,
-Jose
Robert Jacques
2012-03-02 02:24:31 UTC
Permalink
Post by Richard van Scheijen
When logging the severity level should convey a certain insight
that the developer has about the code. This can be done with a 3
bit field. These are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal
A known cause is when the developer knows why a log event is
made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after.
Basically, you can tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal
debug statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
vote++

I think establishing a good guideline as to log usage should be part of std.log's documentation. Making the bitflags a part of Severity might help cement this concept. It would also allow self documenting code, like:

log!(knownCause|unknownEffect|breaksFlow)("This is a severe message.");
H. S. Teoh
2012-03-02 08:20:03 UTC
Permalink
Post by Robert Jacques
Post by Richard van Scheijen
When logging the severity level should convey a certain insight
that the developer has about the code. This can be done with a 3
bit field. These are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal
A known cause is when the developer knows why a log event is
made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after.
Basically, you can tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal
debug statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
vote++
I think establishing a good guideline as to log usage should be part
of std.log's documentation. Making the bitflags a part of Severity
might help cement this concept. It would also allow self documenting
log!(knownCause|unknownEffect|breaksFlow)("This is a severe message.");
+1. I like this *much* better than "info", "notice", ... etc.


T
--
"I'm not childish; I'm just in touch with the child within!" - RL
mist
2012-03-03 13:28:04 UTC
Permalink
Post by Robert Jacques
log!(knownCause|unknownEffect|breaksFlow)("This is a severe
message.");
Simply defining log level enum in terms of this bit field would
help a lot.
Like, what is the first thing I do when getting a new log lib?
Checking all
pre-defined log levels and deciding when to use them. And, woah,
here it is, subtle but formal guide for use cases!
Jose Armando Garcia
2012-03-06 17:34:21 UTC
Permalink
Post by Robert Jacques
Post by Richard van Scheijen
When logging the severity level should convey a certain insight
that the developer has about the code. This can be done with a 3
bit field. These are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 ?1 ?0 ?Trace
0 ?1 ?0 ?Info
1 ?0 ?0 ?Notice
0 ?0 ?0 ?Warning
1 ?1 ?1 ?Error
0 ?1 ?1 ?Critical
1 ?0 ?1 ?Severe
0 ?0 ?1 ?Fatal
A known cause is when the developer knows why a log event is
made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after.
Basically, you can tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal
debug statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
vote++
I think establishing a good guideline as to log usage should be part of
std.log's documentation. Making the bitflags a part of Severity might help
log!(knownCause|unknownEffect|breaksFlow)("This is a severe message.");
Alluded to this before. My concern with this is that order is not
clear from the usage. And if we want to configure logging with a
mechanism that doesn't support ordering that means that the user will
need 3 knobs to configure each with 3 possible values.

Thanks,
-Jose
Robert Jacques
2012-03-06 18:18:01 UTC
Permalink
On Tue, 06 Mar 2012 11:34:21 -0600, Jose Armando Garcia
Post by Jose Armando Garcia
On Wed, 29 Feb 2012 18:13:30 -0600, Richard van Scheijen
<dlang at mesadu.net>
Post by Richard van Scheijen
When logging the severity level should convey a certain insight
that the developer has about the code. This can be done with a 3
bit field. These are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal
A known cause is when the developer knows why a log event is
made. e.g.: if you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after.
Basically, you can tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal
debug statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
vote++
I think establishing a good guideline as to log usage should be part of
std.log's documentation. Making the bitflags a part of Severity might
help
log!(knownCause|unknownEffect|breaksFlow)("This is a severe message.");
Alluded to this before. My concern with this is that order is not
clear from the usage. And if we want to configure logging with a
mechanism that doesn't support ordering that means that the user will
need 3 knobs to configure each with 3 possible values.
Thanks,
-Jose
The corollary to this is that causation is not clear from order. As I
posted in the other thread, I don't see a conflict between standardized
descriptive flags and a total ordering; in fact I think the flags help to
define the total ordering and improve logging consistency.
Jose Armando Garcia
2012-03-06 17:01:19 UTC
Permalink
When logging the severity level should convey a certain insight that the
developer has about the code. This can be done with a 3 bit field. These
are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 ?1 ?0 ?Trace
0 ?1 ?0 ?Info
1 ?0 ?0 ?Notice
0 ?0 ?0 ?Warning
1 ?1 ?1 ?Error
0 ?1 ?1 ?Critical
1 ?0 ?1 ?Severe
0 ?0 ?1 ?Fatal
A known cause is when the developer knows why a log event is made. e.g.: if
you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after. Basically, you can
tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal debug
statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
Interesting observation on logging. I like your theoretical
observation and explanation. To me the most important thing is
usability and unfortunately people are used to log levels as a order
concept. Meaning error is higher severity than info so if I am logging
info events I should probably also log error events.

If we go with a mechanism like the one you describe above there is no
order so the configuration is a little more complicated or verbose I
should say. Instead of saying we should log everything "greater" than
warning the user needs to say that they want to log known-cause,
known-effect, breaks-flow events. This mean that there are 27 (= 3^3)
configuration combinations. To implement this we need 3 configuration
nobs with 3 values (on, off, both).

Thoughts?
-Jose
Robert Jacques
2012-03-06 17:32:07 UTC
Permalink
On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia
On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen <dlang at mesadu.net>
When logging the severity level should convey a certain insight that the
developer has about the code. This can be done with a 3 bit field. These
are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal
A known cause is when the developer knows why a log event is made.
e.g.: if
you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after. Basically, you
can
tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal debug
statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
Interesting observation on logging. I like your theoretical
observation and explanation. To me the most important thing is
usability and unfortunately people are used to log levels as a order
concept. Meaning error is higher severity than info so if I am logging
info events I should probably also log error events.
If we go with a mechanism like the one you describe above there is no
order so the configuration is a little more complicated or verbose I
should say. Instead of saying we should log everything "greater" than
warning the user needs to say that they want to log known-cause,
known-effect, breaks-flow events. This mean that there are 27 (= 3^3)
configuration combinations. To implement this we need 3 configuration
nobs with 3 values (on, off, both).
Thoughts?
-Jose
There are only 8 possible configurations and they are nicely ordered in
terms of severity. So I don't see this as a problem. Also, if you went
with a combinatorial approach, shouldn't it be 2^8 = 256, not 3^3 = 27
values?
Jose Armando Garcia
2012-03-06 17:44:13 UTC
Permalink
On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia <jsancio at gmail.com>
On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen <dlang at mesadu.net>
When logging the severity level should convey a certain insight that the
developer has about the code. This can be done with a 3 bit field. These
are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 ?1 ?0 ?Trace
0 ?1 ?0 ?Info
1 ?0 ?0 ?Notice
0 ?0 ?0 ?Warning
1 ?1 ?1 ?Error
0 ?1 ?1 ?Critical
1 ?0 ?1 ?Severe
0 ?0 ?1 ?Fatal
if
you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after. Basically, you
can
tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal debug
statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
Interesting observation on logging. I like your theoretical
observation and explanation. To me the most important thing is
usability and unfortunately people are used to log levels as a order
concept. Meaning error is higher severity than info so if I am logging
info events I should probably also log error events.
If we go with a mechanism like the one you describe above there is no
order so the configuration is a little more complicated or verbose I
should say. Instead of saying we should log everything "greater" than
warning the user needs to say that they want to log known-cause,
known-effect, breaks-flow events. This mean that there are 27 (= 3^3)
configuration combinations. To implement this we need 3 configuration
nobs with 3 values (on, off, both).
Thoughts?
-Jose
There are only 8 possible configurations and they are nicely ordered in
terms of severity. So I don't see this as a problem. Also, if you went with
a combinatorial approach, shouldn't it be 2^8 = 256, not 3^3 = 27 values?
Yes. If you want to enable and disable each individual "level" then
you need 8 configuration options which leads to 2^8.

I suggested 3^3 as a more reasonable options that matches how the
developer is logging but doesn't give you as much expressiveness as
the 2^8 option.
Robert Jacques
2012-03-06 18:11:49 UTC
Permalink
On Tue, 06 Mar 2012 11:44:13 -0600, Jose Armando Garcia
Post by Jose Armando Garcia
Post by Robert Jacques
On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia
<jsancio at gmail.com>
On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen
<dlang at mesadu.net>
When logging the severity level should convey a certain insight that the
developer has about the code. This can be done with a 3 bit field. These
are: known-cause, known-effect and breaks-flow.
KC KE BF Severity
=================
1 1 0 Trace
0 1 0 Info
1 0 0 Notice
0 0 0 Warning
1 1 1 Error
0 1 1 Critical
1 0 1 Severe
0 0 1 Fatal
A known cause is when the developer knows why a log event is made.
if
you cannot open a file, you do not know why.
A known effect is when he/she knows what happens after. Basically, you
can
tell if it is a catch-all by this flag.
When a severity should only be handled by a debugger, the normal debug
statement should be used. This is in essence a 4th bit.
I hope this helpful in the search for a good level system.
Interesting observation on logging. I like your theoretical
observation and explanation. To me the most important thing is
usability and unfortunately people are used to log levels as a order
concept. Meaning error is higher severity than info so if I am logging
info events I should probably also log error events.
If we go with a mechanism like the one you describe above there is no
order so the configuration is a little more complicated or verbose I
should say. Instead of saying we should log everything "greater" than
warning the user needs to say that they want to log known-cause,
known-effect, breaks-flow events. This mean that there are 27 (= 3^3)
configuration combinations. To implement this we need 3 configuration
nobs with 3 values (on, off, both).
Thoughts?
-Jose
There are only 8 possible configurations and they are nicely ordered in
terms of severity. So I don't see this as a problem. Also, if you went
with
a combinatorial approach, shouldn't it be 2^8 = 256, not 3^3 = 27
values?
Yes. If you want to enable and disable each individual "level" then
you need 8 configuration options which leads to 2^8.
I suggested 3^3 as a more reasonable options that matches how the
developer is logging but doesn't give you as much expressiveness as
the 2^8 option.
In practice, all you'd need to take is a flag with the desired levels. i.e.

// Automatically set logging levels using the standard severity ordering
config.minSeverity(Severity.Warning);

// Manually set the logging levels
config.setSeverities(Severity.Warning|
Severity.Error|
Severity.Critical|
Severity.Severe|
Severity.Fatal);

I don't see the problem with including both methods and a large advantage
to having a standardized severity framework.
Brad Roberts
2012-03-02 08:56:31 UTC
Permalink
There are several modules in the review queue right now, and to get things going, I have volunteered to manage the
review of Jose's std.log proposal. Barring any objections, the review period starts now and ends in three weeks, on
March 6th, followed by a week of voting.
---
Code: https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
- Proof-reading of the docs is required.
- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141 (will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an abundance of partly incompatible logging
libraries like in Java. Thus, I'd warmly encourage everyone to actively try out the module or compare it with any
logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although comprehensive reviews are obviously appreciated, short
comments are very welcome as well!
David
My 2 cents from a fairly quick scan of the docs:

1) I'm of the opinion that it should be possible to strip all log code from an app without changing it's behavior.
Having log levels that change execution flow is evil. It's it the same class of bad practices as assert expressions
having side effects, imho.

2) Apps over a certain size (that tends to not be all that big, a few 10's of thousands of lines) tend to start to need
module based logging. This proposal includes a set of log levels that have no concept of modularity and another
separate set that do. The distinction seems arbitrary and limiting.

3) The conditional stuff seems cute, but I can't recall ever wanting it in anything I've done before.

4) I don't see an obvious facility for changing log parameters at runtime, unless the intent is to build a paramstring
array as if it came from command line parameters and calling parseCommandLine again. use case: long running application
that has a configuration api or notices a config file has been updated or whatever. Fairly common behavior.

5) The logger severity symbols part should allow more than single character tokens. IMHO, the default should be the
full name of the severity, not just the first character.

6) Is the log system thread safe? I see that it's at least thread aware, but what guarantees are about log entry atomicity?

7) The logger setter docs says it's an error to change the logger after a log message has been emitted. That's going to
hurt. It's not at all uncommon for an app to want to log some set of errors before it's potentially had enough time to
execute the code that configures the logger. use case: reading a config file to get the logger configuration, but can't
process the config file properly.

Later,
Brad
Jose Armando Garcia
2012-03-06 18:21:33 UTC
Permalink
Post by Brad Roberts
There are several modules in the review queue right now, and to get things going, I have volunteered to manage the
review of Jose's std.log proposal. Barring any objections, the review period starts now and ends in three weeks, on
March 6th, followed by a week of voting.
---
Code: https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd3cc8e6f5
Docs: http://jsancio.github.com/phobos/phobos/std_log.html
?- Proof-reading of the docs is required.
?- Not yet fully tested on Windows.
Depends on: https://github.com/D-Programming-Language/druntime/pull/141 (will be part of 2.058)
---
Earlier drafts of this library were discussed last year, just search the NG and ML archives for "std.log".
I think getting this right is vitally important so that we can avoid an abundance of partly incompatible logging
libraries like in Java. Thus, I'd warmly encourage everyone to actively try out the module or compare it with any
logging solution you might already be using in your project.
Please post all feedback in this thread, and remember: Although comprehensive reviews are obviously appreciated, short
comments are very welcome as well!
David
Thanks for looking at the documentation.
Post by Brad Roberts
1) I'm of the opinion that it should be possible to strip all log code from an app without changing it's behavior.
Having log levels that change execution flow is evil. ?It's it the same class of bad practices as assert expressions
having side effects, imho.
I think this depends on your point of view. One way to look at
critical("critical") is as a replacement to enforce() that logs. We
could extends critical in a way similar to enforce where you can
specify the exception that should be thrown. David, would this help
with the issues you express earlier?
Post by Brad Roberts
2) Apps over a certain size (that tends to not be all that big, a few 10's of thousands of lines) tend to start to need
module based logging. ?This proposal includes a set of log levels that have no concept of modularity and another
separate set that do. ?The distinction seems arbitrary and limiting.
This distinction is not a limitation of the logger API. It is a
limitation of the configuration API. In the future we can add the
option to enable error, warning, info at the module level without
breaking existing code.
Post by Brad Roberts
3) The conditional stuff seems cute, but I can't recall ever wanting it in anything I've done before.
4) I don't see an obvious facility for changing log parameters at runtime, unless the intent is to build a paramstring
array as if it came from command line parameters and calling parseCommandLine again. ?use case: long running application
that has a configuration api or notices a config file has been updated or whatever. ?Fairly common behavior.
If you want to change the log level at runtime you can just:

std.log.config.minSeverity = Severity.info;

No need to call parseCommandLine. Everything that parseCommandLine
does can be implemented by a client user. Really parseCommandLine
doesn't need to be part of the Configuration class. It is just there
for grouping and documentation.
Post by Brad Roberts
5) The logger severity symbols part should allow more than single character tokens. ?IMHO, the default should be the
full name of the severity, not just the first character.
My motivation for using one char is that it is easier to parse by both
computers and humans. It is also makes the framework faster since it
writes less bytes. I think we can extends this and fix this once we
have custom line formatted.
Post by Brad Roberts
6) Is the log system thread safe? ?I see that it's at least thread aware, but what guarantees are about log entry atomicity?
Yes, it is. It is probably to conservative in this regard. I need to
go back and do a lot performances improvements.
Post by Brad Roberts
7) The logger setter docs says it's an error to change the logger after a log message has been emitted. ?That's going to
hurt. ?It's not at all uncommon for an app to want to log some set of errors before it's potentially had enough time to
execute the code that configures the logger. ?use case: reading a config file to get the logger configuration, but can't
process the config file properly.
This was brought up before. There is no technical reason for this and
I will remove it.

Thanks!
Post by Brad Roberts
Later,
Brad
Steven Schveighoffer
2012-03-05 21:55:07 UTC
Permalink
On Mon, 13 Feb 2012 10:50:04 -0500, David Nadlinger <see at klickverbot.at>
Post by David Nadlinger
There are several modules in the review queue right now, and to get
things going, I have volunteered to manage the review of Jose's std.log
proposal. Barring any objections, the review period starts now and ends
in three weeks, on March 6th, followed by a week of voting.
Some notes:

I dislike that logging affects function execution. In particular, I don't
think the logging library should have any business throwing exceptions or
errors. It should be invisible to the application. The equivalent
function can be had by giving a wrapper function (i.e. log this message at
the fatal level, and then throw an error). A use case I can see is
printing several fatal log messages before exiting.

The log aliases use names that are too common. I think log.info is a
better symbol for logging than just 'info', which could be a symbol in a
myriad of places. Given that D's symbol lookup rules allow shadowing of
global symbols, this does not work out very well.

Like others have stated, I think vlog is a) confusing, and b)
unnecessary. Even reading the docs, I can't understand what it's used
for, and why it has such different syntax than the normal logging stuff.

I really like the every function, that's a great idea, one that I've
manually implemented (at least the once every N times) many times.

Do we have to make the logger a singleton? I'd like to see cases where I
can have different log instances. For example, an instance I can
enable/disable per class type, or an instance that logs to a diffferent
backend. Or a non-shared instance which does not need to handle threading
issues (i.e. a per-thread file log). Does this help with the vlog issue?

-Steve
David Nadlinger
2012-03-05 23:30:03 UTC
Permalink
On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer
Post by Steven Schveighoffer
The log aliases use names that are too common. I think
log.info is a better symbol for logging than just 'info', which
could be a symbol in a myriad of places. Given that D's symbol
lookup rules allow shadowing of global symbols, this does not
work out very well.
Originally, the code used log!info and so on, but it was changed
to the current design right after review begin, the rationale
being that you could always use ?import log = std.log? if you
want the extra namespace.
Post by Steven Schveighoffer
Like others have stated, I think vlog is a) confusing, and b)
unnecessary. Even reading the docs, I can't understand what
it's used for, and why it has such different syntax than the
normal logging stuff.
I think this been modelled after glog's verbose logging support
[1], just like much of the rest of the design (by the way, I
think a note about this should added somewhere in the module
docs). Does the feature as described in the glog docs make sense
to you?
Post by Steven Schveighoffer
I really like the every function, that's a great idea, one that
I've manually implemented (at least the once every N times)
many times.
I love it too, a similar design served me really well in some
larger *shudder* ActionScript projects.

David


[1]
http://google-glog.googlecode.com/svn/trunk/doc/glog.html#verbose
Steven Schveighoffer
2012-03-05 23:51:29 UTC
Permalink
On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger <see at klickverbot.at>
Post by Steven Schveighoffer
The log aliases use names that are too common. I think log.info is a
better symbol for logging than just 'info', which could be a symbol in
a myriad of places. Given that D's symbol lookup rules allow shadowing
of global symbols, this does not work out very well.
Originally, the code used log!info and so on, but it was changed to the
current design right after review begin, the rationale being that you
could always use ?import log = std.log? if you want the extra namespace.
That doesn't help. Software isn't static.

import std.log;
import other; // defines B

class A : B
{
void foo()
{
info("some info message"); // error! int isn't a function!
}
}

other.d:

class B
{
int info; // added later
}
Post by Steven Schveighoffer
Like others have stated, I think vlog is a) confusing, and b)
unnecessary. Even reading the docs, I can't understand what it's used
for, and why it has such different syntax than the normal logging stuff.
I think this been modelled after glog's verbose logging support [1],
just like much of the rest of the design (by the way, I think a note
about this should added somewhere in the module docs). Does the feature
as described in the glog docs make sense to you?
It's good to know the root of where this comes from. The docs in glog do
make more sense than the vlog docs.

This may be a doc issue. I'll have to think about it some more.

-Steve
so
2012-03-06 01:22:05 UTC
Permalink
On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer
Post by Steven Schveighoffer
On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger
Post by David Nadlinger
On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer
Post by Steven Schveighoffer
The log aliases use names that are too common. I think
log.info is a better symbol for logging than just 'info',
which could be a symbol in a myriad of places. Given that
D's symbol lookup rules allow shadowing of global symbols,
this does not work out very well.
Originally, the code used log!info and so on, but it was
changed to the current design right after review begin, the
rationale being that you could always use ?import log =
std.log? if you want the extra namespace.
That doesn't help. Software isn't static.
import std.log;
import other; // defines B
class A : B
{
void foo()
{
info("some info message"); // error! int isn't a function!
}
}
class B
{
int info; // added later
}
That is not a counter-argument to something related to this
library but everything that lies in global namespace.
At its first state both severity levels and the "log" was in
global namespace. Now only severity levels.

You are also overlooking one crucial fact that this library will
be part of phobos, standard library. Which requires everyone to
adopt. When you see codes like this (below), you don't blame
standard library designers do you?

using namespace std;
int cout;
Jonathan M Davis
2012-03-06 01:32:54 UTC
Permalink
Post by so
That is not a counter-argument to something related to this
library but everything that lies in global namespace.
At its first state both severity levels and the "log" was in
global namespace. Now only severity levels.
You are also overlooking one crucial fact that this library will
be part of phobos, standard library. Which requires everyone to
adopt. When you see codes like this (below), you don't blame
standard library designers do you?
using namespace std;
int cout;
Except that cout is not exactly something that would be considered a normal
variable name. Something like info _is_. This logging module is taking
incredibly common names and shoving them as far into the global namespace as
anything can go in D which isn't a compiler built-in. _Not_ a good idea IMHO -
not without good reason. And I really don't think that this merits it.
log!info(msg) would work just fine and would be _far_ better.

- Jonathan M Davis
Steven Schveighoffer
2012-03-06 01:30:41 UTC
Permalink
Post by Steven Schveighoffer
On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger
Post by Steven Schveighoffer
The log aliases use names that are too common. I think log.info is a
better symbol for logging than just 'info', which could be a symbol
in a myriad of places. Given that D's symbol lookup rules allow
shadowing of global symbols, this does not work out very well.
Originally, the code used log!info and so on, but it was changed to
the current design right after review begin, the rationale being that
you could always use ?import log = std.log? if you want the extra
namespace.
That doesn't help. Software isn't static.
import std.log;
import other; // defines B
class A : B
{
void foo()
{
info("some info message"); // error! int isn't a function!
}
}
class B
{
int info; // added later
}
That is not a counter-argument to something related to this library but
everything that lies in global namespace.
At its first state both severity levels and the "log" was in global
namespace. Now only severity levels.
You are also overlooking one crucial fact that this library will be part
of phobos, standard library. Which requires everyone to adopt. When you
see codes like this (below), you don't blame standard library designers
do you?
using namespace std;
int cout;
Except 'info', 'error', 'warning' are all common names, likely to be a
very attractive name for something that has nothing to do with (or cares
about) logging. cout is not a common name or even an english word, so
it's unlikely someone has or wants to create a cout member.

Couple this with the fact that all of these are nouns -- likely candidates
for fields.

Your argument has some merit, but I would add that my argument is only
against *common* global namespace names.

Another solution besides using a namespace is to make the names less
common, like linfo instead of just info.

-Steve
so
2012-03-06 01:39:20 UTC
Permalink
On Tuesday, 6 March 2012 at 01:30:41 UTC, Steven Schveighoffer
Post by Steven Schveighoffer
Except 'info', 'error', 'warning' are all common names, likely
to be a very attractive name for something that has nothing to
do with (or cares about) logging. cout is not a common name or
even an english word, so it's unlikely someone has or wants to
create a cout member.
Couple this with the fact that all of these are nouns -- likely
candidates for fields.
Your argument has some merit, but I would add that my argument
is only against *common* global namespace names.
Another solution besides using a namespace is to make the names
less common, like linfo instead of just info.
I have no objections against changing names. For example, instead
of "info" i use "note" for my logger. Not 100% sure about "error"
but i think "warning" also implies logging and don't see any use
case where it would be used as a variable name.
so
2012-03-06 01:41:29 UTC
Permalink
Post by Jonathan M Davis
And I really don't think that this merits it.
log!info(msg) would work just fine and would be _far_ better.
Now you got not only "info" but "log" in global namespace :)
I think you meant "log.info".
Robert Jacques
2012-03-06 03:11:17 UTC
Permalink
Post by so
On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer
Post by Steven Schveighoffer
On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger
Post by David Nadlinger
Post by Steven Schveighoffer
The log aliases use names that are too common. I think
log.info is a better symbol for logging than just 'info',
which could be a symbol in a myriad of places. Given that
D's symbol lookup rules allow shadowing of global symbols,
this does not work out very well.
Originally, the code used log!info and so on, but it was
changed to the current design right after review begin, the
rationale being that you could always use ?import log =
std.log? if you want the extra namespace.
That doesn't help. Software isn't static.
import std.log;
import other; // defines B
class A : B
{
void foo()
{
info("some info message"); // error! int isn't a function!
}
}
class B
{
int info; // added later
}
That is not a counter-argument to something related to this
library but everything that lies in global namespace.
At its first state both severity levels and the "log" was in
global namespace. Now only severity levels.
You are also overlooking one crucial fact that this library will
be part of phobos, standard library. Which requires everyone to
adopt.
Please don't forget that you are _submitting_ a library into Phobos and the D ecosystem at large. Yes, new code can be expected to avoid these names, but all existing code has to be retrofitted and fixed.
so
2012-03-06 08:16:10 UTC
Permalink
Post by Robert Jacques
Please don't forget that you are _submitting_ a library into
Phobos and the D ecosystem at large. Yes, new code can be
expected to avoid these names, but all existing code has to be
retrofitted and fixed.
Probably it is the reason why they use cryptic variable names in
C++ std library :)
Jacob Carlborg
2012-03-06 07:46:14 UTC
Permalink
Post by Jonathan M Davis
Post by so
That is not a counter-argument to something related to this
library but everything that lies in global namespace.
At its first state both severity levels and the "log" was in
global namespace. Now only severity levels.
You are also overlooking one crucial fact that this library will
be part of phobos, standard library. Which requires everyone to
adopt. When you see codes like this (below), you don't blame
standard library designers do you?
using namespace std;
int cout;
Except that cout is not exactly something that would be considered a normal
variable name. Something like info _is_. This logging module is taking
incredibly common names and shoving them as far into the global namespace as
anything can go in D which isn't a compiler built-in. _Not_ a good idea IMHO -
not without good reason. And I really don't think that this merits it.
log!info(msg) would work just fine and would be _far_ better.
- Jonathan M Davis
The user can then alias "log!info" to "info" if he/she wants to.
--
/Jacob Carlborg
Jonathan M Davis
2012-03-06 07:54:39 UTC
Permalink
Post by Jacob Carlborg
Post by Jonathan M Davis
Post by so
That is not a counter-argument to something related to this
library but everything that lies in global namespace.
At its first state both severity levels and the "log" was in
global namespace. Now only severity levels.
You are also overlooking one crucial fact that this library will
be part of phobos, standard library. Which requires everyone to
adopt. When you see codes like this (below), you don't blame
standard library designers do you?
using namespace std;
int cout;
Except that cout is not exactly something that would be considered a normal
variable name. Something like info _is_. This logging module is taking
incredibly common names and shoving them as far into the global namespace
as anything can go in D which isn't a compiler built-in. _Not_ a good
idea IMHO - not without good reason. And I really don't think that this
merits it. log!info(msg) would work just fine and would be _far_ better.
- Jonathan M Davis
The user can then alias "log!info" to "info" if he/she wants to.
The user can do whatever aliases they want. It's just that we shouldn't
unnecessarily use really common names at the top level, since then they'll
conflict with a lot of stuff.

- Jonathan M Davis
so
2012-03-06 08:14:16 UTC
Permalink
Post by Jacob Carlborg
The user can then alias "log!info" to "info" if he/she wants to.
Again, you are now forcing 2 common names instead of one as it is
now.
When you instantiate log!info where do you get "info" from?
Jonathan M Davis
2012-03-06 08:25:44 UTC
Permalink
Post by so
Post by Jacob Carlborg
The user can then alias "log!info" to "info" if he/she wants to.
Again, you are now forcing 2 common names instead of one as it is
now.
When you instantiate log!info where do you get "info" from?
Yes. My mistake - probably because the time stuff typicall takes such a
template argument as string, which would make this log!"info"(msg). However,
adding _log_ isn't necessarily bad, given that this is std.log that we're
talking about. It's info and the rest that are the problem.

- Jonathan M Davis
Jacob Carlborg
2012-03-06 08:14:50 UTC
Permalink
Post by Jonathan M Davis
Post by Jacob Carlborg
Post by Jonathan M Davis
Post by so
That is not a counter-argument to something related to this
library but everything that lies in global namespace.
At its first state both severity levels and the "log" was in
global namespace. Now only severity levels.
You are also overlooking one crucial fact that this library will
be part of phobos, standard library. Which requires everyone to
adopt. When you see codes like this (below), you don't blame
standard library designers do you?
using namespace std;
int cout;
Except that cout is not exactly something that would be considered a normal
variable name. Something like info _is_. This logging module is taking
incredibly common names and shoving them as far into the global namespace
as anything can go in D which isn't a compiler built-in. _Not_ a good
idea IMHO - not without good reason. And I really don't think that this
merits it. log!info(msg) would work just fine and would be _far_ better.
- Jonathan M Davis
The user can then alias "log!info" to "info" if he/she wants to.
The user can do whatever aliases they want. It's just that we shouldn't
unnecessarily use really common names at the top level, since then they'll
conflict with a lot of stuff.
- Jonathan M Davis
What I'm trying so say is that if we use the template function the user
can get the best of both worlds.
--
/Jacob Carlborg
Jose Armando Garcia
2012-03-06 19:22:18 UTC
Permalink
On Mon, Mar 5, 2012 at 3:51 PM, Steven Schveighoffer
Post by Steven Schveighoffer
On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger <see at klickverbot.at>
Post by Steven Schveighoffer
The log aliases use names that are too common. ?I think log.info is a
better symbol for logging than just 'info', which could be a symbol in a
myriad of places. ?Given that D's symbol lookup rules allow shadowing of
global symbols, this does not work out very well.
Originally, the code used log!info and so on, but it was changed to the
current design right after review begin, the rationale being that you could
always use ?import log = std.log? if you want the extra namespace.
That doesn't help. ?Software isn't static.
import std.log;
import log = std.log;
Post by Steven Schveighoffer
import other; // defines B
class A : B
{
? void foo()
? {
? ? ?info("some info message"); // error! int isn't a function!
log.info("some info message");
Post by Steven Schveighoffer
? }
}
class B
{
? int info; // added later
}
Post by Steven Schveighoffer
Like others have stated, I think vlog is a) confusing, and b)
unnecessary. ?Even reading the docs, I can't understand what it's used for,
and why it has such different syntax than the normal logging stuff.
I think this been modelled after glog's verbose logging support [1], just
like much of the rest of the design (by the way, I think a note about this
should added somewhere in the module docs). Does the feature as described in
the glog docs make sense to you?
It's good to know the root of where this comes from. ?The docs in glog do
make more sense than the vlog docs.
This may be a doc issue. ?I'll have to think about it some more.
-Steve
Jose Armando Garcia
2012-03-06 19:19:27 UTC
Permalink
On Mon, Mar 5, 2012 at 1:55 PM, Steven Schveighoffer
Post by Steven Schveighoffer
On Mon, 13 Feb 2012 10:50:04 -0500, David Nadlinger <see at klickverbot.at>
There are several modules in the review queue right now, and to get things
going, I have volunteered to manage the review of Jose's std.log proposal.
Barring any objections, the review period starts now and ends in three
weeks, on March 6th, followed by a week of voting.
I dislike that logging affects function execution. ?In particular, I don't
think the logging library should have any business throwing exceptions or
errors. ?It should be invisible to the application. ?The equivalent function
can be had by giving a wrapper function (i.e. log this message at the fatal
level, and then throw an error). ?A use case I can see is printing several
fatal log messages before exiting.
Then don't use std.log.fatal. It is not like you are forced to use it.
You can implement the above by using std.log.error
Post by Steven Schveighoffer
The log aliases use names that are too common. ?I think log.info is a better
symbol for logging than just 'info', which could be a symbol in a myriad of
places. ?Given that D's symbol lookup rules allow shadowing of global
symbols, this does not work out very well.
This is a tough one. Should we be relying on D's module abstraction.
It is not scalable as a module designer and implementer to think about
other modules. This is why a lot of programming languages implement
the concept of namespaces.

import log = std.log;
log.info("hello world");
Post by Steven Schveighoffer
Like others have stated, I think vlog is a) confusing, and b) unnecessary.
?Even reading the docs, I can't understand what it's used for, and why it
has such different syntax than the normal logging stuff.
I have tried to explain this before but it looks like I have failed. I
find it useful. If you are interested on a different explaination:
http://google-glog.googlecode.com/svn/trunk/doc/glog.html
Post by Steven Schveighoffer
I really like the every function, that's a great idea, one that I've
manually implemented (at least the once every N times) many times.
Great!
Post by Steven Schveighoffer
Do we have to make the logger a singleton? ?I'd like to see cases where I
can have different log instances. ?For example, an instance I can
enable/disable per class type, or an instance that logs to a diffferent
backend. ?Or a non-shared instance which does not need to handle threading
issues (i.e. a per-thread file log).?Does this help with the vlog issue?
My point of view here is that as a developer I never know how I want
to categorize my log during development. Some people use class name as
a hack for doing this. What about functional programs that don't use
class/objects? What about logical component/classes that span multiple
classes? I always found class based grouping for logging as a hack. D
made the observation that classes are not always the best abstraction
unit so it introduced modules. std.log filters based on modules
(actually source files to be exact but if D had __MODULE__, std.log
would use that instead.)
Post by Steven Schveighoffer
-Steve
Loading...