www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Review of Jose Armando Garcia Sancio's std.log

reply David Nadlinger <see klickverbot.at> writes:
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
Feb 13 2012
next sibling parent reply David Nadlinger <see klickverbot.at> writes:
On 2/13/12 4:50 PM, David Nadlinger wrote:
 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
Feb 13 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, February 13, 2012 17:49:49 David Nadlinger wrote:
 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
Feb 13 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'd like to see a simple example of how to specify the filename of the log file.
Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 4:19 PM, Jonathan M Davis <jmdavisProg gmx.com> wro=
te:
 On Monday, February 13, 2012 17:49:49 David Nadlinger wrote:
 You define the Severity enum members starting with fatal as 0. Why not
 the other way round =96 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 we=

 The greater the number, the more logging output, you're going to see. So,=

 following syslog in that respect, though he doesn't have as many log leve=

 He should probably add at least debug. He also aliases them to module-lev=

 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
 - Jonathan M Davis

Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 5:06 PM, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 I'd like to see a simple example of how to specify the filename of the log
file.

Fair enough...
Feb 13 2012
prev sibling parent "HeiHon" <heiko.honrath gmx.de> writes:
On Tuesday, 14 February 2012 at 01:58:50 UTC, Jose Armando Garcia 
wrote:
 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.

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).
Feb 16 2012
prev sibling next sibling parent reply "jdrewsen" <jdrewsen nospam.com> writes:
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
Feb 13 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/13/12 8:28 PM, Jose Armando Garcia wrote:
 On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen<jdrewsen nospam.com>  wrote:
 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");

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
Feb 13 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Feb 13, 2012, at 12:44 PM, jdrewsen wrote:

 A first quick observation:
=20
 I vote for a debug severity level. Then make that default to the =

=20
 template log(Severity severity =3D Severity.debug)
=20
 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.=
Feb 13 2012
prev sibling next sibling parent reply =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= <ludwig informatik.uni-luebeck.de> writes:
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.
Feb 13 2012
next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 9:12 PM, James Miller <james aatch.net> wrote:
 On 14 February 2012 10:17, S=F6nke Ludwig
 <ludwig informatik.uni-luebeck.de> wrote:
 Log levels "debug" and maybe also "trace" would be useful, but I see tha=


 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 o=


 overhead would be searching once through the format string in the case o=


 format placeholders.

 A predefined logger for OutputDebugString on Windows would be useful - o=


 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 nice=


 formatted HTML file with built-in JavaScript to be able to filter messag=


 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)=


 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.

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?
 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.

--alsologtostderr and --stderrthreshold.
 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.

a living module. The most important thing I think is that we can make this future improvements without breaking existing users.
 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

Feb 13 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-02-13 22:17, Sönke Ludwig wrote:
 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.
 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
Feb 13 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-02-14 17:19, Jose Armando Garcia wrote:
 On Tue, Feb 14, 2012 at 5:44 AM, Jacob Carlborg<doob me.com>  wrote:
 On 2012-02-13 22:17, Snke Ludwig wrote:
 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.

(FileLogger) allow you to specify the format line see FileLogger.Configuration.lineFormat If you want to do the HTML stuff Snke 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
Feb 14 2012
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Feb 14, 2012 at 5:44 AM, Jacob Carlborg <doob me.com> wrote:
 On 2012-02-13 22:17, S=F6nke Ludwig wrote:
 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.

(FileLogger) allow you to specify the format line see FileLogger.Configuration.lineFormat If you want to do the HTML stuff S=F6nke 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
 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

Feb 14 2012
prev sibling next sibling parent James Miller <james aatch.net> writes:
On 14 February 2012 10:17, S=C3=B6nke Ludwig
<ludwig informatik.uni-luebeck.de> wrote:
 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 on=

 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 nicel=

 formatted HTML file with built-in JavaScript to be able to filter message=

 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).=

 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
Feb 13 2012
prev sibling next sibling parent reply "so" <so so.so> writes:
On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger 
wrote:
 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

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".
Feb 13 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-02-14 00:37, so wrote:
 On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger wrote:
 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

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".

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
Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 2:49 PM, David Nadlinger <see klickverbot.at> wrote=
:
 On 2/13/12 4:50 PM, David Nadlinger wrote:
 https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cb=


 Docs: http://jsancio.github.com/phobos/phobos/std_log.html

A few small points from a first pass through the docs: Spelling nits: =A0- potion -> position =A0- enviroment -> environment =A0- arguements -> arguments =A0- explictly -> explicitly =A0- fileter -> filter =A0- persiste -> persist =A0- genereated -> generated =A0- brakets -> brackets =A0- paramater -> parameter =A0- compuration -> computation

 The introductory section needs some copy editing, e.g.:
 =A0- In the first paragraph, every sentence starts with =BBThe module=AB
 =A0- disabled/enabled -> disable/enable
 =A0- =BBIn the other=AB -> =BBin the order=AB

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 th=

 other way round =96 so that severityA < severityB would do what you (or a=

 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?

 Maybe clarify the meaning of =BBcan be logged=AB (i.e. the severity level=

 completely disabled) in the LogFilter docs?

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, =BBThe default value a
 FileLogger.=AB, =BBchange and configure=AB (where is the difference?)

 =BBCreate a configuration object based on the passed parameter.=AB is sli=

 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.
Feb 13 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, February 13, 2012 23:58:38 Jose Armando Garcia wrote:
 On Mon, Feb 13, 2012 at 4:19 PM, Jonathan M Davis <jmdavisProg gmx.com> 

 On Monday, February 13, 2012 17:49:49 David Nadlinger wrote:
 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.

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
Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 6:47 PM, Sean Kelly <sean invisibleduck.org> wrote:
 On Feb 13, 2012, at 12:44 PM, jdrewsen wrote:

 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.

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...
Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen <jdrewsen nospam.com> wrote:
 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");

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

Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 7:17 PM, S=F6nke Ludwig
<ludwig informatik.uni-luebeck.de> wrote:
 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 on=

 overhead would be searching once through the format string in the case of
 format placeholders.

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.

gets commit to phobos? Thanks.
 One kind of log writer that I have in my code is one that outputs a nicel=

 formatted HTML file with built-in JavaScript to be able to filter message=

 by priority or module. Maybe this is too much for a standard library
 implementation though.

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).=

 course, one can also simply write a "MultiDispatchLogger"...

 A format option to log the thread name instead of just the ID.

Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 9:37 PM, so <so so.so> wrote:
 On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger wrote:
 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

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".

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...
Feb 13 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Feb 14, 2012 at 12:02 AM, Jonathan M Davis <jmdavisProg gmx.com> wr=
ote:
 On Monday, February 13, 2012 23:58:38 Jose Armando Garcia wrote:
 On Mon, Feb 13, 2012 at 4:19 PM, Jonathan M Davis <jmdavisProg gmx.com>

 On Monday, February 13, 2012 17:49:49 David Nadlinger wrote:
 You define the Severity enum members starting with fatal as 0. Why no=




 the other way round =96 so that severityA < severityB would do what y=




 (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 als=



 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.

Personally, I'd just copy what syslog does in terms of log levels. Then std.log can use syslog and everything maps wonderfully.

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.
 - Jonathan M Davis

Feb 13 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, February 14, 2012 01:16:29 Jose Armando Garcia wrote:
 On Tue, Feb 14, 2012 at 12:02 AM, Jonathan M Davis <jmdavisProg gmx.c=

wrote:
 On Monday, February 13, 2012 23:58:38 Jose Armando Garcia wrote:
 On Mon, Feb 13, 2012 at 4:19 PM, Jonathan M Davis <jmdavisProg gmx=



=20
 wrote:
 On Monday, February 13, 2012 17:49:49 David Nadlinger wrote:
 You define the Severity enum members starting with fatal as 0. =





 the other way round =E2=80=93 so that severityA < severityB wou=





 (or at least I) would expect?

syslog defines 0 (LOG_EMERG) as the strongest and 7 (LOG_DEBUG) =




 weakest. The greater the number, the more logging output, you're=




 to see. So, he's following syslog in that respect, though he doe=




 have as many log levels. He should probably add at least debug. =




 aliases them to module-level symbols for some reason, which is a=




 no-no IMHO.

I am trying to minimize the number of predefined log levels. One o=



 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 thi=



 very clear:
=20
 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 violati=



 but you wish to continue and cross your finger
 4. Log at warning if you detected peculiar condition yet the progr=



 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.
=20
 I think it would help me that instead of suggesting another level =



 instead state what we think the user would like to do or log but t=



 framework as defined doesn't let the user do.

Personally, I'd just copy what syslog does in terms of log levels. =


 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. =20 This is exactly what SLF4J does with Log4J, java.util.logger, syslog,=

Where I work, we log debug messages to syslog all the time when the pro= duct is=20 under development. It's incredibly useful. And on Linux, syslog is _the= _=20 logging facility. It's where all log messages should go. Then syslog ca= n be=20 configured to split up log files per program or log level or whatever e= lse you=20 want to do on that particular system. But regardless, all logging goes = to=20 syslog. That's what it's for. - Jonathan M Davis
Feb 13 2012
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/13/12 9:50 AM, David Nadlinger wrote:
 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
Feb 13 2012
prev sibling next sibling parent Johannes Pfau <nospam example.com> writes:
Am Mon, 13 Feb 2012 19:22:54 -0800
schrieb Jonathan M Davis <jmdavisProg gmx.com>:
 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
Feb 14 2012
prev sibling next sibling parent "jdrewsen" <jdrewsen nospam.com> writes:
On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando Garcia 
wrote:
 On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen <jdrewsen nospam.com> 
 wrote:
 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");

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
Feb 14 2012
prev sibling next sibling parent "jdrewsen" <jdrewsen nospam.com> writes:
On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger 
wrote:
 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

Updated wiki: http://prowiki.org/wiki4d/wiki.cgi?ReviewQueue /Jonas
Feb 14 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-02-13 16:50, David Nadlinger wrote:
 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

Is it possible to log to other locations, i.e. to the standard location for the given platform. -- /Jacob Carlborg
Feb 14 2012
next sibling parent reply David Nadlinger <see klickverbot.at> writes:
On 2/14/12 2:14 PM, Jacob Carlborg wrote:
 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
Feb 14 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-02-14 14:24, David Nadlinger wrote:
 On 2/14/12 2:14 PM, Jacob Carlborg wrote:
 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
Feb 14 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-02-14 17:27, Jose Armando Garcia wrote:
 On Tue, Feb 14, 2012 at 11:14 AM, Jacob Carlborg<doob me.com>  wrote:
 On 2012-02-13 16:50, David Nadlinger wrote:
 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

Is it possible to log to other locations, i.e. to the standard location for the given platform.

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.

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
Feb 14 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Feb 14, 2012 at 4:50 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 2/13/12 9:50 AM, David Nadlinger wrote:
 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).

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.
 * "Descripton of the supported severities." -> "Description of supported
 severities." (notice the typo too)

 * vlog should take uint, not int.

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?
 * 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.

NoopLogFilter (used for compiled time disabling). But yes they have structurally the same set of public methods. Fixed.
 * 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").

info.when(first())("Only log this one time per thread run")
 * No examples include durations.

be readable.
 * There might be a better name for Rich.

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

Thanks! -Jose
 Andrei

Feb 14 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger <see klickverbot.at> wrote=
:
 There are several modules in the review queue right now, and to get thing=

 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/d114420e0791c704f6899d81a0293cbd=

 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");
 Known remaining issues:
 =A0- Proof-reading of the docs is required.
 =A0- 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 =

 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'=

 warmly encourage everyone to actively try out the module or compare it wi=

 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

Feb 14 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Feb 14, 2012 at 8:42 AM, jdrewsen <jdrewsen nospam.com> wrote:
 On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando Garcia wrote:
 On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen <jdrewsen nospam.com> wrote:
 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");

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

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

Feb 14 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Feb 14, 2012 at 11:14 AM, Jacob Carlborg <doob me.com> wrote:
 On 2012-02-13 16:50, David Nadlinger wrote:
 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

Is it possible to log to other locations, i.e. to the standard location for the given platform.

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

Feb 14 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger <see klickverbot.at> wrote=
:
 There are several modules in the review queue right now, and to get thing=

 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/d114420e0791c704f6899d81a0293cbd=

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

 Known remaining issues:
 =A0- Proof-reading of the docs is required.
 =A0- 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 =

 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'=

 warmly encourage everyone to actively try out the module or compare it wi=

 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

Feb 14 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Tuesday, 14 February 2012 at 16:21:42 UTC, Jose Armando Garcia 
wrote:
 On Tue, Feb 14, 2012 at 8:42 AM, jdrewsen <jdrewsen nospam.com> 
 wrote:
 On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando 
 Garcia wrote:
 On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen 
 <jdrewsen nospam.com> wrote:
 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");

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

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".
Feb 14 2012
prev sibling next sibling parent "jdrewsen" <jdrewsen nospam.com> writes:
On Tuesday, 14 February 2012 at 17:48:06 UTC, so wrote:
 On Tuesday, 14 February 2012 at 16:21:42 UTC, Jose Armando 
 Garcia wrote:
 On Tue, Feb 14, 2012 at 8:42 AM, jdrewsen 
 <jdrewsen nospam.com> wrote:
 On Tuesday, 14 February 2012 at 02:28:11 UTC, Jose Armando 
 Garcia wrote:
 On Mon, Feb 13, 2012 at 6:44 PM, jdrewsen 
 <jdrewsen nospam.com> wrote:
 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");

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

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".

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
Feb 14 2012
prev sibling next sibling parent "jdrewsen" <jdrewsen nospam.com> writes:
On Tuesday, 14 February 2012 at 16:12:57 UTC, Jose Armando Garcia 
wrote:
 On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger 
 <see klickverbot.at> wrote:
 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

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");

In the introduction text the references to Configuration etc. should be made into links. /Jonas
Feb 14 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Feb 14, 2012 at 4:44 PM, jdrewsen <jdrewsen nospam.com> wrote:
 On Tuesday, 14 February 2012 at 16:12:57 UTC, Jose Armando Garcia wrote:
 On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger <see klickverbot.at>
 wrote:
 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/d114420e0791c704f6899d81a0293c=



 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). =A0this means that to concatenate strings you need to info.write("Hello ", "world");

In the introduction text the references to Configuration etc. should be m=

 into links.

 /Jonas

Feb 14 2012
prev sibling next sibling parent "jdrewsen" <jdrewsen nospam.com> writes:
On Tuesday, 14 February 2012 at 18:51:20 UTC, Jose Armando Garcia 
wrote:
 On Tue, Feb 14, 2012 at 4:44 PM, jdrewsen <jdrewsen nospam.com> 
 wrote:
 On Tuesday, 14 February 2012 at 16:12:57 UTC, Jose Armando 
 Garcia wrote:
 On Mon, Feb 13, 2012 at 1:50 PM, David Nadlinger 
 <see klickverbot.at>
 wrote:
 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

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");

In the introduction text the references to Configuration etc. should be made into links.


For example: $(LREF Configuration) The LREF macro is defined in https://github.com/D-Programming-Language/d-programming-language.org/blob/ aster/std.ddoc#L293 along with other useful macros. /Jonas
Feb 14 2012
prev sibling next sibling parent reply bls <bizprac orange.fr> writes:
On 02/13/2012 07:50 AM, David Nadlinger wrote:
 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)

This is somehow bad. Review a piece of library-software by using a beta compiler and beta-library.
Feb 12 2012
next sibling parent "so" <so so.so> writes:
On Tuesday, 14 February 2012 at 21:47:42 UTC, bls wrote:

 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.
Feb 15 2012
prev sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 14 February 2012 at 21:47:42 UTC, bls wrote:
 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
Feb 15 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, February 13, 2012 16:50:04 David Nadlinger wrote: 
 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
Feb 16 2012
parent reply =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= <ludwig informatik.uni-luebeck.de> writes:
Am 16.02.2012 10:21, schrieb Jonathan M Davis:
 On Monday, February 13, 2012 16:50:04 David Nadlinger wrote:
 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.
 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...
 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

Feb 16 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-02-16 10:57, Sönke Ludwig wrote:
 Am 16.02.2012 10:21, schrieb Jonathan M Davis:
 On Monday, February 13, 2012 16:50:04 David Nadlinger wrote:
 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
Feb 16 2012
parent =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= <ludwig informatik.uni-luebeck.de> writes:
Am 17.02.2012 02:49, schrieb 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.
 From experience, I would recommend:

- 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).
Feb 17 2012
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/17/12 12:06 PM, Jose Armando Garcia wrote:
 info("%s message", Severity.info);

I think defaulting to formatted stuff may be confusing. Andrei
Feb 17 2012
parent reply =?ISO-8859-1?Q?S=F6nke_Ludwig?= <ludwig informatik.uni-luebeck.de> writes:
Am 17.02.2012 21:48, schrieb Andrei Alexandrescu:
 On 2/17/12 12:06 PM, Jose Armando Garcia wrote:
 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.
Mar 03 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/3/12 5:51 AM, Snke Ludwig wrote:
 Am 17.02.2012 21:48, schrieb Andrei Alexandrescu:
 On 2/17/12 12:06 PM, Jose Armando Garcia wrote:
 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
Mar 03 2012
parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 04.03.2012 2:17, Andrei Alexandrescu wrote:
 On 3/3/12 5:51 AM, Snke Ludwig wrote:
 Am 17.02.2012 21:48, schrieb Andrei Alexandrescu:
 On 2/17/12 12:06 PM, Jose Armando Garcia wrote:
 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?

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
Mar 04 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/4/12 3:17 AM, Dmitry Olshansky wrote:
 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);

Yah, agreed. Probably calls with no extra arguments should be safe. Andrei
Mar 04 2012
prev sibling next sibling parent Jonathan Stephens <slashrslashn gmail.com> writes:
 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.
From experience, I would recommend:

- 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.
Feb 16 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Feb 16, 2012 at 06:49:41PM -0700, Jonathan Stephens wrote:
 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.
From experience, I would recommend:

- 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.

From my experience, such a proliferation of log levels is rarely used

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.
Feb 16 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Feb 16, 2012 at 7:21 AM, Jonathan M Davis <jmdavisProg gmx.com> wro=
te:
 On Monday, February 13, 2012 16:50:04 David Nadlinger wrote:
 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 th=

 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.
 Also, _please_ add a debug level. Personally, I'd argue for simply copyin=

 syslog's levels and matching them, since ideally any logging on Linux wou=

 going to syslog anyway. But there are good reasons to have messages beyon=

 info. I sure wouldn't want _all_ messages which don't indicate a problem =

 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.
 I'd need
 another log level which isn't there. Using the concept of verbosity to tr=

 handle this is a needless complication. syslog has

 #define LOG_EMERG =A0 =A0 =A0 0 =A0 =A0 =A0 /* system is unusable */
 #define LOG_ALERT =A0 =A0 =A0 1 =A0 =A0 =A0 /* action must be taken immed=

 #define LOG_CRIT =A0 =A0 =A0 =A02 =A0 =A0 =A0 /* critical conditions */
 #define LOG_ERR =A0 =A0 =A0 =A0 3 =A0 =A0 =A0 /* error conditions */
 #define LOG_WARNING =A0 =A0 4 =A0 =A0 =A0 /* warning conditions */
 #define LOG_NOTICE =A0 =A0 =A05 =A0 =A0 =A0 /* normal but significant con=

 #define LOG_INFO =A0 =A0 =A0 =A06 =A0 =A0 =A0 /* informational */
 #define LOG_DEBUG =A0 =A0 =A0 7 =A0 =A0 =A0 /* 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 _fata=

 condition not be fatal if it were in release mode if it were fatal in deb=

 mode? Is it fatal or not? It seems to me like another needless complicati=


Barely a complication. dfatal looks as follow: debug alias log!(Severity.fatal) dfatal; /// ditto else alias log!(Severity.critical) dfatal; /// ditto
 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.
 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.
 Rich is a horrible name IMHO. It says nothing about what it actually is o=

 does. I'm not sure what a good name would be (BoolMessage?, LogResult?), =

 Rich by itself is very confusing and utterly uninformative.

the suggestions!
 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 =

 swap out loggers at runtime? Or is the idea that you'd swap out the
 Configuration?

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
 - Jonathan M Davis

Feb 17 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Feb 16, 2012 at 7:57 AM, S=F6nke Ludwig
<ludwig informatik.uni-luebeck.de> wrote:
 Am 16.02.2012 10:21, schrieb Jonathan M Davis:
 On Monday, February 13, 2012 16:50:04 David Nadlinger wrote:
 Please post all feedback in this thread, and remember: Although
 comprehensive reviews are obviously appreciated, short comments are ver=



 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 t=


 concept of verbosity on top of that. It's a needless complication.

 Also, _please_ add a debug level. Personally, I'd argue for simply copyi=


 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 beyo=


 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 t=


 and
 handle this is a needless complication. syslog has

 #define LOG_EMERG =A0 =A0 =A0 0 =A0 =A0 =A0 /* system is unusable */
 #define LOG_ALERT =A0 =A0 =A0 1 =A0 =A0 =A0 /* action must be taken imme=


 #define LOG_CRIT =A0 =A0 =A0 =A02 =A0 =A0 =A0 /* critical conditions */
 #define LOG_ERR =A0 =A0 =A0 =A0 3 =A0 =A0 =A0 /* error conditions */
 #define LOG_WARNING =A0 =A0 4 =A0 =A0 =A0 /* warning conditions */
 #define LOG_NOTICE =A0 =A0 =A05 =A0 =A0 =A0 /* normal but significant co=


 #define LOG_INFO =A0 =A0 =A0 =A06 =A0 =A0 =A0 /* informational */
 #define LOG_DEBUG =A0 =A0 =A0 7 =A0 =A0 =A0 /* 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 name=

 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
 So I see a point in the
 argument that vlog() allows everyone to be happy without endless numbers =

 predefined log levels.. however I'm also not quite convinced.


 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.=

 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 for=

 and info.write("") as the plain string version seems to be quite optimal =

 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 n=

 influence the program flow and should immediately understandable by anyon=

 who sees them. But something like log.warn/logf.warn or log.warn/log.warn=

 might also work if you really want the consistency...

info("%s message", Severity.info); info.write(Severity.info, " message); info.writef("%s message", Severity.info); Thanks! -Jose
 Rich is a horrible name IMHO. It says nothing about what it actually is =


 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


Feb 17 2012
prev sibling next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 2/13/2012 7:50 AM, David Nadlinger wrote:
 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.
Feb 17 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Fri, Feb 17, 2012 at 6:48 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 2/17/12 12:06 PM, Jose Armando Garcia wrote:
 info("%s message", Severity.info);

I think defaulting to formatted stuff may be confusing.

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.
From my experience I tend to write or log using a format string mainly

frameworks like gettext. Thoughts? -Jose
 Andrei

Feb 17 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Fri, Feb 17, 2012 at 7:12 PM, Walter Bright
<newshound2 digitalmars.com> wrote:
 On 2/13/2012 7:50 AM, David Nadlinger wrote:
 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.

Yep. I have been following that thread and your commits. I have a TODO for this. Thanks. -Jose
Feb 17 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Friday, 17 February 2012 at 06:39:29 UTC, H. S. Teoh wrote:
 […] 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
Feb 18 2012
prev sibling next sibling parent "Kalle Svensson" <kalle ieee.org> writes:
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
Feb 27 2012
prev sibling next sibling parent reply "Richard van Scheijen" <dlang mesadu.net> writes:
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.
Feb 29 2012
parent kennytm <kennytm gmail.com> writes:
"Richard van Scheijen" <dlang mesadu.net> wrote:
 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
 

Minor nit: if you rearrange it as AllowFlow / KnownEffect / KnownCause Then the description will correspond exactly to their integer values. 111 (7) = Trace 110 (6) = Info 101 (5) = Notice 100 (4) = Warning 011 (3) = Error 010 (2) = Critical 001 (1) = Severe 000 (0) = 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.

Mar 07 2012
prev sibling next sibling parent "Mikael Lindsten" <mikael lindsten.net> writes:
On Monday, 27 February 2012 at 18:10:15 UTC, Kalle Svensson wrote:
 * 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
Mar 01 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Mar 01, 2012 at 10:09:28AM +0100, Mikael Lindsten wrote:
 On Monday, 27 February 2012 at 18:10:15 UTC, Kalle Svensson wrote:
* I agree that it is a good idea just to use few log levels.


 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.
Mar 01 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Feb 29, 2012, at 4:13 PM, Richard van Scheijen wrote:

 When logging the severity level should convey a certain insight that =

These are: known-cause, known-effect and breaks-flow.
=20
 This creates the following matrix:
=20
 KC KE BF Severity
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 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
=20
 A known cause is when the developer knows why a log event is made. =

 A known effect is when he/she knows what happens after. Basically, you =

=20
 When a severity should only be handled by a debugger, the normal debug =

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).=
Mar 01 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Wed, 29 Feb 2012 18:13:30 -0600, Richard van Scheijen <dlang mesadu.net>
wrote:

 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.

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.");
Mar 01 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Mar 01, 2012 at 08:24:31PM -0600, Robert Jacques wrote:
 On Wed, 29 Feb 2012 18:13:30 -0600, Richard van Scheijen <dlang mesadu.net>
wrote:
 
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.

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.");

+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
Mar 02 2012
prev sibling next sibling parent Brad Roberts <braddr puremagic.com> writes:
On 2/13/2012 7:50 AM, David Nadlinger wrote:
 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

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
Mar 02 2012
prev sibling next sibling parent "mist" <none none.none> writes:
 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!
Mar 03 2012
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 13 Feb 2012 10:50:04 -0500, David Nadlinger <see klickverbot.at>  
wrote:

 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
Mar 05 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 11:36 AM, Jose Armando Garcia wrote:
 import someSymboleThatDoesntCollide = std.log;

I think this works better: static import log = std.log; Andrei
Mar 06 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer 
wrote:
 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.
 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?
 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
Mar 05 2012
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger <see klickverbot.at>=
  =

wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer wrote:
 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 i=


 a myriad of places.  Given that D's symbol lookup rules allow shadowi=


 of global symbols, this does not work out very well.

Originally, the code used log!info and so on, but it was changed to th=

 current design right after review begin, the rationale being that you =

 could always use =C2=BBimport log =3D std.log=C2=AB if you want the ex=

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 }
 Like others have stated, I think vlog is a) confusing, and b)  =


 unnecessary.  Even reading the docs, I can't understand what it's use=


 for, and why it has such different syntax than the normal logging stu=


 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 featur=

 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 d= o = make more sense than the vlog docs. This may be a doc issue. I'll have to think about it some more. -Steve
Mar 05 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-06 02:32, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 02:22:05 so wrote:
 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
Mar 05 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-06 08:54, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 08:46:14 Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 02:22:05 so wrote:
 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
Mar 06 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 09:14:16 so wrote:
 On Tuesday, 6 March 2012 at 07:46:14 UTC, Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:
 
 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
Mar 06 2012
prev sibling next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 12:25 AM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Tuesday, March 06, 2012 09:14:16 so wrote:
 On Tuesday, 6 March 2012 at 07:46:14 UTC, Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:

 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.

What is wrong with: import log = std.log; log.info("cool"); Thanks, -Jose
 - Jonathan M Davis

Mar 06 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 11:39 AM, Jose Armando Garcia wrote:
 Seriously everyone. What are we spending some much effort on this?
 What is wrong with:

 import log = std.log;
 log.info("cool");

Indeed I think that should be fine. Thanks, Andrei
Mar 06 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 06, 2012 at 11:45:47AM -0800, Andrei Alexandrescu wrote:
 On 3/6/12 11:39 AM, Jose Armando Garcia wrote:
Seriously everyone. What are we spending some much effort on this?
What is wrong with:

import log = std.log;
log.info("cool");

Indeed I think that should be fine.

+1. I think std.log is ready to merge, as is. T -- Questions are the beginning of intelligence, but the fear of God is the beginning of wisdom.
Mar 06 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 6, 2012, at 11:39 AM, Jose Armando Garcia wrote:

 Seriously everyone. What are we spending some much effort on this?
 What is wrong with:
=20
 import log =3D std.log;
 log.info("cool");

Why should the default be unqualified names? Is this simply a desire to = not change std.log so we can just get it in already?=
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 12:43 PM, Sean Kelly <sean invisibleduck.org> wrote:
 On Mar 6, 2012, at 11:39 AM, Jose Armando Garcia wrote:

 Seriously everyone. What are we spending some much effort on this?
 What is wrong with:

 import log =3D std.log;
 log.info("cool");

Why should the default be unqualified names? =A0Is this simply a desire t=

What are you proposing? struct Log { static alias log!Severity.info info; ... } I am not exactly sure when this idiom became popular. I don't know if this is an C++ idiom or a Java idiom but I do know that it is a broken hack. C++ developers use it because the name-spacing facility is limiting. Java uses it because everything is a class and they don't have the concept of compile time objects. We don't need this hack in D. D's module mechanism make this C++/Java idiom unnecessary. Thanks, -Jose
Mar 06 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
Sorry. For some reason I thought info was callable directly without the lead=
ing log portion.=20

On Mar 6, 2012, at 1:37 PM, Jose Armando Garcia <jsancio gmail.com> wrote:

 On Tue, Mar 6, 2012 at 12:43 PM, Sean Kelly <sean invisibleduck.org> wrote=

 On Mar 6, 2012, at 11:39 AM, Jose Armando Garcia wrote:
=20
 Seriously everyone. What are we spending some much effort on this?
 What is wrong with:
=20
 import log =3D std.log;
 log.info("cool");

Why should the default be unqualified names? Is this simply a desire to n=


=20
 What are you proposing?
=20
 struct Log {
  static alias log!Severity.info info;
  ...
 }
=20
 I am not exactly sure when this idiom became popular. I don't know if
 this is an C++ idiom or a Java idiom but I do know that it is a broken
 hack. C++ developers use it because the name-spacing facility is
 limiting. Java uses it because everything is a class and they don't
 have the concept of compile time objects. We don't need this hack in
 D. D's module mechanism make this C++/Java idiom unnecessary.
=20
=20
 Thanks,
 -Jose

Mar 06 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 14:39:28 -0500, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Tue, Mar 6, 2012 at 12:25 AM, Jonathan M Davis <jmdavisProg gmx.com>  
 wrote:
 On Tuesday, March 06, 2012 09:14:16 so wrote:
 On Tuesday, 6 March 2012 at 07:46:14 UTC, Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:

 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.


Because naming is important. It's very difficult to change names once something is released. I seriously could care less about implementation (didn't even look at it). That can be fixed. Naming can't.
 What is wrong with:

 import log = std.log;
 log.info("cool");

What is wrong with import std.log; log.info("cool"); -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 07 Mar 2012 07:09:17 -0500, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Tue, 06 Mar 2012 14:39:28 -0500, Jose Armando Garcia  
 <jsancio gmail.com> wrote:

 On Tue, Mar 6, 2012 at 12:25 AM, Jonathan M Davis <jmdavisProg gmx.com>  
 wrote:
 On Tuesday, March 06, 2012 09:14:16 so wrote:
 On Tuesday, 6 March 2012 at 07:46:14 UTC, Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:

 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.


Because naming is important. It's very difficult to change names once something is released. I seriously could care less about implementation (didn't even look at it). That can be fixed. Naming can't.
 What is wrong with:

 import log = std.log;
 log.info("cool");

What is wrong with import std.log; log.info("cool");

alternatively: log_info("cool"); linfo("cool"); lginfo("cool"); There are so many choices besides just "info." We should use something else. -Steve
Mar 07 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Mar 7, 2012 at 6:39 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Wed, 07 Mar 2012 07:09:17 -0500, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 On Tue, 06 Mar 2012 14:39:28 -0500, Jose Armando Garcia
 <jsancio gmail.com> wrote:

 On Tue, Mar 6, 2012 at 12:25 AM, Jonathan M Davis <jmdavisProg gmx.com>
 wrote:
 On Tuesday, March 06, 2012 09:14:16 so wrote:
 On Tuesday, 6 March 2012 at 07:46:14 UTC, Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:

 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 =




 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.


Because naming is important. =A0It's very difficult to change names once something is released. =A0I seriously could care less about implementati=


 (didn't even look at it). =A0That can be fixed. =A0Naming can't.

 What is wrong with:

 import log =3D std.log;
 log.info("cool");

What is wrong with import std.log; log.info("cool");

alternatively: log_info("cool"); linfo("cool"); lginfo("cool"); There are so many choices besides just "info." =A0We should use something else.

Lets flip the question. Why are you against: import log =3D std.log; Thanks, -Jose
 -Steve

Mar 11 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 11, 2012, at 10:26 PM, Jose Armando Garcia <jsancio gmail.com> wrote:

 On Wed, Mar 7, 2012 at 6:39 AM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 
 
 alternatively:
 
 log_info("cool");
 linfo("cool");
 lginfo("cool");
 
 There are so many choices besides just "info."  We should use something
 else.
 

Lets flip the question. Why are you against: import log = std.log;

Which is the more common case?
Mar 11 2012
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 12 Mar 2012 01:26:54 -0400, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Wed, Mar 7, 2012 at 6:39 AM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Wed, 07 Mar 2012 07:09:17 -0500, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 What is wrong with

 import std.log;
 log.info("cool");

alternatively: log_info("cool"); linfo("cool"); lginfo("cool"); There are so many choices besides just "info." We should use something else.

Lets flip the question. Why are you against: import log = std.log;

I'm against having a requirement (or at least a strong suggestion) to import std.log in a certain way other than import std.log. There are a couple problems with this: 1. Almost all code examples in modules use import modulename; They don't have some documentation that says "you should probably import modulename by import modulename = modulename". For an example of this, see http://www.dsource.org/projects/tango/docs/stable/tango.io.Path.html 2. With no guarantees that everyone will use "log" as the symbol (or even use the symbol), you potentially have several files using std.log under different symbols. For example, someone might prefer "logger" or "lg". This just makes things more confusing than is necessary. I'm not actually against using this technique, I'm just against making it standard practice. I feel using a naming scheme which eliminates having to use this trick to be able to keep your existing names and/or use these common names as members would foster more uniform code and usage. That's all. Yes, this is a form of bikeshedding, but it's one of those things that will be difficult to change later. Even just changing the names of the functions which log to something less common, like I stated above, could be worth a lot. I won't vote against the lib if this is my only objection, but I do think it's important. If others don't, well, I guess we'll see what happens. I likely will be using import log = std.log whenever I use it. -Steve
Mar 12 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer 
wrote:
 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger 
 <see klickverbot.at> wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer 
 wrote:
 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 }

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;
Mar 05 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 05 Mar 2012 20:22:05 -0500, so <so so.so> wrote:

 On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer wrote:
 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger  =


 <see klickverbot.at> wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer wrote:=



 The log aliases use names that are too common.  I think log.info is=




 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 tha=



 you could always use =C2=BBimport log =3D std.log=C2=AB if you want =



 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 }

That is not a counter-argument to something related to this library bu=

 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 pa=

 of phobos, standard library. Which requires everyone to adopt. When yo=

 see codes like this (below), you don't blame standard library designer=

 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 candidat= es = 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
Mar 05 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 02:22:05 so wrote:
 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
Mar 05 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Tuesday, 6 March 2012 at 01:30:41 UTC, Steven Schveighoffer 
wrote:

 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.
Mar 05 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Tuesday, 6 March 2012 at 01:33:05 UTC, Jonathan M Davis wrote:

 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".
Mar 05 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Mon, 05 Mar 2012 19:22:05 -0600, so <so so.so> wrote:
 On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer
 wrote:
 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger
 <see klickverbot.at> wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer
 wrote:
 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 }

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.
Mar 05 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 08:46:14 Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 02:22:05 so wrote:
 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
Mar 05 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Tuesday, 6 March 2012 at 07:46:14 UTC, Jacob Carlborg wrote:
 On 2012-03-06 02:32, Jonathan M Davis wrote:

 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?
Mar 06 2012
prev sibling next sibling parent "so" <so so.so> writes:
On Tuesday, 6 March 2012 at 03:11:11 UTC, Robert Jacques wrote:

 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 :)
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 27, 2012 at 10:10 AM, Kalle Svensson <kalle ieee.org> wrote:
 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.

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.
 =A0 =A0///Kalle

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen <dlang mesadu.net> wr=
ote:
 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
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 1 =A01 =A00 =A0Trace
 0 =A01 =A00 =A0Info
 1 =A00 =A00 =A0Notice
 0 =A00 =A00 =A0Warning
 1 =A01 =A01 =A0Error
 0 =A01 =A01 =A0Critical
 1 =A00 =A01 =A0Severe
 0 =A00 =A01 =A0Fatal

 A known cause is when the developer knows why a log event is made. e.g.: =

 you cannot open a file, you do not know why.
 A known effect is when he/she knows what happens after. Basically, you ca=

 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 (=3D 3^3) configuration combinations. To implement this we need 3 configuration nobs with 3 values (on, off, both). Thoughts? -Jose
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Mar 1, 2012 at 6:38 AM, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:
 On Thu, Mar 01, 2012 at 10:09:28AM +0100, Mikael Lindsten wrote:
 On Monday, 27 February 2012 at 18:10:15 UTC, Kalle Svensson wrote:
* I agree that it is a good idea just to use few log levels.


 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
 T

 --
 What's a "hot crossed bun"? An angry rabbit.

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Mar 1, 2012 at 4:59 PM, Sean Kelly <sean invisibleduck.org> wrote:
 On Feb 29, 2012, at 4:13 PM, Richard van Scheijen wrote:

 When logging the severity level should convey a certain insight that the=


re: known-cause, known-effect and breaks-flow.
 This creates the following matrix:

 KC KE BF Severity
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 1 =A01 =A00 =A0Trace
 0 =A01 =A00 =A0Info
 1 =A00 =A00 =A0Notice
 0 =A00 =A00 =A0Warning
 1 =A01 =A01 =A0Error
 0 =A01 =A01 =A0Critical
 1 =A00 =A01 =A0Severe
 0 =A00 =A01 =A0Fatal

 A known cause is when the developer knows why a log event is made. e.g.:=


 A known effect is when he/she knows what happens after. Basically, you c=


 When a severity should only be handled by a debugger, the normal debug s=


 This is a really great breakdown of the log levels. =A0I've never seen it=

found is primarily regarding what person should see a particular log line,= and then only differentiated between INFO and ERROR messages. =A0Roughly:
 * Developer-Trace
 * Developer-Info
 * Developer-Error
 * Admin-Info
 * Admin-Error
 * All-Fatal

 Typically, the Developer and Admin logs go to different locations, in whi=

ide added context. =A0In any case, what I've found is that with more than a= few log levels, people typically don't know how to classify things, severi= ty becomes arbitrary, and log-levels are rendered largely useless. =A0So fr= om 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
Mar 06 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen <dlang mesadu.net>  
 wrote:
 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.

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?
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Mar 1, 2012 at 6:24 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Wed, 29 Feb 2012 18:13:30 -0600, Richard van Scheijen <dlang mesadu.ne=

 wrote:

 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
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 1 =A01 =A00 =A0Trace
 0 =A01 =A00 =A0Info
 1 =A00 =A00 =A0Notice
 0 =A00 =A00 =A0Warning
 1 =A01 =A01 =A0Error
 0 =A01 =A01 =A0Critical
 1 =A00 =A01 =A0Severe
 0 =A00 =A01 =A0Fatal

 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 hel=

 cement this concept. It would also allow self documenting code, like:

 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
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 9:32 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia <jsancio gmail.co=

 wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen <dlang mesadu.net>
 wrote:
 When logging the severity level should convey a certain insight that th=



 developer has about the code. This can be done with a 3 bit field. Thes=



 are: known-cause, known-effect and breaks-flow.

 This creates the following matrix:

 KC KE BF Severity
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 1 =A01 =A00 =A0Trace
 0 =A01 =A00 =A0Info
 1 =A00 =A00 =A0Notice
 0 =A00 =A00 =A0Warning
 1 =A01 =A01 =A0Error
 0 =A01 =A01 =A0Critical
 1 =A00 =A01 =A0Severe
 0 =A00 =A01 =A0Fatal

 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 (=3D 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 wi=

 a combinatorial approach, shouldn't it be 2^8 =3D 256, not 3^3 =3D 27 val=

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.
Mar 06 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 11:44:13 -0600, Jose Armando Garcia  
<jsancio gmail.com> wrote:
 On Tue, Mar 6, 2012 at 9:32 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia  
 <jsancio gmail.com>
 wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen  
 <dlang mesadu.net>
 wrote:
 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.

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.
Mar 06 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 11:34:21 -0600, Jose Armando Garcia  
<jsancio gmail.com> wrote:
 On Thu, Mar 1, 2012 at 6:24 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Wed, 29 Feb 2012 18:13:30 -0600, Richard van Scheijen  
 <dlang mesadu.net>
 wrote:

 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.

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.");

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.
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Fri, Mar 2, 2012 at 12:56 AM, Brad Roberts <braddr puremagic.com> wrote:
 On 2/13/2012 7:50 AM, David Nadlinger wrote:
 There are several modules in the review queue right now, and to get thin=


 review of Jose's std.log proposal. Barring any objections, the review pe=


 March 6th, followed by a week of voting.

 ---
 Code: https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a=


 Docs: http://jsancio.github.com/phobos/phobos/std_log.html

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

 Depends on: https://github.com/D-Programming-Language/druntime/pull/141 =


 ---

 Earlier drafts of this library were discussed last year, just search the=


 I think getting this right is vitally important so that we can avoid an =


 libraries like in Java. Thus, I'd warmly encourage everyone to actively =


 logging solution you might already be using in your project.

 Please post all feedback in this thread, and remember: Although comprehe=


 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 fr=

 Having log levels that change execution flow is evil. =A0It's it the same=

 having side effects, imho.

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?
 2) Apps over a certain size (that tends to not be all that big, a few 10'=

 module based logging. =A0This proposal includes a set of log levels that =

 separate set that do. =A0The 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.
 3) The conditional stuff seems cute, but I can't recall ever wanting it i=

 4) I don't see an obvious facility for changing log parameters at runtime=

 array as if it came from command line parameters and calling parseCommand=

 that has a configuration api or notices a config file has been updated or=


If you want to change the log level at runtime you can just: std.log.config.minSeverity =3D 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.
 5) The logger severity symbols part should allow more than single charact=

 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.
 6) Is the log system thread safe? =A0I see that it's at least thread awar=


Yes, it is. It is probably to conservative in this regard. I need to go back and do a lot performances improvements.
 7) The logger setter docs says it's an error to change the logger after a=

 hurt. =A0It's not at all uncommon for an app to want to log some set of e=

 execute the code that configures the logger. =A0use case: reading a confi=

 process the config file properly.

I will remove it. Thanks!
 Later,
 Brad

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 5, 2012 at 1:55 PM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Mon, 13 Feb 2012 10:50:04 -0500, David Nadlinger <see klickverbot.at>
 wrote:

 There are several modules in the review queue right now, and to get thin=


 going, I have volunteered to manage the review of Jose's std.log proposa=


 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. =A0In particular, I do=

 think the logging library should have any business throwing exceptions or
 errors. =A0It should be invisible to the application. =A0The equivalent f=

 can be had by giving a wrapper function (i.e. log this message at the fat=

 level, and then throw an error). =A0A use case I can see is printing seve=

 fatal log messages before exiting.

You can implement the above by using std.log.error
 The log aliases use names that are too common. =A0I think log.info is a b=

 symbol for logging than just 'info', which could be a symbol in a myriad =

 places. =A0Given that D's symbol lookup rules allow shadowing of global
 symbols, this does not work out very well.

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 =3D std.log; log.info("hello world");
 Like others have stated, I think vlog is a) confusing, and b) unnecessary=

 =A0Even reading the docs, I can't understand what it's used for, and why =

 has such different syntax than the normal logging stuff.

find it useful. If you are interested on a different explaination: http://google-glog.googlecode.com/svn/trunk/doc/glog.html
 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!
 Do we have to make the logger a singleton? =A0I'd like to see cases where=

 can have different log instances. =A0For example, an instance I can
 enable/disable per class type, or an instance that logs to a diffferent
 backend. =A0Or a non-shared instance which does not need to handle thread=

 issues (i.e. a per-thread file log).=A0Does this help with the vlog issue=


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.)
 -Steve

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 5, 2012 at 3:51 PM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger <see klickverbot.at>
 wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer wrote:
 The log aliases use names that are too common. =A0I think log.info is a
 better symbol for logging than just 'info', which could be a symbol in =



 myriad of places. =A0Given that D's symbol lookup rules allow shadowing=



 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 co=


 always use =BBimport log =3D std.log=AB if you want the extra namespace.

That doesn't help. =A0Software isn't static. import std.log;

 import other; // defines B

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

 =A0 }
 }

 other.d:

 class B
 {
 =A0 int info; // added later

 }

 Like others have stated, I think vlog is a) confusing, and b)
 unnecessary. =A0Even reading the docs, I can't understand what it's use=



 and why it has such different syntax than the normal logging stuff.

I think this been modelled after glog's verbose logging support [1], jus=


 like much of the rest of the design (by the way, I think a note about th=


 should added somewhere in the module docs). Does the feature as describe=


 the glog docs make sense to you?

It's good to know the root of where this comes from. =A0The docs in glog =

 make more sense than the vlog docs.

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

 -Steve

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 5, 2012 at 5:32 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Tuesday, March 06, 2012 02:22:05 so wrote:
 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.

using namesapce std; matrix vector = new Matrix(...) The variable vector conflicts with std::vector. Honestly, I can sit here and come up with 10s or 100s of example where you want to use a symbol that is expose by another module. You don't have to go far just look at druntime and phobos. This the exact reason why modules and namespace exist and one of the reason why people hate C's preprocessor macros. D solved this problem years ago.
 - Jonathan M Davis

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 5, 2012 at 5:30 PM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Mon, 05 Mar 2012 20:22:05 -0500, so <so so.so> wrote:

 On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer wrote:
 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger <see klickverbot.at=


 wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer wrote:
 The log aliases use names that are too common. =A0I think log.info is=





 better symbol for logging than just 'info', which could be a symbol i=





 myriad of places. =A0Given that D's symbol lookup rules allow shadowi=





 global symbols, this does not work out very well.

Originally, the code used log!info and so on, but it was changed to th=




 current design right after review begin, the rationale being that you =




 always use =BBimport log =3D std.log=AB if you want the extra namespac=




 That doesn't help. =A0Software isn't static.

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

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

 other.d:

 class B
 {
 =A0 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 =


 codes like this (below), you don't blame standard library designers do y=


 using namespace std;
 int cout;

Except 'info', 'error', 'warning' are all common names, likely to be a ve=

 attractive name for something that has nothing to do with (or cares about=

 logging. =A0cout is not a common name or even an english word, so it's
 unlikely someone has or wants to create a cout member.

name for a symbol in std.stdio. I suspect that the only reason that it is there is to keep C developer migrating to D happy. It should probably just be "out" like Java (System.out) and C# (Console.Out).
 Couple this with the fact that all of these are nouns -- likely candidate=

 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 comm=

 like linfo instead of just info.

 -Steve

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 5, 2012 at 7:11 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Mon, 05 Mar 2012 19:22:05 -0600, so <so so.so> wrote:
 On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer
 wrote:
 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger
 <see klickverbot.at> wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer
 wrote:
 The log aliases use names that are too common. =A0I think
 log.info is a better symbol for logging than just 'info',
 which could be a symbol in a myriad of places. =A0Given 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 =BBimport log =3D std.log=AB if you want the extra namespace.

That doesn't help. =A0Software isn't static. import std.log; import other; // defines B class A : B { =A0 void foo() =A0 { =A0 =A0 =A0info("some info message"); // error! int isn't a function! =A0 } } other.d: class B { =A0 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 t=

 D ecosystem at large. Yes, new code can be expected to avoid these names,
 but all existing code has to be retrofitted and fixed.

Not is doesn't. First, it will only break your code if you import std.log. If you are now importing std.log that means you are already modifying the code. If you don't want to modify existing code when adding your changes just: import someSymboleThatDoesntCollide =3D std.log; Pick your poison. Thanks, -Jose
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 10:11 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:44:13 -0600, Jose Armando Garcia <jsancio gmail.co=

 wrote:
 On Tue, Mar 6, 2012 at 9:32 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia
 <jsancio gmail.com>
 wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen <dlang mesadu.ne=




 wrote:
 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
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 1 =A01 =A00 =A0Trace
 0 =A01 =A00 =A0Info
 1 =A00 =A00 =A0Notice
 0 =A00 =A00 =A0Warning
 1 =A01 =A01 =A0Error
 0 =A01 =A01 =A0Critical
 1 =A00 =A01 =A0Severe
 0 =A00 =A01 =A0Fatal

 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, yo=





 can
 tell if it is a catch-all by this flag.

 When a severity should only be handled by a debugger, the normal debu=





 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 (=3D 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 =3D 256, not 3^3 =3D 27 v=



 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.=

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

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

 I don't see the problem with including both methods and a large advantage=

 having a standardized severity framework.

Interesting. If you find this useful, I think we can add this in a future release as it shouldn't break existing modules that maybe using the library.
Mar 06 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Tuesday, 6 March 2012 at 19:47:50 UTC, Andrei Alexandrescu 
wrote:
 On 3/6/12 11:36 AM, Jose Armando Garcia wrote:
 import someSymboleThatDoesntCollide = std.log;

I think this works better: static import log = std.log;

Isn't this just another case of DMD silently accepting superfluous attributes/modifiers? David
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Feb 13, 2012 at 7:50 AM, David Nadlinger <see klickverbot.at> wrote=
:
 There are several modules in the review queue right now, and to get thing=

 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.

Hi everyone, I have been tracking all the changes we need to make immediately and things we can add in the future without break backward compatibility if have access to trello go here: https://trello.com/card/std-log/4f33d3c6542c156960533efb/1# Exporting things form trello looks like a pain but here it is: Future: 1. Allowing filtering of regular log messages (like info, warning, etc) based on the module. Similar to how vlog works. 2. Add support for custom line formatters 3. Talk about adding config.setSeverity(...) which is a union of all the severity specified. The logical OR operator is not going to work because internally the values are 0,1, etc. and we use them to index into an array. One solution is to pass an array to config.setSeverity(...) Fix now: 1. Add thread name attribute to the default logger 2. Check that the example compile 3. Come up with a better name for Rich and rich template 4. Add safe pure nothrow const to as many methods as possible 5. Remove check when setting Configuration.logger Note: There were a few other things that were suggested here that I have already fixed. Need to look at my commits for this. Thanks, -Jose
 ---
 Code:
 https://github.com/jsancio/phobos/commit/d114420e0791c704f6899d81a0293cbd=

 Docs: http://jsancio.github.com/phobos/phobos/std_log.html

 Known remaining issues:
 =A0- Proof-reading of the docs is required.
 =A0- 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 =

 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'=

 warmly encourage everyone to actively try out the module or compare it wi=

 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

Mar 06 2012
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
On Mar 6, 2012, at 11:59 AM, Jose Armando Garcia wrote:
=20
 Future:
=20
 1. Allowing filtering of regular log messages (like info, warning,
 etc) based on the module. Similar to how vlog works.
 2. Add support for custom line formatters
 3. Talk about adding config.setSeverity(...) which is a union of all
 the severity specified. The logical OR operator is not going to work
 because internally the values are 0,1, etc. and we use them to index
 into an array. One solution is to pass an array to
 config.setSeverity(=85)

For future enhancements, I'd just reference the docs for Boost.Log :-p=
Mar 06 2012
prev sibling next sibling parent Brad Roberts <braddr puremagic.com> writes:
On Tue, 6 Mar 2012, Jose Armando Garcia wrote:

 Future:
 
 1. Allowing filtering of regular log messages (like info, warning,
 etc) based on the module. Similar to how vlog works.

Once you add module filtering to the regularly log messages, what's the point of having the separate vlog? I think this needs to be figured out before merge, not at some vague future.
 Fix now:
 
 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. From the feed back, I am not alone in thinking that. I don't believe that "well, don't use those log levels" is a workaround if for no other reason that there will be libraries that contain them and that becomes a "dont use those libraries either" response. My 2 cents, Brad
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 1:08 PM, Brad Roberts <braddr puremagic.com> wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:

 Future:

 1. Allowing filtering of regular log messages (like info, warning,
 etc) based on the module. Similar to how vlog works.

Once you add module filtering to the regularly log messages, what's the point of having the separate vlog? =A0I think this needs to be figured ou=

 before merge, not at some vague future.

That is true the need for vlog is lessen from a configuration point of view but not from a performance point of view. Adding module filtering to info, warning, etc increases the computational cost of determining if you should log. Right now that computational cost is constant. It is equal to a comparison operation. If you want module base filtering the computational complexity will probably be O(n + l) where n is the number of modules/entry in the filter and l is the minimum between the length of the module/file name and the length of the filters. This makes info, warning, error a great tool to use in production across your program. While you can use vlog on a case by case basis in testing environments. Thanks, -Jose
 Fix now:

 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. =A0From the feed back, I=

 not alone in thinking that. =A0I don't believe that "well, don't use thos=

 log levels" is a workaround if for no other reason that there will be
 libraries that contain them and that becomes a "dont use those libraries
 either" response.

 My 2 cents,
 Brad

Mar 06 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 13:41:32 -0600, Jose Armando Garcia  
<jsancio gmail.com> wrote:
 On Tue, Mar 6, 2012 at 10:11 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:44:13 -0600, Jose Armando Garcia  
 <jsancio gmail.com>
 wrote:
 On Tue, Mar 6, 2012 at 9:32 AM, Robert Jacques <sandford jhu.edu>  
 wrote:
 On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia
 <jsancio gmail.com>
 wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen  
 <dlang mesadu.net>
 wrote:
 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.

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.

Interesting. If you find this useful, I think we can add this in a future release as it shouldn't break existing modules that maybe using the library.

This began as a discussion regarding Richard's organization of logging severity. That organization isn't something that can be trivially included at a later date.
Mar 06 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 13:32:37 -0600, Jose Armando Garcia  =

<jsancio gmail.com> wrote:

 On Mon, Mar 5, 2012 at 5:30 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Mon, 05 Mar 2012 20:22:05 -0500, so <so so.so> wrote:

 On Monday, 5 March 2012 at 23:51:29 UTC, Steven Schveighoffer wrote:=



 On Mon, 05 Mar 2012 18:30:03 -0500, David Nadlinger  =




 <see klickverbot.at>
 wrote:

 On Monday, 5 March 2012 at 21:55:08 UTC, Steven Schveighoffer wrot=





 The log aliases use names that are too common.  I think log.info =






 a
 better symbol for logging than just 'info', which could be a symb=






 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 t=





 the
 current design right after review begin, the rationale being that =





 you could
 always use =BBimport log =3D std.log=AB if you want the extra name=





 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
 }

That is not a counter-argument to something related to this library =



 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 =



 you?

 using namespace std;
 int cout;

Except 'info', 'error', 'warning' are all common names, likely to be =


 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.

name for a symbol in std.stdio. I suspect that the only reason that it=

 is there is to keep C developer migrating to D happy. It should
 probably just be "out" like Java (System.out) and C# (Console.Out).

D doesn't have a cout, in stdio or elsewhere.
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 1:08 PM, Brad Roberts <braddr puremagic.com> wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:

 Future:

 1. Allowing filtering of regular log messages (like info, warning,
 etc) based on the module. Similar to how vlog works.

Once you add module filtering to the regularly log messages, what's the point of having the separate vlog? =A0I think this needs to be figured ou=

 before merge, not at some vague future.

 Fix now:

 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. =A0From the feed back, I=

 not alone in thinking that. =A0I don't believe that "well, don't use thos=

 log levels" is a workaround if for no other reason that there will be
 libraries that contain them and that becomes a "dont use those libraries
 either" response.

Yeah. I completely understand your point. I don't have a technical argument for adding or removing fatal and critical. The only advantage is that the developer is explicitly telling the logging framework when the application will/may terminate. Instead of everyone having to write: void critical(...) { log.error(...); // force a flush. currently there is no way of expressing this so we need to put this throw new ...; } and: void fatal(...) { log.error(...); // force a flush. currently there is no way of expressing this so we need to put this assert(true); }
 My 2 cents,
 Brad

Mar 06 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I still don't understand how to set the filename of the log file. Has
this been added yet?
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 2:44 PM, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 I still don't understand how to set the filename of the log file. Has
 this been added yet?

http://jsancio.github.com/phobos/phobos/std_log.html#fileNamePrefixes
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 2:03 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 13:41:32 -0600, Jose Armando Garcia <jsancio gmail.co=

 wrote:
 On Tue, Mar 6, 2012 at 10:11 AM, Robert Jacques <sandford jhu.edu> wrote=


 On Tue, 06 Mar 2012 11:44:13 -0600, Jose Armando Garcia
 <jsancio gmail.com>
 wrote:
 On Tue, Mar 6, 2012 at 9:32 AM, Robert Jacques <sandford jhu.edu> wrot=




 On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia
 <jsancio gmail.com>
 wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen
 <dlang mesadu.net>
 wrote:
 When logging the severity level should convey a certain insight tha=







 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
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 1 =A01 =A00 =A0Trace
 0 =A01 =A00 =A0Info
 1 =A00 =A00 =A0Notice
 0 =A00 =A00 =A0Warning
 1 =A01 =A01 =A0Error
 0 =A01 =A01 =A0Critical
 1 =A00 =A01 =A0Severe
 0 =A00 =A01 =A0Fatal

 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 loggi=






 info events I should probably also log error events.

 If we go with a mechanism like the one you describe above there is n=






 order so the configuration is a little more complicated or verbose I
 should say. Instead of saying we should log everything "greater" tha=






 warning the user needs to say that they want to log known-cause,
 known-effect, breaks-flow events. This mean that there are 27 (=3D 3=






 configuration combinations. To implement this we need 3 configuratio=






 nobs with 3 values (on, off, both).

 Thoughts?
 -Jose

There are only 8 possible configurations and they are nicely ordered =





 terms of severity. So I don't see this as a problem. Also, if you wen=





 with
 a combinatorial approach, shouldn't it be 2^8 =3D 256, not 3^3 =3D 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 orderin=



 config.minSeverity(Severity.Warning);

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

 I don't see the problem with including both methods and a large advanta=



 to
 having a standardized severity framework.

Interesting. If you find this useful, I think we can add this in a future release as it shouldn't break existing modules that maybe using the library.

This began as a discussion regarding Richard's organization of logging severity. That organization isn't something that can be trivially include=

 at a later date.

Please be explicit in what you are requesting... If you have an API even be= tter.
Mar 06 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 3/7/12, Jose Armando Garcia <jsancio gmail.com> wrote:
 http://jsancio.github.com/phobos/phobos/std_log.html#fileNamePrefixes

That was what I was looking for but I didn't find it at first. I think that info about what the defaults are ([program].[hostname].[user].[severity].log.[datetime].[pid]) might be useful somewhere at the top. But that's just my 2 cents..
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 3:27 PM, Andrej Mitrovic
<andrej.mitrovich gmail.com> wrote:
 On 3/7/12, Jose Armando Garcia <jsancio gmail.com> wrote:
 http://jsancio.github.com/phobos/phobos/std_log.html#fileNamePrefixes

That was what I was looking for but I didn't find it at first. I think that info about what the defaults are ([program].[hostname].[user].[severity].log.[datetime].[pid]) might be useful somewhere at the top. But that's just my 2 cents..

Yeah. I am not terribly happy how ddoc and dlang.org organizes the documentation. I have been thinking of duplicating a lot of the documentation to the top but I have two main objections that are holding back. 1. document duplication and 2. overloading the user with information. I would like the top of the document with enough information and example for the regular user to just start logging. They can later come back and read the whole thing when they want to configure and tweak things. Thoughts? Thanks, -Jose
Mar 06 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 13:08:42 Brad Roberts wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:
 Future:
 
 1. Allowing filtering of regular log messages (like info, warning,
 etc) based on the module. Similar to how vlog works.

Once you add module filtering to the regularly log messages, what's the point of having the separate vlog? I think this needs to be figured out before merge, not at some vague future.
 Fix now:
 
 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. From the feed back, I am not alone in thinking that. I don't believe that "well, don't use those log levels" is a workaround if for no other reason that there will be libraries that contain them and that becomes a "dont use those libraries either" response.

Agreed. The logging functions should _not_ throw. - Jonathan M Davis
Mar 06 2012
prev sibling next sibling parent reply Geoffrey Biggs <geoffrey.biggs aist.go.jp> writes:
On 07/03/12 09:25, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 13:08:42 Brad Roberts wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:
 Fix now:

 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. From the feed back, I am not alone in thinking that. I don't believe that "well, don't use those log levels" is a workaround if for no other reason that there will be libraries that contain them and that becomes a "dont use those libraries either" response.

Agreed. The logging functions should _not_ throw.

+1. Is std.log a logging library or a complete error management library? If it's a logging library, the last thing it should be doing is affecting program flow. In the case of fatal, in particular, the program may need to do something else after logging the fatal error before terminating. You could argue that the program should do that before logging the fatal error, but I don't think that's nice semantics. On the other hand, if it's a complete error management library, it probably shouldn't be called std.log. That's my opinion as an uninformed user. Geoff
Mar 06 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 4:31 PM, Geoffrey Biggs wrote:
 On 07/03/12 09:25, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 13:08:42 Brad Roberts wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:
 Fix now:

 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. From the feed back, I am not alone in thinking that. I don't believe that "well, don't use those log levels" is a workaround if for no other reason that there will be libraries that contain them and that becomes a "dont use those libraries either" response.

Agreed. The logging functions should _not_ throw.

+1. Is std.log a logging library or a complete error management library? If it's a logging library, the last thing it should be doing is affecting program flow. In the case of fatal, in particular, the program may need to do something else after logging the fatal error before terminating. You could argue that the program should do that before logging the fatal error, but I don't think that's nice semantics. On the other hand, if it's a complete error management library, it probably shouldn't be called std.log.

I don't see why the agitation around this particular matter. It's a matter of convenience, much like writeln (as opposed to just write). Let's admit that it often happens that you want to log some troublesome stuff just before throwing an exception with essentially the same message, so the thing is shown on the screen and also persisted in the log. Without a critical level, the pattern would be: string message = stuff() + ": " + moreStuff(); log.error(message); throw new Exception(message); It's nice to encapsulate this frequent pattern, hence: log.critical(stuff() + ": " + moreStuff()); If you want to log but not throw, use log.error. I don't think the response "dont use those libraries either" is meaningful. Andrei
Mar 06 2012
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 5:07 PM, Jonathan M Davis wrote:
 As it stands, std.log is conflating two separate concepts - logging and and
 error handling.

Throwing an exception is not error handling. If it were, so many entities would do so, the whole concept would become devoid of meaning. Andrei
Mar 06 2012
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 6:05 PM, Geoffrey Biggs wrote:
 That approach means that if I actually do have a fatal error, I can't
 mark it as such.

Use log.fatal for those. Andrei
Mar 06 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 06, 2012 at 03:52:56PM -0800, Jose Armando Garcia wrote:
 On Tue, Mar 6, 2012 at 3:27 PM, Andrej Mitrovic
 <andrej.mitrovich gmail.com> wrote:
 On 3/7/12, Jose Armando Garcia <jsancio gmail.com> wrote:
 http://jsancio.github.com/phobos/phobos/std_log.html#fileNamePrefixes

That was what I was looking for but I didn't find it at first. I think that info about what the defaults are ([program].[hostname].[user].[severity].log.[datetime].[pid]) might be useful somewhere at the top. But that's just my 2 cents..

Yeah. I am not terribly happy how ddoc and dlang.org organizes the documentation. I have been thinking of duplicating a lot of the documentation to the top but I have two main objections that are holding back. 1. document duplication and 2. overloading the user with information. I would like the top of the document with enough information and example for the regular user to just start logging. They can later come back and read the whole thing when they want to configure and tweak things. Thoughts?

I don't like the current state of dlang.org docs either. There is little or no intro paragraph to explain what on earth the module is used for or why you should bother reading the rest of the page for the next hour or so. It also doesn't give any motivating examples (I'm thinking of std.range here) why this module is useful. I think a good intro is a must to good documentation. Include some code snippets to show typical usage of the module. How to change common settings. Some explanation of why the user might find the module helpful. It's OK to duplicate some docs here, within reason. It should also be concise without being uninformative. For example (from std.range): This module defines the notion of range (by the membership tests isInputRange, isForwardRange, isBidirectionalRange, isRandomAccessRange), range capability tests (such as hasLength or hasSlicing), and a few useful range incarnations. is concise, but not very informative. Why should the user care what a range is anyway? No explanation is given. Something like this may be a beginning to better documentation: This module defines the notion of a range. Ranges generalize the concept of arrays, lists, or anything that involves sequential access. This abstraction enables the same set of algorithms (see std.algorithm) to be used with a vast variety of different concrete types. For example, a linear search algorithm such as std.find works not just for arrays, but for linked-lists, input files, incoming network data, etc.. This module defines several templates (<!--insert list here-->)for testing whether a given object is a range, and what kind of range it is. It also lets you construct new ranges out of existing ranges. For example, retro lets you access a bidirectional range in reverse, cycle creates a range that is an endless repetition of the original range. ... ... Basically, you're writing an overview to the module, so highlight its main components, give some insight into why it's useful, etc., so that the user can make sense of the long list of declarations that follow. As it stands, std.range's page consists of a giant list of range-related declarations that gives no hint to the user as to how they all fit together. You basically have to wade through it until it somehow all "clicks" together. That is poor documentation. The overview should give some general categories of stuff that's found in the module (e.g. range tests, constructing new ranges, etc., as I've tried to do above in my one-shot attempt to improve std.range's docs). Include some examples of really clever stuff that you can do with the help of the module. Such examples are usually a very good way to get the user up-to-speed with what the module has to offer. T -- What doesn't kill me makes me stranger.
Mar 06 2012
parent David Gileadi <gileadis NSPMgmail.com> writes:
On 3/6/12 5:39 PM, H. S. Teoh wrote:
 I don't like the current state of dlang.org docs either. There is little
 or no intro paragraph to explain what on earth the module is used for or
 why you should bother reading the rest of the page for the next hour or
 so. It also doesn't give any motivating examples (I'm thinking of
 std.range here) why this module is useful.

 I think a good intro is a must to good documentation. Include some code
 snippets to show typical usage of the module. How to change common
 settings. Some explanation of why the user might find the module
 helpful. It's OK to duplicate some docs here, within reason. It should
 also be concise without being uninformative.

 For example (from std.range):

 	This module defines the notion of range (by the membership tests
 	isInputRange, isForwardRange, isBidirectionalRange,
 	isRandomAccessRange), range capability tests (such as hasLength
 	or hasSlicing), and a few useful range incarnations.

 is concise, but not very informative. Why should the user care what a
 range is anyway? No explanation is given. Something like this may be a
 beginning to better documentation:

 	This module defines the notion of a range. Ranges generalize the
 	concept of arrays, lists, or anything that involves sequential
 	access. This abstraction enables the same set of algorithms (see
 	std.algorithm) to be used with a vast variety of different
 	concrete types. For example, a linear search algorithm such as
 	std.find works not just for arrays, but for linked-lists, input
 	files, incoming network data, etc..

 	This module defines several templates (<!--insert list
 	here-->)for testing whether a given object is a range, and what
 	kind of range it is.

 	It also lets you construct new ranges out of existing ranges.
 	For example, retro lets you access a bidirectional range in
 	reverse, cycle creates a range that is an endless repetition of
 	the original range. ...

 	...

 Basically, you're writing an overview to the module, so highlight its
 main components, give some insight into why it's useful, etc., so that
 the user can make sense of the long list of declarations that follow.

 As it stands, std.range's page consists of a giant list of range-related
 declarations that gives no hint to the user as to how they all fit
 together. You basically have to wade through it until it somehow all
 "clicks" together. That is poor documentation. The overview should give
 some general categories of stuff that's found in the module (e.g. range
 tests, constructing new ranges, etc., as I've tried to do above in my
 one-shot attempt to improve std.range's docs). Include some examples of
 really clever stuff that you can do with the help of the module. Such
 examples are usually a very good way to get the user up-to-speed with
 what the module has to offer.

I strongly agree, particularly in the case of ranges which are not a familiar concept to many, but also with the general principle.
Mar 07 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Mar 06, 2012 at 07:25:23PM -0500, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 13:08:42 Brad Roberts wrote:

 I still believe pretty strongly that the logger must not affect
 application flow, ie, not throw or exit the app. From the feed back,
 I am not alone in thinking that. I don't believe that "well, don't
 use those log levels" is a workaround if for no other reason that
 there will be libraries that contain them and that becomes a "dont
 use those libraries either" response.

Agreed. The logging functions should _not_ throw.

+1. Logging functions are for ... logging? Not for managing errors. Leave it up to the user to define something like the following, if they're so inclined: void logAndAbort(T...)(string fmt, T args) { critical(fmt.format(args)); throw new CriticalError(...); } One shouldn't have to write a try/catch block just so one can log a critical message and continue doing whatever it is needs to be done. (For example, you might want to log a critical condition immediately to ensure the sysadmin sees the message, before proceeding to attempt self-recovery that *may* fail and crash the system, and thereby lose the ability to log a message.) Let the user decide whether or not to throw. T -- Why have vacation when you can work?? -- EC
Mar 06 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 16:59:09 Andrei Alexandrescu wrote:
 I don't see why the agitation around this particular matter. It's a
 matter of convenience, much like writeln (as opposed to just write).
 Let's admit that it often happens that you want to log some troublesome
 stuff just before throwing an exception with essentially the same
 message, so the thing is shown on the screen and also persisted in the
 log. Without a critical level, the pattern would be:
 
 string message = stuff() + ": " + moreStuff();
 log.error(message);
 throw new Exception(message);
 
 It's nice to encapsulate this frequent pattern, hence:
 
 log.critical(stuff() + ": " + moreStuff());
 
 If you want to log but not throw, use log.error. I don't think the
 response "dont use those libraries either" is meaningful.

I think that it would be far more meaningful to have a logging function which you pass the exception to throw. That way, you can throw whatever is appropriate for your program, not have std.log throw a logging exception of some kind. Such a function would be a convenience function where the programmer is explicitly saying that they want to log and then throw rather than having logging functions throw as a matter of course if the logging level is critical enough. What if you want to log such a message _without_ throwing? As it stands, std.log is conflating two separate concepts - logging and and error handling. Providing a convenience function to make that easier is fine, but making it so that the normal logging functions deal with error handling is not. - Jonathan M Davis
Mar 06 2012
prev sibling next sibling parent Geoffrey Biggs <geoffrey.biggs aist.go.jp> writes:
On 07/03/12 09:59, Andrei Alexandrescu wrote:
 I don't see why the agitation around this particular matter. It's a
 matter of convenience, much like writeln (as opposed to just write).
 Let's admit that it often happens that you want to log some troublesome
 stuff just before throwing an exception with essentially the same
 message, so the thing is shown on the screen and also persisted in the
 log. Without a critical level, the pattern would be:

 string message = stuff() + ": " + moreStuff();
 log.error(message);
 throw new Exception(message);

 It's nice to encapsulate this frequent pattern, hence:

 log.critical(stuff() + ": " + moreStuff());

 If you want to log but not throw, use log.error. I don't think the
 response "dont use those libraries either" is meaningful.

That approach means that if I actually do have a fatal error, I can't mark it as such. It gets conflated with the non-fatal errors, both in the source and in the logging output (which may, for example, be filtering for fatal errors to phone someone in the middle of the night while errors just send an email). Another point worth considering is that I cannot use the fatal level and be able to re-compile my software with logging disabled, because that will change the program flow. Forcing the two semantic concepts (logging and error handling) together needlessly restricts the ways the library can be used. It is nice to encapsulate frequent patterns, but providing a convenience function that throws an error, or a new level ("terminate" or something) is a better approach than forcing that pattern on everyone. Based on the name, it's a *logging* library, not an error handling library. Geoff
Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 6:05 PM, Geoffrey Biggs
<geoffrey.biggs aist.go.jp> wrote:
 On 07/03/12 09:59, Andrei Alexandrescu wrote:
 I don't see why the agitation around this particular matter. It's a
 matter of convenience, much like writeln (as opposed to just write).
 Let's admit that it often happens that you want to log some troublesome
 stuff just before throwing an exception with essentially the same
 message, so the thing is shown on the screen and also persisted in the
 log. Without a critical level, the pattern would be:

 string message = stuff() + ": " + moreStuff();
 log.error(message);
 throw new Exception(message);

 It's nice to encapsulate this frequent pattern, hence:

 log.critical(stuff() + ": " + moreStuff());

 If you want to log but not throw, use log.error. I don't think the
 response "dont use those libraries either" is meaningful.

That approach means that if I actually do have a fatal error, I can't mark it as such. It gets conflated with the non-fatal errors, both in the source and in the logging output (which may, for example, be filtering for fatal errors to phone someone in the middle of the night while errors just send an email). Another point worth considering is that I cannot use the fatal level and be able to re-compile my software with logging disabled, because that will change the program flow.

compile. In other words fatal log messages will always assert(true) and critical log messages will always throw.
 Forcing the two semantic concepts (logging and error handling) together
 needlessly restricts the ways the library can be used. It is nice to
 encapsulate frequent patterns, but providing a convenience function that
 throws an error, or a new level ("terminate" or something) is a better
 approach than forcing that pattern on everyone. Based on the name, it's a
 *logging* library, not an error handling library.

 Geoff

Mar 06 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, Mar 6, 2012 at 5:07 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Tuesday, March 06, 2012 16:59:09 Andrei Alexandrescu wrote:
 I don't see why the agitation around this particular matter. It's a
 matter of convenience, much like writeln (as opposed to just write).
 Let's admit that it often happens that you want to log some troublesome
 stuff just before throwing an exception with essentially the same
 message, so the thing is shown on the screen and also persisted in the
 log. Without a critical level, the pattern would be:

 string message = stuff() + ": " + moreStuff();
 log.error(message);
 throw new Exception(message);

 It's nice to encapsulate this frequent pattern, hence:

 log.critical(stuff() + ": " + moreStuff());

 If you want to log but not throw, use log.error. I don't think the
 response "dont use those libraries either" is meaningful.

I think that it would be far more meaningful to have a logging function which you pass the exception to throw.

API yet but the intent is that you can pass an exception to critical and the module will throw it for you. Very similar to how enforce works.
 That way, you can throw whatever is
 appropriate for your program, not have std.log throw a logging exception of
 some kind. Such a function would be a convenience function where the
 programmer is explicitly saying that they want to log and then throw rather
 than having logging functions throw as a matter of course if the logging level
 is critical enough. What if you want to log such a message _without_ throwing?

throw then use error.
 As it stands, std.log is conflating two separate concepts - logging and and
 error handling. Providing a convenience function to make that easier is fine,
 but making it so that the normal logging functions deal with error handling is
 not.

reiterate. fatal will always assert and critical will always throw. It is impossible for the user to disable these things. Thanks, -Jose
 - Jonathan M Davis

Mar 06 2012
prev sibling next sibling parent Geoffrey Biggs <geoffrey.biggs aist.go.jp> writes:
On 07/03/12 11:12, Jose Armando Garcia wrote:
 On Tue, Mar 6, 2012 at 6:05 PM, Geoffrey Biggs
 <geoffrey.biggs aist.go.jp>  wrote:
 That approach means that if I actually do have a fatal error, I can't mark
 it as such. It gets conflated with the non-fatal errors, both in the source
 and in the logging output (which may, for example, be filtering for fatal
 errors to phone someone in the middle of the night while errors just send an
 email). Another point worth considering is that I cannot use the fatal level
 and be able to re-compile my software with logging disabled, because that
 will change the program flow.

compile. In other words fatal log messages will always assert(true) and critical log messages will always throw.
 Forcing the two semantic concepts (logging and error handling) together
 needlessly restricts the ways the library can be used. It is nice to
 encapsulate frequent patterns, but providing a convenience function that
 throws an error, or a new level ("terminate" or something) is a better
 approach than forcing that pattern on everyone. Based on the name, it's a
 *logging* library, not an error handling library.


OK, I took another look at the docs. I see your point now. Sorry for making a fuss. However, I think that in this case, the log levels usable without killing the program are too coarse. This may be a matter of taste, though. Geoff
Mar 06 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 17:20:29 -0600, Jose Armando Garcia <jsancio gmail.com>
wrote:
 On Tue, Mar 6, 2012 at 2:03 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 13:41:32 -0600, Jose Armando Garcia <jsancio gmail.com>
 wrote:
 On Tue, Mar 6, 2012 at 10:11 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:44:13 -0600, Jose Armando Garcia
 <jsancio gmail.com>
 wrote:
 On Tue, Mar 6, 2012 at 9:32 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 11:01:19 -0600, Jose Armando Garcia
 <jsancio gmail.com>
 wrote:

 On Wed, Feb 29, 2012 at 4:13 PM, Richard van Scheijen
 <dlang mesadu.net>
 wrote:
 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.

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.

Interesting. If you find this useful, I think we can add this in a future release as it shouldn't break existing modules that maybe using the library.

This began as a discussion regarding Richard's organization of logging severity. That organization isn't something that can be trivially included at a later date.

Please be explicit in what you are requesting... If you have an API even better.

Richard proposed an organizational framework for logging severity, which many people including myself and yourself found valuable. In another thread I proposed a logical extension of this framework to make the logging call self documenting. You criticized both as having being overly complex with regard to setting the runtime severity level, to which I proposed a reasonable counter argument. Your response to the counter argument is to suggest making one aspect of it a possible future extension. ?? This seemed to ignore Richard's original suggestion and the extreme value of having a set of well-documented and standardized logging guidelines so that multiple code monkeys / projects 'play well' together. Better yet, by specifying those levels in terms of their conceptual components at the call site, code reviewers can instantly see the nature of what is being logged, without having to remember what each of those log levels mean. And not having to remember the classifications reduces the radius of comprehension needed to use / review the library (http://pragprog.com/magazines/2010-04/tangled-up-in-tools). P.S. You could also set config options using method chaining / fluent interfaces: config.logWarnings.logErrors.logCriticals.logSevers.logFatals;
Mar 06 2012
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 18:19:23 Jose Armando Garcia wrote:
 Fatal and Critical are exactly these continence functions... To
 reiterate. fatal will always assert and critical will always throw. It
 is impossible for the user to disable these things.

No, because they affect the log level. The concept of throwing and the log level should be _completely_ separate. std.log shouldn't be declaring _any_ exception types unless they're related to setting up the logging (_none_ which relate to functions which log). Adding an extra function which logs and then throws the exception that it's given is fine, but that should have _nothing_ to do with the log level. Asserting or throwing unconditionally like std.log does now is completely unacceptable IMHO. Logging should _not_ affect program flow. - Jonathan M Davis
Mar 06 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 7:04 PM, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 18:19:23 Jose Armando Garcia wrote:
 Fatal and Critical are exactly these continence functions... To
 reiterate. fatal will always assert and critical will always throw. It
 is impossible for the user to disable these things.

No, because they affect the log level. The concept of throwing and the log level should be _completely_ separate.

Why?
 std.log shouldn't be declaring _any_
 exception types unless they're related to setting up the logging (_none_ which
 relate to functions which log).

Why?
 Adding an extra function which logs and then throws the exception that it's
 given is fine, but that should have _nothing_ to do with the log level.

Why?
 Asserting or throwing unconditionally like std.log does now is completely
 unacceptable IMHO.

Why?
 Logging should _not_ affect program flow.

Why? Once again, the fallacy police finds you in violation of asserting the hypothesis as its own sustaining argument. Andrei
Mar 06 2012
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/6/12 7:43 PM, Jonathan M Davis wrote:
 Because the level that you log something at and what you want to do in terms
 of exceptions aren't necessarily related at all. It could easily be that you
 want to log something and then do some series of operations before throwing -
 even if the log level is the most severe level, and you intend to throw an
 Error to kill the program. And as others have pointed out, you might want to
 log a series of messages. Having std.log throw on the first one makes it so
 that you can't log any others.

Then I guess you'd be well advised to use the function that "logs to the error log", not the one that "logs to the error log and then throws". No? I mean you're explaining how a screwdriver is not appropriate for pounding nails.
 std.log shouldn't be declaring _any_
 exception types unless they're related to setting up the logging (_none_
 which relate to functions which log).

Why?

Because as others have asserted, logging should not affect program flow. It's printing out messages to a log, which doesn't necessarily have _anything_ to do with throwing exceptions.

It does, because, as I mentioned, frequently one is interested in logging erroneous events that are followed by a breakage of flow.
 It's merely for providing information about what
 the program is doing. If you have it throwing exceptions - _especially_
 exceptions which are specific to it - you're conflating two separate concepts:
 logging to a log file and having the program report errors. They _can_ be
 related, but they often aren't.

Well all I can say is they are in my experience. Some logging libraries have primitives that throw, some don't. I prefer a library that has the option in it because I use it all the time with glog.
 And when you _do_ throw an exception, why on earth would anyone want a
 LoggingException (or whatever std.log would call its exception type)? You want
 an exception which relates to what went wrong, not what threw it. The fact
 that you logged a message before throwing is incidental. Nothing that catches
 the exception is going to care.

That I do agree with. Andrei
Mar 06 2012
prev sibling parent reply Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 07.03.2012 7:54, James Miller wrote:
 On 7 March 2012 16:43, Jonathan M Davis<jmdavisProg gmx.com>  wrote:
 On Tuesday, March 06, 2012 19:27:35 Andrei Alexandrescu wrote:
 On 3/6/12 7:04 PM, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 18:19:23 Jose Armando Garcia wrote:
 Fatal and Critical are exactly these continence functions... To
 reiterate. fatal will always assert and critical will always throw. It
 is impossible for the user to disable these things.

No, because they affect the log level. The concept of throwing and the log level should be _completely_ separate.

Why?

Because the level that you log something at and what you want to do in terms of exceptions aren't necessarily related at all. It could easily be that you want to log something and then do some series of operations before throwing - even if the log level is the most severe level, and you intend to throw an Error to kill the program. And as others have pointed out, you might want to log a series of messages. Having std.log throw on the first one makes it so that you can't log any others.
 std.log shouldn't be declaring _any_
 exception types unless they're related to setting up the logging (_none_
 which relate to functions which log).

Why?

Because as others have asserted, logging should not affect program flow. It's printing out messages to a log, which doesn't necessarily have _anything_ to do with throwing exceptions. It's merely for providing information about what the program is doing. If you have it throwing exceptions - _especially_ exceptions which are specific to it - you're conflating two separate concepts: logging to a log file and having the program report errors. They _can_ be related, but they often aren't. And when you _do_ throw an exception, why on earth would anyone want a LoggingException (or whatever std.log would call its exception type)? You want an exception which relates to what went wrong, not what threw it. The fact that you logged a message before throwing is incidental. Nothing that catches the exception is going to care. - Jonathan M Davis

Surprisingly, I agree with the idea that fatal and critical shouldn't throw, or at least shouldn't throw by default, maybe a configuration option would allow for that functionality. Logging probably shouldn't affect program flow. Its possible that I may need to log a "critical" error, then do some graceful shutdown.

Exception is a graceful shutdown, as it calls destructors & finally blocks while unrolling the stack.
 In my opinion, critical and error should /not/ throw by default,
 however they should be able to get an optional Exception to throw, if
 that is appropriate behavior.

 --
 James Miller

-- Dmitry Olshansky
Mar 06 2012
parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 07.03.2012 16:34, Steven Schveighoffer wrote:
 On Wed, 07 Mar 2012 02:33:05 -0500, Dmitry Olshansky
 <dmitry.olsh gmail.com> wrote:

 Exception is a graceful shutdown, as it calls destructors & finally
 blocks while unrolling the stack.

You're assuming the program uses finally/scope exit blocks to do shutdown logic. This is not always the case. A library shouldn't force certain development styles.

I do and within the reason. Doing graceful shutdown logic in scope/finally/destructors or what the heck the top-most catch(Exception) is not just a good practice. Otherwise an unexpected exception on the way up leaves debris and destruction behind, and the whole point of graceful shutdown is lost. Yup, one can provide an alternative way of shutdown, yet one still has to think of unexpected exceptions. -- Dmitry Olshansky
Mar 07 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 19:10:14 Sean Kelly wrote:
 Sorry. For some reason I thought info was callable directly without the
 leading log portion.

It _is_ callable that way. Just look at the example at the top: http://jsancio.github.com/phobos/phobos/std_log.html - Jonathan M Davis
Mar 06 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 19:27:35 Andrei Alexandrescu wrote:
 On 3/6/12 7:04 PM, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 18:19:23 Jose Armando Garcia wrote:
 Fatal and Critical are exactly these continence functions... To
 reiterate. fatal will always assert and critical will always throw. It
 is impossible for the user to disable these things.

No, because they affect the log level. The concept of throwing and the log level should be _completely_ separate.

Why?

Because the level that you log something at and what you want to do in terms of exceptions aren't necessarily related at all. It could easily be that you want to log something and then do some series of operations before throwing - even if the log level is the most severe level, and you intend to throw an Error to kill the program. And as others have pointed out, you might want to log a series of messages. Having std.log throw on the first one makes it so that you can't log any others.
 std.log shouldn't be declaring _any_
 exception types unless they're related to setting up the logging (_none_
 which relate to functions which log).

Why?

Because as others have asserted, logging should not affect program flow. It's printing out messages to a log, which doesn't necessarily have _anything_ to do with throwing exceptions. It's merely for providing information about what the program is doing. If you have it throwing exceptions - _especially_ exceptions which are specific to it - you're conflating two separate concepts: logging to a log file and having the program report errors. They _can_ be related, but they often aren't. And when you _do_ throw an exception, why on earth would anyone want a LoggingException (or whatever std.log would call its exception type)? You want an exception which relates to what went wrong, not what threw it. The fact that you logged a message before throwing is incidental. Nothing that catches the exception is going to care. - Jonathan M Davis
Mar 06 2012
prev sibling next sibling parent James Miller <james aatch.net> writes:
On 7 March 2012 16:43, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Tuesday, March 06, 2012 19:27:35 Andrei Alexandrescu wrote:
 On 3/6/12 7:04 PM, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 18:19:23 Jose Armando Garcia wrote:
 Fatal and Critical are exactly these continence functions... To
 reiterate. fatal will always assert and critical will always throw. It
 is impossible for the user to disable these things.

No, because they affect the log level. The concept of throwing and the log level should be _completely_ separate.

Why?

Because the level that you log something at and what you want to do in terms of exceptions aren't necessarily related at all. It could easily be that you want to log something and then do some series of operations before throwing - even if the log level is the most severe level, and you intend to throw an Error to kill the program. And as others have pointed out, you might want to log a series of messages. Having std.log throw on the first one makes it so that you can't log any others.
 std.log shouldn't be declaring _any_
 exception types unless they're related to setting up the logging (_none_
 which relate to functions which log).

Why?

Because as others have asserted, logging should not affect program flow. It's printing out messages to a log, which doesn't necessarily have _anything_ to do with throwing exceptions. It's merely for providing information about what the program is doing. If you have it throwing exceptions - _especially_ exceptions which are specific to it - you're conflating two separate concepts: logging to a log file and having the program report errors. They _can_ be related, but they often aren't. And when you _do_ throw an exception, why on earth would anyone want a LoggingException (or whatever std.log would call its exception type)? You want an exception which relates to what went wrong, not what threw it. The fact that you logged a message before throwing is incidental. Nothing that catches the exception is going to care. - Jonathan M Davis

Surprisingly, I agree with the idea that fatal and critical shouldn't throw, or at least shouldn't throw by default, maybe a configuration option would allow for that functionality. Logging probably shouldn't affect program flow. Its possible that I may need to log a "critical" error, then do some graceful shutdown. In my opinion, critical and error should /not/ throw by default, however they should be able to get an optional Exception to throw, if that is appropriate behavior. -- James Miller
Mar 06 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, March 06, 2012 20:10:58 Andrei Alexandrescu wrote:
 On 3/6/12 7:43 PM, Jonathan M Davis wrote:
 Because the level that you log something at and what you want to do in
 terms of exceptions aren't necessarily related at all. It could easily be
 that you want to log something and then do some series of operations
 before throwing - even if the log level is the most severe level, and you
 intend to throw an Error to kill the program. And as others have pointed
 out, you might want to log a series of messages. Having std.log throw on
 the first one makes it so that you can't log any others.

Then I guess you'd be well advised to use the function that "logs to the error log", not the one that "logs to the error log and then throws". No? I mean you're explaining how a screwdriver is not appropriate for pounding nails.

Sure, but std.log appears to have built in whether an exception is thrown or not into the log level itself. The log level and whether an exception is thrown are not necessarily related. Having one log function which throws and another which doesn't is fine. It's the fact that this proposal ties the exceptions to the log levels which is the problem.
 std.log shouldn't be declaring _any_
 exception types unless they're related to setting up the logging (_none_
 which relate to functions which log).

Why?

Because as others have asserted, logging should not affect program flow. It's printing out messages to a log, which doesn't necessarily have _anything_ to do with throwing exceptions.

It does, because, as I mentioned, frequently one is interested in logging erroneous events that are followed by a breakage of flow.

Sure, you _may_ want to throw when you log, and having a way to do that in one command is fine. The problem is that you don't _always_ want to throw or not at a particular log level, and this std.log proposal ties to the two together.
 And when you _do_ throw an exception, why on earth would anyone want a
 LoggingException (or whatever std.log would call its exception type)? You
 want an exception which relates to what went wrong, not what threw it.
 The fact that you logged a message before throwing is incidental. Nothing
 that catches the exception is going to care.

That I do agree with.

And the current proposal declares a CriticalException type which is thrown when logging at the critical level. So, while we may agree on this, the current proposal does not. - Jonathan M Davis
Mar 06 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 14:32:37 -0500, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Mon, Mar 5, 2012 at 5:30 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 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.

name for a symbol in std.stdio. I suspect that the only reason that it is there is to keep C developer migrating to D happy. It should probably just be "out" like Java (System.out) and C# (Console.Out).

Like Robert says, cout is not in std.stdio. (maybe you were thinking of stdout?) And right in your counter-argument, you specify how Java and C# use namespaces to clarify common words (*System*.out and *Console*.Out). These only work because they must be identified by the fully qualified name. -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 19:59:09 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 4:31 PM, Geoffrey Biggs wrote:
 On 07/03/12 09:25, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 13:08:42 Brad Roberts wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:
 Fix now:

 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. From the feed back, I am not alone in thinking that. I don't believe that "well, don't use those log levels" is a workaround if for no other reason that there will be libraries that contain them and that becomes a "dont use those libraries either" response.

Agreed. The logging functions should _not_ throw.

+1. Is std.log a logging library or a complete error management library? If it's a logging library, the last thing it should be doing is affecting program flow. In the case of fatal, in particular, the program may need to do something else after logging the fatal error before terminating. You could argue that the program should do that before logging the fatal error, but I don't think that's nice semantics. On the other hand, if it's a complete error management library, it probably shouldn't be called std.log.

I don't see why the agitation around this particular matter. It's a matter of convenience, much like writeln (as opposed to just write). Let's admit that it often happens that you want to log some troublesome stuff just before throwing an exception with essentially the same message, so the thing is shown on the screen and also persisted in the log. Without a critical level, the pattern would be: string message = stuff() + ": " + moreStuff(); log.error(message); throw new Exception(message); It's nice to encapsulate this frequent pattern, hence: log.critical(stuff() + ": " + moreStuff()); If you want to log but not throw, use log.error. I don't think the response "dont use those libraries either" is meaningful.

I think access to the fatal/critical logging level should not be coupled with throwing exceptions. I have no problem with having critical or fatal convenience functions that throw and log, but it should not be a *requirement*, and it should not be the default. I'd combine these two levels into one (there is no semantic difference except one throws an exception and one throws an error), and if I got my way, log.critical(...) would log a message and logAndThrow!(E = Exception)(...) (name to be determined) would log a critical message and throw the given exception/error with the same message. -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 23:10:58 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 7:43 PM, Jonathan M Davis wrote:
 Because the level that you log something at and what you want to do in  
 terms
 of exceptions aren't necessarily related at all. It could easily be  
 that you
 want to log something and then do some series of operations before  
 throwing -
 even if the log level is the most severe level, and you intend to throw  
 an
 Error to kill the program. And as others have pointed out, you might  
 want to
 log a series of messages. Having std.log throw on the first one makes  
 it so
 that you can't log any others.

Then I guess you'd be well advised to use the function that "logs to the error log", not the one that "logs to the error log and then throws". No? I mean you're explaining how a screwdriver is not appropriate for pounding nails.

As has been repeatedly pointed out, the fatal and critical levels are different levels than the error level. Also, they cannot be turned off. Access to those levels should not be coupled with throwing an exception. Convenience functions to log at those levels and then throw an exception are perfectly acceptable. They just shouldn't be the only/default mechanism. A screwdriver is not appropriate for driving nails, but neither is an explosive-tipped hammer. -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 22:54:39 -0500, James Miller <james aatch.net> wrote:

 Surprisingly, I agree with the idea that fatal and critical shouldn't
 throw, or at least shouldn't throw by default, maybe a configuration
 option would allow for that functionality. Logging probably shouldn't
 affect program flow.

 Its possible that I may need to log a "critical" error, then do some
 graceful shutdown.

I see this pattern emerging: try { critical("Connection aborted!"); } catch(LoggingException e) { } // do graceful shutdown ... throw SomeError("Connection aborted!"); -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Wed, 07 Mar 2012 02:33:05 -0500, Dmitry Olshansky  
<dmitry.olsh gmail.com> wrote:

 Exception is a graceful shutdown, as it calls destructors & finally  
 blocks while unrolling the stack.

You're assuming the program uses finally/scope exit blocks to do shutdown logic. This is not always the case. A library shouldn't force certain development styles. -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 14:27:17 -0500, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Mon, Mar 5, 2012 at 5:32 PM, Jonathan M Davis <jmdavisProg gmx.com>  
 wrote:
 On Tuesday, March 06, 2012 02:22:05 so wrote:
 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.

using namesapce std; matrix vector = new Matrix(...) The variable vector conflicts with std::vector. Honestly, I can sit here and come up with 10s or 100s of example where you want to use a symbol that is expose by another module. You don't have to go far just look at druntime and phobos. This the exact reason why modules and namespace exist and one of the reason why people hate C's preprocessor macros. D solved this problem years ago.

The not so trivial and important difference is here: using namespace std; That is, the default is, vector is *NOT* imported into your namespace. For D modules, it is. -Steve
Mar 07 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 06 Mar 2012 14:19:27 -0500, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Mon, Mar 5, 2012 at 1:55 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Mon, 13 Feb 2012 10:50:04 -0500, David Nadlinger <see klickverbot.at>
 wrote:

 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.

You can implement the above by using std.log.error

Then I can't access the fatal level. When I used Log4Net to log application errors, I only logged fatal errors to the event log (using an event log backend). In fact, in that case, I was *catching* uncaught exceptions. There was no need to throw another exception at that point. My point is, whether to throw an exception or not should be up to the application, and having a fatal level can be utilized in other ways than "this is just like error but throws an exception". Again, the logging library should not be in the business of dictating application design. If fatal and critical logged an error at the "Error" logging level, and threw an appropriate exception, that would be a different story, because then it's just a convenience function. But you have made two levels of logging unavailable without throwing exceptions. As I brought up in another part of this thread, I envision the following pattern emerging: try { fatal("connection aborted!"); } catch(LoggingError) { } ... // graceful shutdown of rest of the application throw new LoggingError("connection aborted!");
 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.

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.

The problem is that by default D pulls in a module's symbols into the current scope. You have to go out of your way to *avoid* this. By default you should be able to just import std.log and not have your local symbols shadow std.log's. There are many solutions to this, as I have brought up elsewhere.
 import log = std.log;
 log.info("hello world");

I like this better: import std.log; // alias log.info info // if you desire log.info("hello world");
 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.

find it useful. If you are interested on a different explaination: http://google-glog.googlecode.com/svn/trunk/doc/glog.html

Someone else pointed that out. I think the documentation explanation there is much more complete than your version, and I think vlog is fine, it just needs a lot more documentation.
 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?

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.)

I wasn't speaking so much about filtering logging based on classes (and BTW, most logging libraries use hierarchical symbols to denote logging instances, they don't necessarily have to follow class names), but simply being able to have multiple log instances. That is, instead of having one global instance of log, what about multiple instances (I don't care if they are named or not). They don't have to be based on some sort of name, just another place you can configure independently of the rest of the application. For example, I may want a log instance in my library that logs to some library log file independent of the full application log. -Steve
Mar 07 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Tue, 06 Mar 2012 21:22:21 -0600, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 6:05 PM, Geoffrey Biggs wrote:
 That approach means that if I actually do have a fatal error, I can't
 mark it as such.

Use log.fatal for those. Andrei

But fatal "Logs a fatal severity message. Fatal log messages terminate the application after the message is persisted. Fatal log message cannot be disable at compile time or at run time." The point is that he want to log a fatal message and then terminate in a custom manner. I don't see a problem with convince functions that log and error and then throw, but not having the option to not throw is an unnecessary limitation.
Mar 07 2012
prev sibling next sibling parent reply "David Nadlinger" <see klickverbot.at> writes:
On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger 
wrote:
 Barring any objections, the review period starts now and ends 
 in three weeks, on March 6th, followed by a week of voting.

Okay, everyone, by the original schedule, the review period would have ended yesterday. However, I don't think it makes sense to start a vote right now, where several points are actively discussed. After discussing the situation with Jose, I think the best option is to extend the review period for another few days, until next Monday. Jose will try to answer any open comments so everybody can get a good idea of what the library does and what others expect it to do until the vote starts next week. Thanks for the comments and review so far, David
Mar 07 2012
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/11/12 4:49 PM, David Nadlinger wrote:
 Unfortunately, the discussion has ground to a halt again, so consider
 this a friendly reminder that there is still one day left until the end
 of the review period.

 David

I thought more about the point made about mixing throwing and logging levels. I agree that it's awkward to e.g. log to critical without throwing etc. I personally think in that case you really want the error log, but hey, point taken. Here's a suggestion: * Don't throw from the critical log and don't abort from the fatal log. * Define the logging functions such that logging an exception will log its toString() and then throw the exception. * Regarding static import log = std.log, I suggest we keep course. Works? Andrei
Mar 11 2012
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/12/12 5:35 PM, David Nadlinger wrote:
 On Monday, 12 March 2012 at 05:05:43 UTC, Jose Armando Garcia wrote:
 I think there is currently too much disagreement on std.log. I am
 honestly too busy juggling family, friends, school and work. I am
 currently leaning towards removing std.log from the review queue and
 spending some time ironing out the details pointed in this thread. I
 would like to experiment with some things before making any real
 suggestions but I would really like to have a logging library that I
 use throw/assert for me as it would simplify my code.

Okay, so let's remove std.log from the review queue without a vote for now. Be sure to let everybody know when you had a chance to work on it and you think it's time for resuming the review, even if this should already be next week; std.log will re-enter the queue then. Thanks to everyone, David

I think that's a wise decision, thanks Jose and David. One possibility is that Jose transfers the code to someone else who takes it through the review process and makes the appropriate amends. Jose would of course keep authoring credits, to which the new submitter would be added. Is anyone interested? Thanks, Andrei
Mar 12 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Mar 7, 2012 at 1:53 PM, David Nadlinger <see klickverbot.at> wrote:
 On Monday, 13 February 2012 at 15:50:05 UTC, David Nadlinger wrote:
 Barring any objections, the review period starts now and ends in three
 weeks, on March 6th, followed by a week of voting.

Okay, everyone, by the original schedule, the review period would have ended yesterday. However, I don't think it makes sense to start a vote right now, where several points are actively discussed. After discussing the situation with Jose, I think the best option is to extend the review period for another few days, until next Monday. Jose will try to answer any open comments so everybody can get a good idea of what the library does and what others expect it to do until the vote starts next week.

Thanks David! I will have to some time later today to answer some of the open questions.
 Thanks for the comments and review so far,
 David

Mar 07 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
Unfortunately, the discussion has ground to a halt again, so 
consider this a friendly reminder that there is still one day 
left until the end of the review period.

David
Mar 11 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Sun, 11 Mar 2012 16:49:24 -0500, David Nadlinger <see klickverbot.at> wrote:

 Unfortunately, the discussion has ground to a halt again, so
 consider this a friendly reminder that there is still one day
 left until the end of the review period.

 David

Has Jose updated anything?
Mar 11 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Sunday, 11 March 2012 at 22:09:54 UTC, Robert Jacques wrote:
 Has Jose updated anything?

Not sure what you mean – the latest state of the code is at https://github.com/D-Programming-Language/phobos/pull/432. I was more referring to the design-level discussions anyway, though. David
Mar 11 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Mar 11, 2012 at 05:28:44PM -0500, Andrei Alexandrescu wrote:
[...]
 I thought more about the point made about mixing throwing and logging
 levels. I agree that it's awkward to e.g. log to critical without
 throwing etc. I personally think in that case you really want the
 error log, but hey, point taken.
 
 Here's a suggestion:
 
 * Don't throw from the critical log and don't abort from the fatal
 log.
 
 * Define the logging functions such that logging an exception will log
 its toString() and then throw the exception.

+1. I feel much more comfortable with this design. T -- Tell me and I forget. Teach me and I remember. Involve me and I understand. -- Benjamin Franklin
Mar 11 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Sun, 11 Mar 2012 17:14:37 -0500, David Nadlinger <see klickverbot.at> wrote:

 On Sunday, 11 March 2012 at 22:09:54 UTC, Robert Jacques wrote:
 Has Jose updated anything?

Not sure what you mean – the latest state of the code is at https://github.com/D-Programming-Language/phobos/pull/432. I was more referring to the design-level discussions anyway, though. David

There was a bunch of discussions/suggestions and then silence from Jose. I assumed he was trying stuff out or thinking about it and would post an update to the newsgroup.
Mar 11 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Sun, Mar 11, 2012 at 3:28 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 3/11/12 4:49 PM, David Nadlinger wrote:
 Unfortunately, the discussion has ground to a halt again, so consider
 this a friendly reminder that there is still one day left until the end
 of the review period.

 David

I thought more about the point made about mixing throwing and logging levels. I agree that it's awkward to e.g. log to critical without throwin=

 etc. I personally think in that case you really want the error log, but h=

 point taken.

I thought about this a lot too and right now I think that if we want to remove asserting from fatal and remove throwing from critical then we should just remove those log levels completely. To me they don't add any additional value. The whole point of having them in the first place was because of their assert and throw semantic.
 Here's a suggestion:

 * Don't throw from the critical log and don't abort from the fatal log.

 * Define the logging functions such that logging an exception will log it=

 toString() and then throw the exception.

This would be great if it made everyone happy but I think it would also confuse developers coming from Java and C#. I think most developer coming from Java and probably C# are used to having: logger.info(e, "format message", ...); log the formatted message and the exception e. Ideally what I would like is= : enum Severity { fatal, error, warning, info }; // fatal cannot be disabled // none of the severity levels assert or throw and we have a template: logAndThrow!(FileNotFoundException, Severity.{fatal,error,warning,info})("formatted message", args...); logAndThrow logs the message, and throws a FileNotFoundException object with a message equal to the "formatted message". Unfortunately to implement this in a consistent way I would have to rethink the way the current "fa=E7ade" is designed/implemented.
 * Regarding static import log =3D std.log, I suggest we keep course.

 Works?

I think there is currently too much disagreement on std.log. I am honestly too busy juggling family, friends, school and work. I am currently leaning towards removing std.log from the review queue and spending some time ironing out the details pointed in this thread. I would like to experiment with some things before making any real suggestions but I would really like to have a logging library that I use throw/assert for me as it would simplify my code. I would like to thank everyone that commented on the design as it was really helpful for me to understand everyone's point of view and expectations. Thanks! Thoughts? -Jose
 Andrei

Mar 11 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Mar 7, 2012 at 7:16 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 21:22:21 -0600, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 6:05 PM, Geoffrey Biggs wrote:
 That approach means that if I actually do have a fatal error, I can't
 mark it as such.

Use log.fatal for those. Andrei

But fatal "Logs a fatal severity message. Fatal log messages terminate the application after the message is persisted. Fatal log message cannot be disable at compile time or at run time." The point is that he want to log a fatal message and then terminate in a custom manner. I don't see a problem with convince functions that log and error and then throw, but not having the option to not throw is an unnecessary limitation.

Okay. Let me say this one last time. If you don't want to assert or throw don't use fatal and critical. I think we are done beating a dead horse. Maybe it is not clear from the documentation but the only reason why fatal and critical exist is because of their assert and throw semantic. This is also the reason why you can't disable them. I understand that to a person that has not read the documentation is may not be clear to them that fatal("message") asserts and critical("message") throws. Knowing this observation maybe we can remove these severities and make the behavior more obvious by adding the tempalte logAndThrow. Thanks, -Jose
Mar 11 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Mar 7, 2012 at 4:21 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Tue, 06 Mar 2012 19:59:09 -0500, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 4:31 PM, Geoffrey Biggs wrote:
 On 07/03/12 09:25, Jonathan M Davis wrote:
 On Tuesday, March 06, 2012 13:08:42 Brad Roberts wrote:
 On Tue, 6 Mar 2012, Jose Armando Garcia wrote:
 Fix now:

 1. Add thread name attribute to the default logger
 2. Check that the example compile
 3. Come up with a better name for Rich and rich template
 4. Add  safe pure nothrow const to as many methods as possible
 5. Remove check when setting Configuration.logger

I still believe pretty strongly that the logger must not affect application flow, ie, not throw or exit the app. From the feed back, I am not alone in thinking that. I don't believe that "well, don't use tho=





 log levels" is a workaround if for no other reason that there will be
 libraries that contain them and that becomes a "dont use those
 libraries
 either" response.

Agreed. The logging functions should _not_ throw.

+1. Is std.log a logging library or a complete error management library? If it's a logging library, the last thing it should be doing is affecting program flow. In the case of fatal, in particular, the progra=



 may need to do something else after logging the fatal error before
 terminating. You could argue that the program should do that before
 logging the fatal error, but I don't think that's nice semantics.

 On the other hand, if it's a complete error management library, it
 probably shouldn't be called std.log.

I don't see why the agitation around this particular matter. It's a matt=


 of convenience, much like writeln (as opposed to just write). Let's admi=


 that it often happens that you want to log some troublesome stuff just
 before throwing an exception with essentially the same message, so the t=


 is shown on the screen and also persisted in the log. Without a critical
 level, the pattern would be:

 string message =3D stuff() + ": " + moreStuff();
 log.error(message);
 throw new Exception(message);

 It's nice to encapsulate this frequent pattern, hence:

 log.critical(stuff() + ": " + moreStuff());

 If you want to log but not throw, use log.error. I don't think the
 response "dont use those libraries either" is meaningful.

I think access to the fatal/critical logging level should not be coupled with throwing exceptions. =A0I have no problem with having critical or fa=

 convenience functions that throw and log, but it should not be a
 *requirement*, and it should not be the default.

 I'd combine these two levels into one (there is no semantic difference
 except one throws an exception and one throws an error), and if I got my
 way, log.critical(...) would log a message and logAndThrow!(E =3D
 Exception)(...) (name to be determined) would log a critical message and
 throw the given exception/error with the same message.

Yes, I am leaning toward this idea. Give me some time to come up with a better API that would make this logAndThrow template possible (we need to hint the Logger implementation that it needs to flush). Thanks, -Jose
 -Steve

Mar 11 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Mar 7, 2012 at 4:31 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Tue, 06 Mar 2012 22:54:39 -0500, James Miller <james aatch.net> wrote:

 Surprisingly, I agree with the idea that fatal and critical shouldn't
 throw, or at least shouldn't throw by default, maybe a configuration
 option would allow for that functionality. Logging probably shouldn't
 affect program flow.

 Its possible that I may need to log a "critical" error, then do some
 graceful shutdown.

I see this pattern emerging: try { =A0 critical("Connection aborted!"); } catch(LoggingException e) { } // do graceful shutdown ... throw SomeError("Connection aborted!");

Or you can just: scope(exit) // do graceful shutdown error("connection aborted"); throw SomeError("connection aborted"); Or better yet: scope(exit) // do graceful shutdown //... logAndThrow!(Exception, Severity.error)("connection aborted");
 -Steve

Mar 11 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Mon, 12 Mar 2012 01:05:33 -0400, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Sun, Mar 11, 2012 at 3:28 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 I thought more about the point made about mixing throwing and logging
 levels. I agree that it's awkward to e.g. log to critical without  
 throwing
 etc. I personally think in that case you really want the error log, but  
 hey,
 point taken.

I thought about this a lot too and right now I think that if we want to remove asserting from fatal and remove throwing from critical then we should just remove those log levels completely. To me they don't add any additional value. The whole point of having them in the first place was because of their assert and throw semantic.

This is fine, since we can always add more levels later if a need arises. -Steve
Mar 12 2012
prev sibling next sibling parent Geoffrey Biggs <geoffrey.biggs aist.go.jp> writes:
On Mar 12, 2012, at 7:28 AM, Andrei Alexandrescu wrote:

 On 3/11/12 4:49 PM, David Nadlinger wrote:
 Unfortunately, the discussion has ground to a halt again, so consider
 this a friendly reminder that there is still one day left until the =


 of the review period.
=20
 David

I thought more about the point made about mixing throwing and logging =

throwing etc. I personally think in that case you really want the error = log, but hey, point taken.
=20
 Here's a suggestion:
=20
 * Don't throw from the critical log and don't abort from the fatal =

=20
 * Define the logging functions such that logging an exception will log =

=20
 * Regarding static import log =3D std.log, I suggest we keep course.
=20
 Works?

+1 (I particularly like the idea of logging an exception rather than = logging a message and a separate exception to throw, which may contain a = different message.) Geoff=
Mar 12 2012
prev sibling next sibling parent "Robert Jacques" <sandford jhu.edu> writes:
On Mon, 12 Mar 2012 00:15:14 -0500, Jose Armando Garcia <jsancio gmail.com>
wrote:
 On Wed, Mar 7, 2012 at 7:16 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 21:22:21 -0600, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 6:05 PM, Geoffrey Biggs wrote:
 That approach means that if I actually do have a fatal error, I can't
 mark it as such.

Use log.fatal for those. Andrei

But fatal "Logs a fatal severity message. Fatal log messages terminate the application after the message is persisted. Fatal log message cannot be disable at compile time or at run time." The point is that he want to log a fatal message and then terminate in a custom manner. I don't see a problem with convince functions that log and error and then throw, but not having the option to not throw is an unnecessary limitation.

Okay. Let me say this one last time. If you don't want to assert or throw don't use fatal and critical. I think we are done beating a dead horse. Maybe it is not clear from the documentation but the only reason why fatal and critical exist is because of their assert and throw semantic. This is also the reason why you can't disable them. I understand that to a person that has not read the documentation is may not be clear to them that fatal("message") asserts and critical("message") throws. Knowing this observation maybe we can remove these severities and make the behavior more obvious by adding the tempalte logAndThrow. Thanks, -Jose

There is a strong impression that a 'fatal' error and an 'error' will appear differently in the log file. So long as fatal is anything more than log an error, flush and throw, there will be people wanting to separate the fatal log level from fatal log and throw command. I think the logAndThrow will clear up this confusion.
Mar 12 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 12, 2012 at 1:11 PM, Robert Jacques <sandford jhu.edu> wrote:
 On Mon, 12 Mar 2012 00:15:14 -0500, Jose Armando Garcia <jsancio gmail.com>
 wrote:
 On Wed, Mar 7, 2012 at 7:16 AM, Robert Jacques <sandford jhu.edu> wrote:
 On Tue, 06 Mar 2012 21:22:21 -0600, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:

 On 3/6/12 6:05 PM, Geoffrey Biggs wrote:
 That approach means that if I actually do have a fatal error, I can't
 mark it as such.

Use log.fatal for those. Andrei

But fatal "Logs a fatal severity message. Fatal log messages terminate the application after the message is persisted. Fatal log message cannot be disable at compile time or at run time." The point is that he want to log a fatal message and then terminate in a custom manner. I don't see a problem with convince functions that log and error and then throw, but not having the option to not throw is an unnecessary limitation.

Okay. Let me say this one last time. If you don't want to assert or throw don't use fatal and critical. I think we are done beating a dead horse. Maybe it is not clear from the documentation but the only reason why fatal and critical exist is because of their assert and throw semantic. This is also the reason why you can't disable them. I understand that to a person that has not read the documentation is may not be clear to them that fatal("message") asserts and critical("message") throws. Knowing this observation maybe we can remove these severities and make the behavior more obvious by adding the tempalte logAndThrow. Thanks, -Jose

There is a strong impression that a 'fatal' error and an 'error' will appear differently in the log file. So long as fatal is anything more than log an error, flush and throw, there will be people wanting to separate the fatal log level from fatal log and throw command. I think the logAndThrow will clear up this confusion.

Okay. Let me try to wipe something up soonish but it may take me some time given my current schedule.
Mar 12 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Monday, 12 March 2012 at 05:05:43 UTC, Jose Armando Garcia 
wrote:
 I think there is currently too much disagreement on std.log. I 
 am
 honestly too busy juggling family, friends, school and work. I 
 am
 currently leaning towards removing std.log from the review 
 queue and
 spending some time ironing out the details pointed in this 
 thread. I
 would like to experiment with some things before making any real
 suggestions but I would really like to have a logging library 
 that I
 use throw/assert for me as it would simplify my code.

Okay, so let's remove std.log from the review queue without a vote for now. Be sure to let everybody know when you had a chance to work on it and you think it's time for resuming the review, even if this should already be next week; std.log will re-enter the queue then. Thanks to everyone, David
Mar 12 2012
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 12, 2012 at 4:01 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 3/12/12 5:35 PM, David Nadlinger wrote:
 On Monday, 12 March 2012 at 05:05:43 UTC, Jose Armando Garcia wrote:
 I think there is currently too much disagreement on std.log. I am
 honestly too busy juggling family, friends, school and work. I am
 currently leaning towards removing std.log from the review queue and
 spending some time ironing out the details pointed in this thread. I
 would like to experiment with some things before making any real
 suggestions but I would really like to have a logging library that I
 use throw/assert for me as it would simplify my code.

Okay, so let's remove std.log from the review queue without a vote for now. Be sure to let everybody know when you had a chance to work on it and you think it's time for resuming the review, even if this should already be next week; std.log will re-enter the queue then. Thanks to everyone, David

I think that's a wise decision, thanks Jose and David. One possibility is that Jose transfers the code to someone else who takes it through the review process and makes the appropriate amends. Jose would of course keep authoring credits, to which the new submitter would be added. Is anyone interested?

I have tried to document every major modification that the community has requested in Trello. I'll continue to work on std.log but if anyone thinks they can complete this faster than me, please go ahead and take over. Just let know. Thanks David and everyone else for your commitment to the the review process. -Jose
 Thanks,

 Andrei

Mar 12 2012
prev sibling next sibling parent James Miller <james aatch.net> writes:
On 13 March 2012 12:34, Jose Armando Garcia <jsancio gmail.com> wrote:
 On Mon, Mar 12, 2012 at 4:01 PM, Andrei Alexandrescu
 I think that's a wise decision, thanks Jose and David.

 One possibility is that Jose transfers the code to someone else who takes it
 through the review process and makes the appropriate amends. Jose would of
 course keep authoring credits, to which the new submitter would be added. Is
 anyone interested?

I have tried to document every major modification that the community has requested in Trello. I'll continue to work on std.log but if anyone thinks they can complete this faster than me, please go ahead and take over. Just let know. Thanks David and everyone else for your commitment to the the review process. -Jose

Jose, I haven't used Trello, but is it possible to open up this board publicly so we anybody can look at it? It would probably help if people want to contribute. Otherwise, you could start adding issues to Github that people can look at. -- James Miller
Mar 12 2012
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Mon, Mar 12, 2012 at 4:44 PM, James Miller <james aatch.net> wrote:
 On 13 March 2012 12:34, Jose Armando Garcia <jsancio gmail.com> wrote:
 On Mon, Mar 12, 2012 at 4:01 PM, Andrei Alexandrescu
 I think that's a wise decision, thanks Jose and David.

 One possibility is that Jose transfers the code to someone else who takes it
 through the review process and makes the appropriate amends. Jose would of
 course keep authoring credits, to which the new submitter would be added. Is
 anyone interested?

I have tried to document every major modification that the community has requested in Trello. I'll continue to work on std.log but if anyone thinks they can complete this faster than me, please go ahead and take over. Just let know. Thanks David and everyone else for your commitment to the the review process. -Jose

Jose, I haven't used Trello, but is it possible to open up this board publicly so we anybody can look at it? It would probably help if people want to contribute. Otherwise, you could start adding issues to Github that people can look at.

I don't think I have access to do that in Trello. Anyone? Post you trello information here and maybe someone can give you access. Good idea. I'll move all the TODOs to GitHub's issues and let you know when it is there.
 --
 James Miller

Mar 12 2012