www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Implementing std.log

reply Robert Clipsham <robert octarineparrot.com> writes:
Hey folks,

I've just finished porting my web framework from D1/Tango to D2/Phobos, 
and in the transition lost logging functionality. As I'll be writing a 
logging library anyway, I wondered if there'd be interest in a std.log? 
If so, is there a current logging library we would like it to be based 
on, or should we design from scratch?

I know there has been discussion about Google's 
http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another 
candidate may be http://logging.apache.org/log4j/ . Do we want a 
comprehensive logging library, or just the basics? (Possibly with some 
method for extension if needed).

-- 
Robert
http://octarineparrot.com/
Apr 20 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/20/11 11:09 AM, Robert Clipsham wrote:
 Hey folks,

 I've just finished porting my web framework from D1/Tango to D2/Phobos,
 and in the transition lost logging functionality. As I'll be writing a
 logging library anyway, I wondered if there'd be interest in a std.log?
 If so, is there a current logging library we would like it to be based
 on, or should we design from scratch?

 I know there has been discussion about Google's
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another
 candidate may be http://logging.apache.org/log4j/ . Do we want a
 comprehensive logging library, or just the basics? (Possibly with some
 method for extension if needed).
Generally, I think a good logging library should: - be small and simple to use - allow defining arbitrary backends - allow switching backends dynamically - offer compile-time control, including zero overhead "all logging off" - offer run-time control I favor glog, which fulfills all of the above. Andrei
Apr 20 2011
parent reply Sean Kelly <sean invisibleduck.org> writes:
On Apr 20, 2011, at 9:23 AM, Andrei Alexandrescu wrote:
=20
 Generally, I think a good logging library should:
=20
 - be small and simple to use
=20
 - allow defining arbitrary backends
=20
 - allow switching backends dynamically
=20
 - offer compile-time control, including zero overhead "all logging =
off"
=20
 - offer run-time control
=20
 I favor glog, which fulfills all of the above.
It does so using macros and IOStreams though. Or is there a = printf-style interface I didn't see?=
Apr 20 2011
next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/20/11 11:35 AM, Sean Kelly wrote:
 On Apr 20, 2011, at 9:23 AM, Andrei Alexandrescu wrote:
 Generally, I think a good logging library should:

 - be small and simple to use

 - allow defining arbitrary backends

 - allow switching backends dynamically

 - offer compile-time control, including zero overhead "all logging off"

 - offer run-time control

 I favor glog, which fulfills all of the above.
It does so using macros and IOStreams though. Or is there a printf-style interface I didn't see?
The interface would of course be adapted to D. Andrei
Apr 20 2011
prev sibling parent so <so so.com> writes:
On Wed, 20 Apr 2011 19:35:33 +0300, Sean Kelly <sean invisibleduck.org>  
wrote:

 On Apr 20, 2011, at 9:23 AM, Andrei Alexandrescu wrote:
 Generally, I think a good logging library should:

 - be small and simple to use

 - allow defining arbitrary backends

 - allow switching backends dynamically

 - offer compile-time control, including zero overhead "all logging off"

 - offer run-time control

 I favor glog, which fulfills all of the above.
It does so using macros and IOStreams though. Or is there a printf-style interface I didn't see?
Probably the reason is that until now there wasn't a way to make printf typesafe in C++, no variadic templates. In D, i don't think iostream-like design has any merits.
Apr 20 2011
prev sibling next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 20 Apr 2011 20:09:30 +0400, Robert Clipsham  
<robert octarineparrot.com> wrote:

 Hey folks,

 I've just finished porting my web framework from D1/Tango to D2/Phobos,  
 and in the transition lost logging functionality. As I'll be writing a  
 logging library anyway, I wondered if there'd be interest in a std.log?  
 If so, is there a current logging library we would like it to be based  
 on, or should we design from scratch?

 I know there has been discussion about Google's  
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another  
 candidate may be http://logging.apache.org/log4j/ . Do we want a  
 comprehensive logging library, or just the basics? (Possibly with some  
 method for extension if needed).
For me, Logger needs to be simple but feature complete. Here is my ideal syntax: Logger log = new Logger(); log.warn("bewarned"); log.error("error code: %d", 42); log.fatal("Derp"); log.wtf("how is this even possible!?"); // What a Terrible Failure! // somewhat related: http://www.reddit.com/r/programming/comments/c6u6f/new_android_22_froyo_api_logwtf/ It would be great if you could configure log output with an external (xml?) file, e.g. formatting (show timestamps in a specified form, include thread id, call-stack etc for each error level), suppress (but still log) some of the error levels, being able to redirect log to file instead of console, etc. Ideally, it would monitor config changes and apply them on-fly, too. In addition, I believe Andrei wouldn't like to type more than 7 characters to add log entry, but I think we could negotiate :)
Apr 20 2011
parent reply so <so so.com> writes:
 For me, Logger needs to be simple but feature complete. Here is my ideal  
 syntax:

 Logger log = new Logger();
 log.warn("bewarned");
 log.error("error code: %d", 42);
 log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Apr 20 2011
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:

 For me, Logger needs to be simple but feature complete. Here is my  
 ideal syntax:

 Logger log = new Logger();
 log.warn("bewarned");
 log.error("error code: %d", 42);
 log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Having different loggers for different parts of programs (e.g. separate logger for my rendering, separate one for audio, separate for physics, and so on) is a must for me. Because when you debug your code by analyzing log output, you want to be able to filter out non-relevant stuff. If you only have ONE logger, you will start adding stupid prefixes like this: error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not valid"); instead of log.error("match data frame is not valid");
Apr 21 2011
next sibling parent reply Jens Mueller <jens.k.mueller gmx.de> writes:
Denis Koroskin wrote:
 On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:
 
For me, Logger needs to be simple but feature complete. Here is
my ideal syntax:

Logger log = new Logger();
log.warn("bewarned");
log.error("error code: %d", 42);
log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Having different loggers for different parts of programs (e.g. separate logger for my rendering, separate one for audio, separate for physics, and so on) is a must for me. Because when you debug your code by analyzing log output, you want to be able to filter out non-relevant stuff. If you only have ONE logger, you will start adding stupid prefixes like this: error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not valid"); instead of log.error("match data frame is not valid");
This can be solved by taking the compilation unit into account. I.e. each logging statement is associated with a file, namely the file it was used in, i.e. __FILE__. Then one only needs the ability to disable/enable logging per compilation unit. See e.g. glog's VLOG/--vmodule on http://google-glog.googlecode.com/svn/trunk/doc/glog.html Jens
Apr 21 2011
parent "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 21 Apr 2011 16:58:17 +0400, Jens Mueller <jens.k.mueller gmx.de>  
wrote:

 Denis Koroskin wrote:
 On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:

For me, Logger needs to be simple but feature complete. Here is
my ideal syntax:

Logger log = new Logger();
log.warn("bewarned");
log.error("error code: %d", 42);
log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Having different loggers for different parts of programs (e.g. separate logger for my rendering, separate one for audio, separate for physics, and so on) is a must for me. Because when you debug your code by analyzing log output, you want to be able to filter out non-relevant stuff. If you only have ONE logger, you will start adding stupid prefixes like this: error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not valid"); instead of log.error("match data frame is not valid");
This can be solved by taking the compilation unit into account. I.e. each logging statement is associated with a file, namely the file it was used in, i.e. __FILE__. Then one only needs the ability to disable/enable logging per compilation unit. See e.g. glog's VLOG/--vmodule on http://google-glog.googlecode.com/svn/trunk/doc/glog.html Jens
That could work, I guess. Either way, one line of code is that much of a difference, I believe.
Apr 21 2011
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-04-21 14:37, Denis Koroskin wrote:
 On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:

 For me, Logger needs to be simple but feature complete. Here is my
 ideal syntax:

 Logger log = new Logger();
 log.warn("bewarned");
 log.error("error code: %d", 42);
 log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Having different loggers for different parts of programs (e.g. separate logger for my rendering, separate one for audio, separate for physics, and so on) is a must for me. Because when you debug your code by analyzing log output, you want to be able to filter out non-relevant stuff. If you only have ONE logger, you will start adding stupid prefixes like this: error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not valid"); instead of log.error("match data frame is not valid");
"log" could be a default instance of a class or struct (Logger for example), instead of a function, implementing opCall. Then you could use it like this: log("info message or whatever is the default"); log.error("error message"); // and so on auto gameLog = new Logger; // set custom settings for the game logging gameLog("info message"); -- /Jacob Carlborg
Apr 21 2011
prev sibling next sibling parent reply so <so so.com> writes:
On Thu, 21 Apr 2011 15:37:42 +0300, Denis Koroskin <2korden gmail.com>  
wrote:

 On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:

 For me, Logger needs to be simple but feature complete. Here is my  
 ideal syntax:

 Logger log = new Logger();
 log.warn("bewarned");
 log.error("error code: %d", 42);
 log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Having different loggers for different parts of programs (e.g. separate logger for my rendering, separate one for audio, separate for physics, and so on) is a must for me. Because when you debug your code by analyzing log output, you want to be able to filter out non-relevant stuff. If you only have ONE logger, you will start adding stupid prefixes like this: error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not valid"); instead of log.error("match data frame is not valid");
So you want the iostream way, global logger objects, otherwise i don't see how this solves the problem you are suggesting.
Apr 21 2011
parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Thu, 21 Apr 2011 19:08:38 +0400, so <so so.com> wrote:

 On Thu, 21 Apr 2011 15:37:42 +0300, Denis Koroskin <2korden gmail.com>  
 wrote:

 On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:

 For me, Logger needs to be simple but feature complete. Here is my  
 ideal syntax:

 Logger log = new Logger();
 log.warn("bewarned");
 log.error("error code: %d", 42);
 log.fatal("Derp");
Fine if you remove the first line, switching the output is something we rarely do, so we shouldn't mandate this for each use. note("just a note :", 5); note!warn("bewarned"); note!error(c, ", ", d);
Having different loggers for different parts of programs (e.g. separate logger for my rendering, separate one for audio, separate for physics, and so on) is a must for me. Because when you debug your code by analyzing log output, you want to be able to filter out non-relevant stuff. If you only have ONE logger, you will start adding stupid prefixes like this: error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not valid"); instead of log.error("match data frame is not valid");
So you want the iostream way, global logger objects, otherwise i don't see how this solves the problem you are suggesting.
No globals, of course, loggers are part of objects. In most cases, everyone who adds log entry creates its own logger and add it into a hierarchy.
Apr 21 2011
parent reply so <so so.com> writes:
 So you want the iostream way, global logger objects, otherwise i don't  
 see how this solves the problem you are suggesting.
No globals, of course, loggers are part of objects. In most cases, everyone who adds log entry creates its own logger and add it into a hierarchy.
class A { logger log; } class B { A a; logger log; } void some_function() { auto log = new logger("where to? why would i care who call this? why do i need this line anyways? :)") log.error(...); } --- I think we are looking this from fairly different angles. Most of the times all i want to do just : module logger; void note(uint level, A...)(A a); void note_redirect(uint level, string); void note_enable(uint level, bool on); uint note_new(string); // default levels enum { warning = 0, error, fatal, } import logger; void some_function() { ... note(...); ... note!error(...); ... note!fatal(...); ... note!my_level(...); }
Apr 21 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/21/11 11:53 AM, so wrote:
 So you want the iostream way, global logger objects, otherwise i
 don't see how this solves the problem you are suggesting.
No globals, of course, loggers are part of objects. In most cases, everyone who adds log entry creates its own logger and add it into a hierarchy.
class A { logger log; } class B { A a; logger log; }
[snip] Again, I'd _much_ rather prefer if someone just implemented this: http://google-glog.googlecode.com/svn/trunk/doc/glog.html It's simple, to the point, and brings the bacon home. In fact I'm putting dibs on this. I'll implement the thing and make a proposal. Andrei
Apr 21 2011
prev sibling parent Kagamin <spam here.lot> writes:
Denis Koroskin Wrote:

 Having different loggers for different parts of programs (e.g. separate  
 logger for my rendering, separate one for audio, separate for physics, and  
 so on) is a must for me.
 Because when you debug your code by analyzing log output, you want to be  
 able to filter out non-relevant stuff. If you only have ONE logger, you  
 will start adding stupid prefixes like this:
 
 error("GAME/GAMEMODE_CHALLENGE/OBJECTIVE_CHECKER: match data frame is not  
 valid");
 
 instead of
 
 log.error("match data frame is not valid");
If you parameterize logger with just a class name, that's not enough. log4net uses similar approach, and I constantly need to prefix log messages with method name, its signature and sometimes even line number to know, where the logging took place. If I don't do this, it's difficult to determine where it blew up just by the class name because there're many identical log calls throughout a class.
Apr 21 2011
prev sibling next sibling parent David Nadlinger <see klickverbot.at> writes:
On 4/20/11 6:09 PM, Robert Clipsham wrote:
 […] and another candidate may be http://logging.apache.org/log4j/.
You might want to have a look at SLF4J and Logback, which were written by the author of log4j as a successor to it. David
Apr 20 2011
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 20.04.2011 20:09, Robert Clipsham wrote:
 Hey folks,

 I've just finished porting my web framework from D1/Tango to 
 D2/Phobos, and in the transition lost logging functionality. As I'll 
 be writing a logging library anyway, I wondered if there'd be interest 
 in a std.log? If so, is there a current logging library we would like 
 it to be based on, or should we design from scratch?

 I know there has been discussion about Google's 
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another 
 candidate may be http://logging.apache.org/log4j/ . Do we want a 
 comprehensive logging library, or just the basics? (Possibly with some 
 method for extension if needed).
Actually we have a lurking proposal (with implementation, though I haven't check it): http://d.puremagic.com/issues/show_bug.cgi?id=5329 -- Dmitry Olshansky
Apr 20 2011
prev sibling next sibling parent Zz <nospam nospam.com> writes:
I currently use the logger written by Masahiro Nakagawa and it has handled what
I need.

You can get it from:
http://www.bitbucket.org/repeatedly/scrap/src/tip/logger.d

Zz

Robert Clipsham Wrote:

 Hey folks,
 
 I've just finished porting my web framework from D1/Tango to D2/Phobos, 
 and in the transition lost logging functionality. As I'll be writing a 
 logging library anyway, I wondered if there'd be interest in a std.log? 
 If so, is there a current logging library we would like it to be based 
 on, or should we design from scratch?
 
 I know there has been discussion about Google's 
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another 
 candidate may be http://logging.apache.org/log4j/ . Do we want a 
 comprehensive logging library, or just the basics? (Possibly with some 
 method for extension if needed).
 
 -- 
 Robert
 http://octarineparrot.com/
Apr 22 2011
prev sibling parent reply Sean Cavanaugh <WorksOnMyMachine gmail.com> writes:
On 4/20/2011 11:09 AM, Robert Clipsham wrote:
 Hey folks,

 I've just finished porting my web framework from D1/Tango to D2/Phobos,
 and in the transition lost logging functionality. As I'll be writing a
 logging library anyway, I wondered if there'd be interest in a std.log?
 If so, is there a current logging library we would like it to be based
 on, or should we design from scratch?

 I know there has been discussion about Google's
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another
 candidate may be http://logging.apache.org/log4j/ . Do we want a
 comprehensive logging library, or just the basics? (Possibly with some
 method for extension if needed).
I just wanted to mention Pantheios as a C++ logging system to take look at as well, I didn't see it mentioned in this thread and it seems to have all the major requirements for frontend/backend chaining and whatnot that people have brought up. The code is on sourceforge to boot.
Apr 24 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 04/24/2011 02:23 PM, Sean Cavanaugh wrote:
 On 4/20/2011 11:09 AM, Robert Clipsham wrote:
 Hey folks,

 I've just finished porting my web framework from D1/Tango to D2/Phobos,
 and in the transition lost logging functionality. As I'll be writing a
 logging library anyway, I wondered if there'd be interest in a std.log?
 If so, is there a current logging library we would like it to be based
 on, or should we design from scratch?

 I know there has been discussion about Google's
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another
 candidate may be http://logging.apache.org/log4j/ . Do we want a
 comprehensive logging library, or just the basics? (Possibly with some
 method for extension if needed).
I just wanted to mention Pantheios as a C++ logging system to take look at as well, I didn't see it mentioned in this thread and it seems to have all the major requirements for frontend/backend chaining and whatnot that people have brought up. The code is on sourceforge to boot.
I think Pantheios is an example of library design gone bad. It is fascinatingly overengineered. Andrei
Apr 24 2011
next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
Hey folks,

For the past couple of days I took the liberty of partially
implementing a logging module for D. I say partially because all the
features that I want to implement are not currently implement. You
should really look at the implementation more as a proof of concept
even thought most of the code will be used in the final
implementation.

That been said I am really interested in getting some feedback on the
API. That includes high-level design (e.g. using a thread to perform
logging. On that note I am planning to also have a shared memory
implementation), interfaces and the documentation.

When making comment be aware that the design goals of the module are:
1) Provide a logging mechanism that is easy to use in the common case.
2) The module should allow for as much configuration as possible at
compile time and execution time without breaking design goal 1.
3) It should be possible to extend or replace the backend without
breaking the semantic exposed by the API.

I am fairly new to the D language so any comment on how I can take
advantage of D idiom or D features in the API or implementation would
be greatly appreciated.

My intent, and hopefully we will get there with your help, is to
include this in Phobos for D2.

Thanks,
-Jose

On Mon, Apr 25, 2011 at 12:03 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 04/24/2011 02:23 PM, Sean Cavanaugh wrote:
 On 4/20/2011 11:09 AM, Robert Clipsham wrote:
 Hey folks,

 I've just finished porting my web framework from D1/Tango to D2/Phobos,
 and in the transition lost logging functionality. As I'll be writing a
 logging library anyway, I wondered if there'd be interest in a std.log?
 If so, is there a current logging library we would like it to be based
 on, or should we design from scratch?

 I know there has been discussion about Google's
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another
 candidate may be http://logging.apache.org/log4j/ . Do we want a
 comprehensive logging library, or just the basics? (Possibly with some
 method for extension if needed).
I just wanted to mention Pantheios as a C++ logging system to take look at as well, I didn't see it mentioned in this thread and it seems to have all the major requirements for frontend/backend chaining and whatnot that people have brought up. The code is on sourceforge to boot.
I think Pantheios is an example of library design gone bad. It is fascinatingly overengineered. Andrei
May 07 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/7/11 3:43 PM, Jose Armando Garcia wrote:
 Hey folks,

 For the past couple of days I took the liberty of partially
 implementing a logging module for D.
[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
May 08 2011
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-09 08:52, Andrei Alexandrescu wrote:
 On 5/7/11 3:43 PM, Jose Armando Garcia wrote:
 Hey folks,

 For the past couple of days I took the liberty of partially
 implementing a logging module for D.
[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
Isn't the name of the log file a little too verbose? Don't know if I'm missing something but this doesn't seem so useful for long running application that use logging. As far as I know you usually have one log file per application and outputs the message along with the level and date and time. -- /Jacob Carlborg
May 09 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 10:37 AM, Jacob Carlborg wrote:
 Isn't the name of the log file a little too verbose? Don't know if I'm
 missing something but this doesn't seem so useful for long running
 application that use logging. As far as I know you usually have one log
 file per application and outputs the message along with the level and
 date and time.
I did what glog does. Going forward, there is a private static string for formatting file names using positional parameters. In the future I'm considering providing an API for changing that format string, which means the log file format will be user-definable. (Same about the format of individual messages - see the string constants fileNameFormat and format toward the top of log.d.) Positional parameters look a bit odd but they are quite flexible. Andrei
May 09 2011
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-09 17:49, Andrei Alexandrescu wrote:
 On 5/9/11 10:37 AM, Jacob Carlborg wrote:
 Isn't the name of the log file a little too verbose? Don't know if I'm
 missing something but this doesn't seem so useful for long running
 application that use logging. As far as I know you usually have one log
 file per application and outputs the message along with the level and
 date and time.
I did what glog does. Going forward, there is a private static string for formatting file names using positional parameters. In the future I'm considering providing an API for changing that format string, which means the log file format will be user-definable. (Same about the format of individual messages - see the string constants fileNameFormat and format toward the top of log.d.) Positional parameters look a bit odd but they are quite flexible. Andrei
Excuse me for asking again but to me it seems that the log functions will output a new file for every log event (since the time is included in the filename). Is that the case? -- /Jacob Carlborg
May 09 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 12:10 PM, Jacob Carlborg wrote:
 On 2011-05-09 17:49, Andrei Alexandrescu wrote:
 On 5/9/11 10:37 AM, Jacob Carlborg wrote:
 Isn't the name of the log file a little too verbose? Don't know if I'm
 missing something but this doesn't seem so useful for long running
 application that use logging. As far as I know you usually have one log
 file per application and outputs the message along with the level and
 date and time.
I did what glog does. Going forward, there is a private static string for formatting file names using positional parameters. In the future I'm considering providing an API for changing that format string, which means the log file format will be user-definable. (Same about the format of individual messages - see the string constants fileNameFormat and format toward the top of log.d.) Positional parameters look a bit odd but they are quite flexible. Andrei
Excuse me for asking again but to me it seems that the log functions will output a new file for every log event (since the time is included in the filename). Is that the case?
No, log files are created and opened only once, and the time in the filename reflects the creation time. Logging messages also contain the time (with added precision) and go to the respective files. A maximum of five files are created. (No support for rotating logs for the time being.) There's one difference from glog by the way - glog defines four levels and consequently four files: info, warning, error, and fatal. I defined critical in between error and fatal. Logging to the critical log throws an exception right after logging. I think this is very useful for figuring out what happens in exceptional code. Andrei
May 09 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-09 17:49, Andrei Alexandrescu wrote:
 On 5/9/11 10:37 AM, Jacob Carlborg wrote:
 Isn't the name of the log file a little too verbose? Don't know if I'm
 missing something but this doesn't seem so useful for long running
 application that use logging. As far as I know you usually have one log
 file per application and outputs the message along with the level and
 date and time.
I did what glog does. Going forward, there is a private static string for formatting file names using positional parameters. In the future I'm considering providing an API for changing that format string, which means the log file format will be user-definable. (Same about the format of individual messages - see the string constants fileNameFormat and format toward the top of log.d.) Positional parameters look a bit odd but they are quite flexible. Andrei
very usable. Although the syntax you've chosen looks a little odd to me. Wouldn't it make more sense to have the $ in front of the number instead of behind, since the % is in front. -- /Jacob Carlborg
May 09 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 12:14 PM, Jacob Carlborg wrote:
 On 2011-05-09 17:49, Andrei Alexandrescu wrote:
 On 5/9/11 10:37 AM, Jacob Carlborg wrote:
 Isn't the name of the log file a little too verbose? Don't know if I'm
 missing something but this doesn't seem so useful for long running
 application that use logging. As far as I know you usually have one log
 file per application and outputs the message along with the level and
 date and time.
I did what glog does. Going forward, there is a private static string for formatting file names using positional parameters. In the future I'm considering providing an API for changing that format string, which means the log file format will be user-definable. (Same about the format of individual messages - see the string constants fileNameFormat and format toward the top of log.d.) Positional parameters look a bit odd but they are quite flexible. Andrei
very usable. Although the syntax you've chosen looks a little odd to me. Wouldn't it make more sense to have the $ in front of the number instead of behind, since the % is in front.
I used the Posix positional format syntax, see http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html. Andrei
May 09 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I'm not a big fan of that format syntax. It's just hard to look at and
figure out what went wrong when things do go wrong.

I'd prefer something like:
https://gist.github.com/963027

But someone would have to implement it, of course. I have my own
little echo() function which takes simple "{}" positional syntax, it
doesn't have any other formatting options though. But I only ever need
formatting for simple cases like the above. It seems some people need
a whole word processor macro language embedded in a format string..
May 09 2011
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 09/05/2011 19:18, Andrej Mitrovic wrote:
 I'm not a big fan of that format syntax. It's just hard to look at and
 figure out what went wrong when things do go wrong.

 I'd prefer something like:
 https://gist.github.com/963027

 But someone would have to implement it, of course. I have my own
 little echo() function which takes simple "{}" positional syntax, it
 doesn't have any other formatting options though. But I only ever need
 formatting for simple cases like the above. It seems some people need
 a whole word processor macro language embedded in a format string..
That is A LOT nicer to look at. Please can we have this? :< -- Robert http://octarineparrot.com/
May 09 2011
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-09 20:34, Robert Clipsham wrote:
 On 09/05/2011 19:18, Andrej Mitrovic wrote:
 I'm not a big fan of that format syntax. It's just hard to look at and
 figure out what went wrong when things do go wrong.

 I'd prefer something like:
 https://gist.github.com/963027

 But someone would have to implement it, of course. I have my own
 little echo() function which takes simple "{}" positional syntax, it
 doesn't have any other formatting options though. But I only ever need
 formatting for simple cases like the above. It seems some people need
 a whole word processor macro language embedded in a format string..
That is A LOT nicer to look at. Please can we have this? :<
-- /Jacob Carlborg
May 09 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 1:34 PM, Robert Clipsham wrote:
 On 09/05/2011 19:18, Andrej Mitrovic wrote:
 I'm not a big fan of that format syntax. It's just hard to look at and
 figure out what went wrong when things do go wrong.

 I'd prefer something like:
 https://gist.github.com/963027

 But someone would have to implement it, of course. I have my own
 little echo() function which takes simple "{}" positional syntax, it
 doesn't have any other formatting options though. But I only ever need
 formatting for simple cases like the above. It seems some people need
 a whole word processor macro language embedded in a format string..
That is A LOT nicer to look at. Please can we have this? :<
I, too, prefer it a great deal to the prinf/scanf format, and it wouldn't be difficult to implement, but at this point we need to worry about compatibility issues and such (TDPL already uses the % syntax as does existing D code). I don't see a simple migration path. format strings into % format strings, e.g. nice2ugly!"{1}:{2}" yields the string constant "%1$s:%2$s". By and large this doesn't seem to be a very worrisome issue as formatting strings are a minority in most applications and are seldom maintained. You pay attention, get them right, and then just use them. Andrei
May 09 2011
next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 09/05/2011 20:47, Andrei Alexandrescu wrote:
 On 5/9/11 1:34 PM, Robert Clipsham wrote:
 That is A LOT nicer to look at. Please can we have this? :<
I, too, prefer it a great deal to the prinf/scanf format, and it wouldn't be difficult to implement, but at this point we need to worry about compatibility issues and such (TDPL already uses the % syntax as does existing D code). I don't see a simple migration path. format strings into % format strings, e.g. nice2ugly!"{1}:{2}" yields the string constant "%1$s:%2$s". By and large this doesn't seem to be a very worrisome issue as formatting strings are a minority in most applications and are seldom maintained. You pay attention, get them right, and then just use them. Andrei
Compilation switch maybe? Support both by default, compile with -version=DisableUglyFormatStrings to remove the overhead. Document it as deprecated, tweak the first revision of TDPL to use the new format strings, give it <X> amount of time, make it deprecated etc. Having nice2ugly!"" all over my codebase is not a solution. -- Robert http://octarineparrot.com/
May 09 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/9/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:

 format strings into % format strings, e.g. nice2ugly!"{1}:{2}" yields
 the string constant "%1$s:%2$s".
That is exactly what my echo function does. It replaces {} syntax with %$s syntax behind the scenes, and then forwards that to writef.
May 09 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-09 19:34, Andrei Alexandrescu wrote:
 On 5/9/11 12:14 PM, Jacob Carlborg wrote:
 On 2011-05-09 17:49, Andrei Alexandrescu wrote:
 On 5/9/11 10:37 AM, Jacob Carlborg wrote:
 Isn't the name of the log file a little too verbose? Don't know if I'm
 missing something but this doesn't seem so useful for long running
 application that use logging. As far as I know you usually have one log
 file per application and outputs the message along with the level and
 date and time.
I did what glog does. Going forward, there is a private static string for formatting file names using positional parameters. In the future I'm considering providing an API for changing that format string, which means the log file format will be user-definable. (Same about the format of individual messages - see the string constants fileNameFormat and format toward the top of log.d.) Positional parameters look a bit odd but they are quite flexible. Andrei
very usable. Although the syntax you've chosen looks a little odd to me. Wouldn't it make more sense to have the $ in front of the number instead of behind, since the % is in front.
I used the Posix positional format syntax, see http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html. Andrei
Ok, I see. -- /Jacob Carlborg
May 09 2011
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-09 08:52, Andrei Alexandrescu wrote:
 On 5/7/11 3:43 PM, Jose Armando Garcia wrote:
 Hey folks,

 For the past couple of days I took the liberty of partially
 implementing a logging module for D.
[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
I assume the "initLogging" function needs the application command line because you want to have the name of the application? If that's the case, I don't like that is handled via the application command line. I have a function that gets the path of the current process: http://dsource.org/projects/tango/attachment/ticket/1536/process.d This links to a file attached to a Tango ticket but don't worry, I've written the whole file myself and I intend to change the license to the Boost License. It's written with D1 (obviously) but it's very easy to port to D2, the only dependencies are C functions. Feel free to port it to D2 and use it in you're logging library if you want to. -- /Jacob Carlborg
May 09 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I assume the "initLogging" function needs the application command line
 because you want to have the name of the application? If that's the
 case, I don't like that is handled via the application command line. I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
Thanks! In fact, the command-line arguments are needed for considerably more than just the application name. std.log is configurable via application's command line (e.g. --logtostderr --log_dir=/tmp/ etc., see documentation) and extracts these flags using getopt. The rest of the flags are left alone for the application to process. In case the application would want to change a flag's name, e.g. use "--log_to_stderr" instead of "--logtostderr", it's easy to define an API that does that; currently all parameter names are hoisted in private strings in std.log. Andrei
May 09 2011
next sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 9, 2011, at 10:45 AM, Andrei Alexandrescu wrote:

 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I assume the "initLogging" function needs the application command =
line
 because you want to have the name of the application? If that's the
 case, I don't like that is handled via the application command line. =
I
 have a function that gets the path of the current process:
=20
 http://dsource.org/projects/tango/attachment/ticket/1536/process.d
=20
 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to =
the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.
=20
 Feel free to port it to D2 and use it in you're logging library if =
you
 want to.
=20 Thanks! In fact, the command-line arguments are needed for =
considerably more than just the application name. std.log is = configurable via application's command line (e.g. --logtostderr = --log_dir=3D/tmp/ etc., see documentation) and extracts these flags = using getopt. The rest of the flags are left alone for the application = to process. For what it's worth, the command-line args are available via = core.runtime as well.=
May 09 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-05-09 20:03, Sean Kelly wrote:
 On May 9, 2011, at 10:45 AM, Andrei Alexandrescu wrote:

 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I assume the "initLogging" function needs the application command line
 because you want to have the name of the application? If that's the
 case, I don't like that is handled via the application command line. I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
Thanks! In fact, the command-line arguments are needed for considerably more than just the application name. std.log is configurable via application's command line (e.g. --logtostderr --log_dir=/tmp/ etc., see documentation) and extracts these flags using getopt. The rest of the flags are left alone for the application to process.
For what it's worth, the command-line args are available via core.runtime as well.
Ah, you're right. -- /Jacob Carlborg
May 09 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-09 19:45, Andrei Alexandrescu wrote:
 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I assume the "initLogging" function needs the application command line
 because you want to have the name of the application? If that's the
 case, I don't like that is handled via the application command line. I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
Thanks! In fact, the command-line arguments are needed for considerably more than just the application name. std.log is configurable via application's command line (e.g. --logtostderr --log_dir=/tmp/ etc., see documentation) and extracts these flags using getopt. The rest of the flags are left alone for the application to process.
Yes, but since it requires you to pass an array I assumed the application name was the minimum requirement.
 In case the application would want to change a flag's name, e.g. use
 "--log_to_stderr" instead of "--logtostderr", it's easy to define an API
 that does that; currently all parameter names are hoisted in private
 strings in std.log.


 Andrei
-- /Jacob Carlborg
May 09 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
I looked over the code, it's quite nice and clean. If you or anyone else would want to create a github pull request, the function would be a valuable addition to std.process. Thanks Jacob for offering the code to Phobos! What I think should change: * Provide two overloads, one that attempts to reuse a buffer and one that always returns a new string: char[] getProcessPath(char[] buf) { ... } static if (is(typeof(getProcessPath(null)) == char[])) { string getProcessPath() { return assumeUnique(getProcessPath(null)); } } * hoist version(OS) up to the function definition, e.g. version (darwin) char[] getProcessPath (char[] buf) { ... } version (freebsd) char[] getProcessPath (char[] buf) { ... } ... Unsupported OSs will simply not define the function (as opposed to asserting at run time). * Use size_t instead of uint throughout for 64-bit compatibility. * Don't do this: if (size > buf.length) buf ~= new char[size - buf.length]; because it allocates memory twice. Instead: if (size > buf.length) buf.length = size; which will allocate memory once or not at all. * Check for all system calls for errors. Again, thanks Jacob for your contribution! Andrei
May 09 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-09 19:58, Andrei Alexandrescu wrote:
 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
I looked over the code, it's quite nice and clean. If you or anyone else would want to create a github pull request, the function would be a valuable addition to std.process. Thanks Jacob for offering the code to Phobos! What I think should change: * Provide two overloads, one that attempts to reuse a buffer and one that always returns a new string: char[] getProcessPath(char[] buf) { ... } static if (is(typeof(getProcessPath(null)) == char[])) { string getProcessPath() { return assumeUnique(getProcessPath(null)); } }
Not sure I understand this.
 * hoist version(OS) up to the function definition, e.g.

 version (darwin) char[] getProcessPath (char[] buf) { ... }
 version (freebsd) char[] getProcessPath (char[] buf) { ... }
 ...

 Unsupported OSs will simply not define the function (as opposed to
 asserting at run time).
Ok.
 * Use size_t instead of uint throughout for 64-bit compatibility.
I'm just following the function signature, it's declared to take an uint, like it or not: http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/dyld.3.html
 * Don't do this:

 if (size > buf.length)
 buf ~= new char[size - buf.length];

 because it allocates memory twice. Instead:

 if (size > buf.length)
 buf.length = size;

 which will allocate memory once or not at all.

 * Check for all system calls for errors.



 Again, thanks Jacob for your contribution!

 Andrei
Ok, I'll see if I can find the time to create a pull request out of this. In what module should I put the function? -- /Jacob Carlborg
May 09 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 1:48 PM, Jacob Carlborg wrote:
 On 2011-05-09 19:58, Andrei Alexandrescu wrote:
 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
I looked over the code, it's quite nice and clean. If you or anyone else would want to create a github pull request, the function would be a valuable addition to std.process. Thanks Jacob for offering the code to Phobos! What I think should change: * Provide two overloads, one that attempts to reuse a buffer and one that always returns a new string: char[] getProcessPath(char[] buf) { ... } static if (is(typeof(getProcessPath(null)) == char[])) { string getProcessPath() { return assumeUnique(getProcessPath(null)); } }
Not sure I understand this.
The static if actually refers to the next point, which implies that getProcessPath(char[]) may not exist on some systems. The idea behind having two functions is to give a string to people who just want a string without messing with buffers and all. The string has the nice property that nobody can trample on it later.
 Ok, I'll see if I can find the time to create a pull request out of
 this. In what module should I put the function?
It looks like core.runtime already allows fetching the process path name, so you need to figure out what the added value of your function is. Andrei
May 09 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-09 21:18, Andrei Alexandrescu wrote:
 On 5/9/11 1:48 PM, Jacob Carlborg wrote:
 On 2011-05-09 19:58, Andrei Alexandrescu wrote:
 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
I looked over the code, it's quite nice and clean. If you or anyone else would want to create a github pull request, the function would be a valuable addition to std.process. Thanks Jacob for offering the code to Phobos! What I think should change: * Provide two overloads, one that attempts to reuse a buffer and one that always returns a new string: char[] getProcessPath(char[] buf) { ... } static if (is(typeof(getProcessPath(null)) == char[])) { string getProcessPath() { return assumeUnique(getProcessPath(null)); } }
Not sure I understand this.
The static if actually refers to the next point, which implies that getProcessPath(char[]) may not exist on some systems. The idea behind having two functions is to give a string to people who just want a string without messing with buffers and all. The string has the nice property that nobody can trample on it later.
 Ok, I'll see if I can find the time to create a pull request out of
 this. In what module should I put the function?
It looks like core.runtime already allows fetching the process path name, so you need to figure out what the added value of your function is. Andrei
Are you referring to core.runtime.Runtime.args? That is not completely reliable because: * You can start a new process, with exec, and then pass in whatever you want as the first argument to the process. * If you start an application via a symlink wouldn't that refer to the symlink instead of the actual executable? * Also if you're running an application in a bundle on Mac OS X it would refer to the bundle and not the actual executable, if I recall correctly. -- /Jacob Carlborg
May 10 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/10/11 3:22 AM, Jacob Carlborg wrote:
 On 2011-05-09 21:18, Andrei Alexandrescu wrote:
 On 5/9/11 1:48 PM, Jacob Carlborg wrote:
 On 2011-05-09 19:58, Andrei Alexandrescu wrote:
 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to
 the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if you
 want to.
I looked over the code, it's quite nice and clean. If you or anyone else would want to create a github pull request, the function would be a valuable addition to std.process. Thanks Jacob for offering the code to Phobos! What I think should change: * Provide two overloads, one that attempts to reuse a buffer and one that always returns a new string: char[] getProcessPath(char[] buf) { ... } static if (is(typeof(getProcessPath(null)) == char[])) { string getProcessPath() { return assumeUnique(getProcessPath(null)); } }
Not sure I understand this.
The static if actually refers to the next point, which implies that getProcessPath(char[]) may not exist on some systems. The idea behind having two functions is to give a string to people who just want a string without messing with buffers and all. The string has the nice property that nobody can trample on it later.
 Ok, I'll see if I can find the time to create a pull request out of
 this. In what module should I put the function?
It looks like core.runtime already allows fetching the process path name, so you need to figure out what the added value of your function is. Andrei
Are you referring to core.runtime.Runtime.args? That is not completely reliable because: * You can start a new process, with exec, and then pass in whatever you want as the first argument to the process. * If you start an application via a symlink wouldn't that refer to the symlink instead of the actual executable? * Also if you're running an application in a bundle on Mac OS X it would refer to the bundle and not the actual executable, if I recall correctly.
I see. I'll defer ultimate decision on adding getProcessPath to Sean and Walter. Probably with a little experimentation to clarify motivation, getProcessPath is a worthy addition. Thanks, Andrei
May 10 2011
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-10 16:41, Andrei Alexandrescu wrote:
 On 5/10/11 3:22 AM, Jacob Carlborg wrote:
 On 2011-05-09 21:18, Andrei Alexandrescu wrote:
 On 5/9/11 1:48 PM, Jacob Carlborg wrote:
 On 2011-05-09 19:58, Andrei Alexandrescu wrote:
 On 5/9/11 12:24 PM, Jacob Carlborg wrote:
 I
 have a function that gets the path of the current process:

 http://dsource.org/projects/tango/attachment/ticket/1536/process.d

 This links to a file attached to a Tango ticket but don't worry, I've
 written the whole file myself and I intend to change the license to
 the
 Boost License. It's written with D1 (obviously) but it's very easy to
 port to D2, the only dependencies are C functions.

 Feel free to port it to D2 and use it in you're logging library if
 you
 want to.
I looked over the code, it's quite nice and clean. If you or anyone else would want to create a github pull request, the function would be a valuable addition to std.process. Thanks Jacob for offering the code to Phobos! What I think should change: * Provide two overloads, one that attempts to reuse a buffer and one that always returns a new string: char[] getProcessPath(char[] buf) { ... } static if (is(typeof(getProcessPath(null)) == char[])) { string getProcessPath() { return assumeUnique(getProcessPath(null)); } }
Not sure I understand this.
The static if actually refers to the next point, which implies that getProcessPath(char[]) may not exist on some systems. The idea behind having two functions is to give a string to people who just want a string without messing with buffers and all. The string has the nice property that nobody can trample on it later.
 Ok, I'll see if I can find the time to create a pull request out of
 this. In what module should I put the function?
It looks like core.runtime already allows fetching the process path name, so you need to figure out what the added value of your function is. Andrei
Are you referring to core.runtime.Runtime.args? That is not completely reliable because: * You can start a new process, with exec, and then pass in whatever you want as the first argument to the process. * If you start an application via a symlink wouldn't that refer to the symlink instead of the actual executable? * Also if you're running an application in a bundle on Mac OS X it would refer to the bundle and not the actual executable, if I recall correctly.
I see. I'll defer ultimate decision on adding getProcessPath to Sean and Walter. Probably with a little experimentation to clarify motivation, getProcessPath is a worthy addition. Thanks, Andrei
Well, I only brought it up because I didn't know about Runtime.args. -- /Jacob Carlborg
May 10 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-10 16:41, Andrei Alexandrescu wrote:
 On 5/10/11 3:22 AM, Jacob Carlborg wrote:
 Are you referring to core.runtime.Runtime.args? That is not completely
 reliable because:

 * You can start a new process, with exec, and then pass in whatever you
 want as the first argument to the process.

 * If you start an application via a symlink wouldn't that refer to the
 symlink instead of the actual executable?

 * Also if you're running an application in a bundle on Mac OS X it would
 refer to the bundle and not the actual executable, if I recall correctly.
I see. I'll defer ultimate decision on adding getProcessPath to Sean and Walter. Probably with a little experimentation to clarify motivation, getProcessPath is a worthy addition. Thanks, Andrei
Sean, Walter, is this worth including? -- /Jacob Carlborg
May 11 2011
parent reply Sean Kelly <sean invisibleduck.org> writes:
On May 11, 2011, at 11:38 AM, Jacob Carlborg wrote:

 On 2011-05-10 16:41, Andrei Alexandrescu wrote:
 On 5/10/11 3:22 AM, Jacob Carlborg wrote:
 Are you referring to core.runtime.Runtime.args? That is not completely
 reliable because:
 
 * You can start a new process, with exec, and then pass in whatever you
 want as the first argument to the process.
 
 * If you start an application via a symlink wouldn't that refer to the
 symlink instead of the actual executable?
 
 * Also if you're running an application in a bundle on Mac OS X it would
 refer to the bundle and not the actual executable, if I recall correctly.
I see. I'll defer ultimate decision on adding getProcessPath to Sean and Walter. Probably with a little experimentation to clarify motivation, getProcessPath is a worthy addition.
Sean, Walter, is this worth including?
Yes. Not sure where it should live though.
May 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/11/11 5:09 PM, Sean Kelly wrote:
 On May 11, 2011, at 11:38 AM, Jacob Carlborg wrote:

 On 2011-05-10 16:41, Andrei Alexandrescu wrote:
 On 5/10/11 3:22 AM, Jacob Carlborg wrote:
 Are you referring to core.runtime.Runtime.args? That is not completely
 reliable because:

 * You can start a new process, with exec, and then pass in whatever you
 want as the first argument to the process.

 * If you start an application via a symlink wouldn't that refer to the
 symlink instead of the actual executable?

 * Also if you're running an application in a bundle on Mac OS X it would
 refer to the bundle and not the actual executable, if I recall correctly.
I see. I'll defer ultimate decision on adding getProcessPath to Sean and Walter. Probably with a little experimentation to clarify motivation, getProcessPath is a worthy addition.
Sean, Walter, is this worth including?
Yes. Not sure where it should live though.
http://d-programming-language.org/phobos/std_process.html Jacob, please write a pull request with documentation (including motivation by comparison with core.Runtime.args), unittests, the works, and provided the quality is up to snuff we'll make sure we merge it in. Thanks! Andrei
May 11 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-05-12 05:38, Andrei Alexandrescu wrote:
 On 5/11/11 5:09 PM, Sean Kelly wrote:
 On May 11, 2011, at 11:38 AM, Jacob Carlborg wrote:

 On 2011-05-10 16:41, Andrei Alexandrescu wrote:
 On 5/10/11 3:22 AM, Jacob Carlborg wrote:
 Are you referring to core.runtime.Runtime.args? That is not completely
 reliable because:

 * You can start a new process, with exec, and then pass in whatever
 you
 want as the first argument to the process.

 * If you start an application via a symlink wouldn't that refer to the
 symlink instead of the actual executable?

 * Also if you're running an application in a bundle on Mac OS X it
 would
 refer to the bundle and not the actual executable, if I recall
 correctly.
I see. I'll defer ultimate decision on adding getProcessPath to Sean and Walter. Probably with a little experimentation to clarify motivation, getProcessPath is a worthy addition.
Sean, Walter, is this worth including?
Yes. Not sure where it should live though.
http://d-programming-language.org/phobos/std_process.html Jacob, please write a pull request with documentation (including motivation by comparison with core.Runtime.args), unittests, the works, and provided the quality is up to snuff we'll make sure we merge it in. Thanks! Andrei
I'll do this as soon as I can find the time, although it's not on the top of my priority list. -- /Jacob Carlborg
May 12 2011
prev sibling next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 09/05/2011 07:52, Andrei Alexandrescu wrote:
 On 5/7/11 3:43 PM, Jose Armando Garcia wrote:
 Hey folks,

 For the past couple of days I took the liberty of partially
 implementing a logging module for D.
[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
The example looks great, exactly what I'd hope for in the way of a logging library. A few questions: * How do you disable logging at compile time? (and is it zero overhead?) * How do you define your own logging backend? * Is it possible to change logging options after initialisation? There are a couple of features missing, but you seem to have mentioned planning to implement these elsewhere in the thread. Once they're in place I'd be happy to vote yes to its inclusion into phobos. -- Robert http://octarineparrot.com/
May 09 2011
next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 09/05/2011 19:30, Robert Clipsham wrote:
 The example looks great, exactly what I'd hope for in the way of a
 logging library. A few questions:

 * How do you disable logging at compile time? (and is it zero overhead?)
 * How do you define your own logging backend?
 * Is it possible to change logging options after initialisation?

 There are a couple of features missing, but you seem to have mentioned
 planning to implement these elsewhere in the thread. Once they're in
 place I'd be happy to vote yes to its inclusion into phobos.
One more question: * Can you log using formatting, or do you have to wrap the call in a call to format()? eg. ---- log.info("My %s string %s", "format", 3); ---- -- Robert http://octarineparrot.com/
May 09 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 1:33 PM, Robert Clipsham wrote:
 On 09/05/2011 19:30, Robert Clipsham wrote:
 The example looks great, exactly what I'd hope for in the way of a
 logging library. A few questions:

 * How do you disable logging at compile time? (and is it zero overhead?)
 * How do you define your own logging backend?
 * Is it possible to change logging options after initialisation?

 There are a couple of features missing, but you seem to have mentioned
 planning to implement these elsewhere in the thread. Once they're in
 place I'd be happy to vote yes to its inclusion into phobos.
One more question: * Can you log using formatting, or do you have to wrap the call in a call to format()? eg. ---- log.info("My %s string %s", "format", 3); ----
I thought I'd leave that to format(), but probably it's worth just putting the feature in std.log too. One nice thing about supporting format directly is that often there's no need to allocate memory while logging. Andrei
May 09 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 1:30 PM, Robert Clipsham wrote:
 On 09/05/2011 07:52, Andrei Alexandrescu wrote:
 On 5/7/11 3:43 PM, Jose Armando Garcia wrote:
 Hey folks,

 For the past couple of days I took the liberty of partially
 implementing a logging module for D.
[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
The example looks great, exactly what I'd hope for in the way of a logging library. A few questions: * How do you disable logging at compile time? (and is it zero overhead?)
Passing -version=strip_log_error during compilation strips all error, warning, and info messages; passing -version=strip_log_warning strips all warning and info messages; and passing -version=strip_log_info strips all info messages. The critical and fatal logs cannot be stripped out. With -O -release -inline, log.info(arguments) leaves no trace in the generated object file. However, log.info.when(condition)(arguments) does leave a few calls behind. This is an issue in the inliner that will need to be fixed before releasing std.log.
 * How do you define your own logging backend?
Currently the backend API is not exposed. The focus now is to get good client-level functionality in shape, after which we can work on a more refined API. We'll also need to tune the code to not generate undue bloating.
 * Is it possible to change logging options after initialisation?
Not for the time being. I agree that that's a good thing to have. Everything is ready for exposure, so writing a couple of extra APIs should be easy.
 There are a couple of features missing, but you seem to have mentioned
 planning to implement these elsewhere in the thread. Once they're in
 place I'd be happy to vote yes to its inclusion into phobos.
Sounds great! Andrei
May 09 2011
prev sibling next sibling parent reply Jens Mueller <jens.k.mueller gmx.de> writes:
Andrei Alexandrescu wrote:
 On 5/7/11 3:43 PM, Jose Armando Garcia wrote:
Hey folks,

For the past couple of days I took the liberty of partially
implementing a logging module for D.
[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter.
I think every() behaves strangely. Because the counter is per function. But it should be per logging statement. std.log differs here from glog and this seems incorrect to me. everyMs() has a similar problem. Even though I believe log.vlog is necessary I often find it difficult to come up with an appropriate level for a given statement. With normal logging it is often obvious whether info, warning, error, critical, or fatal is appropriate. But this is a minor problem and more a matter of coding style. I'd like to try out the code. I'd be very pleased if you can make a compiling version available on github. I'd like to test whether there is no code generated if -version=strip_log_error etc. is specified. I.e. whether the call to an empty function will always be removed. Jens
May 09 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 3:12 PM, Jens Mueller wrote:
 I think every() behaves strangely. Because the counter is per function.
 But it should be per logging statement. std.log differs here from glog
 and this seems incorrect to me. everyMs() has a similar problem.
Actually, they behave correctly. The counters for every and everyMs are static and generated per instantiation of the function. Since each instantiation is determined by __FILE__ and __LINE__, there is a different counters for each __FILE__/__LINE__ combination.
 Even though I believe log.vlog is necessary I often find it difficult to
 come up with an appropriate level for a given statement. With normal
 logging it is often obvious whether info, warning, error, critical, or
 fatal is appropriate. But this is a minor problem and more a matter of
 coding style.
No need to use vlog. But a variety of programs (e.g. ssh) decide quite precisely what will be logged at each verbosity level.
 I'd like to try out the code. I'd be very pleased if you can make a
 compiling version available on github. I'd like to test whether there is
 no code generated if -version=strip_log_error etc. is specified. I.e.
 whether the call to an empty function will always be removed.
Thanks for your interest. I just committed the code to my repo: https://github.com/andralex/phobos You'd need the latest dmd and druntime to compile Phobos. Andrei
May 10 2011
parent Jens Mueller <jens.k.mueller gmx.de> writes:
Andrei Alexandrescu wrote:
 On 5/9/11 3:12 PM, Jens Mueller wrote:
I think every() behaves strangely. Because the counter is per function.
But it should be per logging statement. std.log differs here from glog
and this seems incorrect to me. everyMs() has a similar problem.
Actually, they behave correctly. The counters for every and everyMs are static and generated per instantiation of the function. Since each instantiation is determined by __FILE__ and __LINE__, there is a different counters for each __FILE__/__LINE__ combination.
Oh yes. Now I see. I missed the template arguments. Sorry. Now I also understand why you want to cut down the possible code bloat.
Even though I believe log.vlog is necessary I often find it difficult to
come up with an appropriate level for a given statement. With normal
logging it is often obvious whether info, warning, error, critical, or
fatal is appropriate. But this is a minor problem and more a matter of
coding style.
No need to use vlog. But a variety of programs (e.g. ssh) decide quite precisely what will be logged at each verbosity level.
Maybe it helps that you provide -v as incremental options. Glog does not do it like this. But I think allowing incremental options helps here. It tells the user to use vlog(0) for the least verbose messages and so on incrementally for more verbosity.
I'd like to try out the code. I'd be very pleased if you can make a
compiling version available on github. I'd like to test whether there is
no code generated if -version=strip_log_error etc. is specified. I.e.
whether the call to an empty function will always be removed.
Thanks for your interest. I just committed the code to my repo: https://github.com/andralex/phobos You'd need the latest dmd and druntime to compile Phobos.
Thanks. I'll try it out. Jens
May 11 2011
prev sibling next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
On 5/9/2011 2:52 AM, Andrei Alexandrescu wrote:
 As I mentioned I'd already decided I'll take a stab at implementing a
 logging module inspired in design from glog. I was tired of the endless
 discussions on what a logging API should look like. This ironically is
 leading now to an embarrassment of riches - we now have two proposals on
 the table. I subjectively prefer mine for the simple reason that it
 includes exactly what I wanted from a logging subsystem with a light
 syntax.
I noticed this was recently checked into Phobos. What's its status? Is it experimental? Is it for inclusion in the upcoming (2.053) release? Is it for 2.054 (the next release after)?
May 11 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/11/2011 08:46 AM, dsimcha wrote:
 On 5/9/2011 2:52 AM, Andrei Alexandrescu wrote:
 As I mentioned I'd already decided I'll take a stab at implementing a
 logging module inspired in design from glog. I was tired of the endless
 discussions on what a logging API should look like. This ironically is
 leading now to an embarrassment of riches - we now have two proposals on
 the table. I subjectively prefer mine for the simple reason that it
 includes exactly what I wanted from a logging subsystem with a light
 syntax.
I noticed this was recently checked into Phobos. What's its status? Is it experimental? Is it for inclusion in the upcoming (2.053) release? Is it for 2.054 (the next release after)?
Ouch. Pushing to Phobos is a mistake, I meant to only push it to my own fork of Phobos. I wouldn't dream of pushing a new module without going through the review process, and even less so since there's a competing proposal. How do I undo that push? Thanks, Andrei
May 11 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/11/2011 09:15 AM, Andrei Alexandrescu wrote:
 On 05/11/2011 08:46 AM, dsimcha wrote:
 On 5/9/2011 2:52 AM, Andrei Alexandrescu wrote:
 As I mentioned I'd already decided I'll take a stab at implementing a
 logging module inspired in design from glog. I was tired of the endless
 discussions on what a logging API should look like. This ironically is
 leading now to an embarrassment of riches - we now have two proposals on
 the table. I subjectively prefer mine for the simple reason that it
 includes exactly what I wanted from a logging subsystem with a light
 syntax.
I noticed this was recently checked into Phobos. What's its status? Is it experimental? Is it for inclusion in the upcoming (2.053) release? Is it for 2.054 (the next release after)?
Ouch. Pushing to Phobos is a mistake, I meant to only push it to my own fork of Phobos. I wouldn't dream of pushing a new module without going through the review process, and even less so since there's a competing proposal. How do I undo that push? Thanks, Andrei
I removed std.log from Phobos. I left in support for positional parameter ranges, e.g. writefln("%1$u:%2:3$s-%4:$s", ...); prints the first argument with spec u, the second and third with the spec s, and everything else with the spec s. Andrei
May 11 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
[snip]

I updated my std.log draft. Added a lot of features including formatted 
writing, delayed logging, and a variety of configuration options. 
Replaced the redundant log.xyz with logXyz. The implementation is 
getting close to reviewable form.

Documentation:

http://d-programming-language.org/phobos-prerelease/std_log.html

Source:

https://github.com/andralex/phobos

Feedback welcome.


Thanks,

Andrei
May 14 2011
next sibling parent reply dsimcha <dsimcha yahoo.com> writes:
On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
Overall, I like this library a lot. One comment, though, is that the docs should be more explicit about threading issues. I assume it's going to be made thread-safe before inclusion in Phobos. Also, is there any way to get thread-specific logs instead of having them intermingled?
May 14 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/14/2011 01:29 PM, dsimcha wrote:
 On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
Overall, I like this library a lot. One comment, though, is that the docs should be more explicit about threading issues. I assume it's going to be made thread-safe before inclusion in Phobos. Also, is there any way to get thread-specific logs instead of having them intermingled?
Logs will be thread-shared. I haven't seen a need for thread-local logs. Andrei
May 14 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-14 12:36, Andrei Alexandrescu wrote:
 On 05/14/2011 01:29 PM, dsimcha wrote:
 On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]
 
 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.
 
 Documentation:
 
 http://d-programming-language.org/phobos-prerelease/std_log.html
 
 Source:
 
 https://github.com/andralex/phobos
 
 Feedback welcome.
 
 
 Thanks,
 
 Andrei
Overall, I like this library a lot. One comment, though, is that the docs should be more explicit about threading issues. I assume it's going to be made thread-safe before inclusion in Phobos. Also, is there any way to get thread-specific logs instead of having them intermingled?
Logs will be thread-shared. I haven't seen a need for thread-local logs.
I've dealt with code before where it was critical to know which log messages came from which thread if you had any hope of debugging what was going on. However, what I did was have the ID of each thread put at the beginning of every logged line, and it actually would have been a problem for them to be in separate logs, because it would have lost the timing. Of course, part of what I was doing there was tracking down problems with mutexes and race conditions and the like (and the code was _really_ bad about how it handled threads - every thread could be _anywhere_; no segregation at all), and that sort of problem isn't likely to crop up in D code. Still, knowing which thread is logging a particular message can be very useful. However, I question the usefulness of separating the log into thread-specific logs. It might be useful if std.log had an option to print the Thread's name at the beginning of every log line, but if not, someone who wanted that could always just include that at the beginning of their log messages. So, I do think that knowing which thread is logging what could be very important for some programs, but I don't think that separating the log files is necessarily a good idea. If you did, you'd lose timing information (unless the time is at the beginning of every log line (which could also be useful), but then you'd have to read the times and compare them to see what happened before what). So, I'd be all for some options and extra information which could be added to each log line which would help debugging, but I don't think that thread-local logs is a great idea. - Jonathan M Davis
May 14 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/14/2011 04:31 PM, Jonathan M Davis wrote:
 On 2011-05-14 12:36, Andrei Alexandrescu wrote:
 On 05/14/2011 01:29 PM, dsimcha wrote:
 On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
Overall, I like this library a lot. One comment, though, is that the docs should be more explicit about threading issues. I assume it's going to be made thread-safe before inclusion in Phobos. Also, is there any way to get thread-specific logs instead of having them intermingled?
Logs will be thread-shared. I haven't seen a need for thread-local logs.
I've dealt with code before where it was critical to know which log messages came from which thread if you had any hope of debugging what was going on.
Just like glog, std.log outputs the thread ID for each log line. See the eighth parameter of http://d-programming-language.org/phobos-prerelease/std_log.html#logLinePrefix Andrei
May 14 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-14 14:50, Andrei Alexandrescu wrote:
 On 05/14/2011 04:31 PM, Jonathan M Davis wrote:
 On 2011-05-14 12:36, Andrei Alexandrescu wrote:
 On 05/14/2011 01:29 PM, dsimcha wrote:
 On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]
 
 I updated my std.log draft. Added a lot of features including
 formatted writing, delayed logging, and a variety of configuration
 options. Replaced the redundant log.xyz with logXyz. The
 implementation is getting close to reviewable form.
 
 Documentation:
 
 http://d-programming-language.org/phobos-prerelease/std_log.html
 
 Source:
 
 https://github.com/andralex/phobos
 
 Feedback welcome.
 
 
 Thanks,
 
 Andrei
Overall, I like this library a lot. One comment, though, is that the docs should be more explicit about threading issues. I assume it's going to be made thread-safe before inclusion in Phobos. Also, is there any way to get thread-specific logs instead of having them intermingled?
Logs will be thread-shared. I haven't seen a need for thread-local logs.
I've dealt with code before where it was critical to know which log messages came from which thread if you had any hope of debugging what was going on.
Just like glog, std.log outputs the thread ID for each log line. See the eighth parameter of http://d-programming-language.org/phobos-prerelease/std_log.html#logLinePre fix
Ah, good to know. I haven't a had chance to look at it yet, and I'd never even heard of glog before you brought it up on the newsgroup, so I'm not particularly familiar with how the logging is set up. I just thought that I'd share my thoughts on logging separate threads. However, looking at logLinePrefix, it looks quite good. By the way, you should probably add sample strings of what the default format strings generate. Deciphering exactly what a formatted string is going to generate is a lot harder to do than when seeing an example string that was generated from it. - Jonathan M Davis
May 14 2011
prev sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> said:

 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log files
 is necessarily a good idea. If you did, you'd lose timing information (unless
 the time is at the beginning of every log line (which could also be useful),
 but then you'd have to read the times and compare them to see what happened
 before what). So, I'd be all for some options and extra information which
 could be added to each log line which would help debugging, but I don't think
 that thread-local logs is a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files. I'll also question whether they should be written to files at all by default (as opposed to stdin and stderr). I'm aware initLogging's
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Your post just went asian on me. http://i.imgur.com/solwD.png
May 14 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> said:
 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files is necessarily a good idea. If you did, you'd lose timing
 information (unless the time is at the beginning of every log line
 (which could also be useful), but then you'd have to read the times and
 compare them to see what happened before what). So, I'd be all for some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file. - Jonathan M Davis
May 14 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>  said:
 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files is necessarily a good idea. If you did, you'd lose timing
 information (unless the time is at the beginning of every log line
 (which could also be useful), but then you'd have to read the times and
 compare them to see what happened before what). So, I'd be all for some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels. Generally I'd want to stray from glog's major design decision as little as possible. It's an approach validated by years of experience in heavy-duty applications. Also, people coming from glog and used to its features would find it unpleasant that we decided to do things a different way without solid reasons. Andrei
May 14 2011
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-05-14 18:33:06 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 I'd even go further and question whether it makes sense to have info,
 warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels.
That's better then, even though it's not very obvious. Perhaps it should be called "all" instead of "info". Is that stated somewhere in the documentation? I seem to have missed it. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 14 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/14/2011 06:36 PM, Michel Fortin wrote:
 On 2011-05-14 18:33:06 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 I'd even go further and question whether it makes sense to have info,
 warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels.
That's better then, even though it's not very obvious. Perhaps it should be called "all" instead of "info". Is that stated somewhere in the documentation? I seem to have missed it.
http://d-programming-language.org/phobos-prerelease/std_log.html "Any message logged at a given severity is also logged in logs of lesser severity. Logging to the fatal log always terminates the application after logging. Logging to the critical log always throws an exception after logging." Unless we fix a painful design mistake of glog, I'd keep names as they are. I did diverge from their API with the "critical" log, which throws. Google doesn't use exceptions so they didn't need a critical log. Andrei
May 14 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-14 15:33, Andrei Alexandrescu wrote:
 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>  
said:
 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files is necessarily a good idea. If you did, you'd lose timing
 information (unless the time is at the beginning of every log line
 (which could also be useful), but then you'd have to read the times and
 compare them to see what happened before what). So, I'd be all for some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels. Generally I'd want to stray from glog's major design decision as little as possible. It's an approach validated by years of experience in heavy-duty applications. Also, people coming from glog and used to its features would find it unpleasant that we decided to do things a different way without solid reasons.
If it's based on glog, it makes sense for it to generally stick to what glog does. However, if it's forcing you to put all of the different log levels in different files, then I'd argue that that was a poor design choice on the part of glog and that we should not stick to it. However, if they all end up in the info log, then it's not that bad. Now, I'd still love to be able to tell it only have the info log then and not bother with multiple logs, but at least it's possible to get it all in one log. - Jonathan M Davis
May 14 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-15 00:33, Andrei Alexandrescu wrote:
 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>
 said:
 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files is necessarily a good idea. If you did, you'd lose timing
 information (unless the time is at the beginning of every log line
 (which could also be useful), but then you'd have to read the times and
 compare them to see what happened before what). So, I'd be all for some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels. Generally I'd want to stray from glog's major design decision as little as possible. It's an approach validated by years of experience in heavy-duty applications. Also, people coming from glog and used to its features would find it unpleasant that we decided to do things a different way without solid reasons. Andrei
Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog. I think that, in general, that is a poor argument: "Because library A does it like that we also have to do it like that". What about all people coming from library B, C, D and so on, it will be unpleasant for those as well because we didn't follow their particular library design. -- /Jacob Carlborg
May 15 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/15/2011 10:26 AM, Jacob Carlborg wrote:
 On 2011-05-15 00:33, Andrei Alexandrescu wrote:
 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>
 said:
 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files is necessarily a good idea. If you did, you'd lose timing
 information (unless the time is at the beginning of every log line
 (which could also be useful), but then you'd have to read the times
 and
 compare them to see what happened before what). So, I'd be all for
 some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local
 logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels. Generally I'd want to stray from glog's major design decision as little as possible. It's an approach validated by years of experience in heavy-duty applications. Also, people coming from glog and used to its features would find it unpleasant that we decided to do things a different way without solid reasons. Andrei
Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog.
That's beside the point as the documentation could and should be changed. I've said repeatedly it's based on glog, and I think it's a good thing.
 I think that, in general, that is a poor
 argument: "Because library A does it like that we also have to do it
 like that". What about all people coming from library B, C, D and so on,
 it will be unpleasant for those as well because we didn't follow their
 particular library design.
It's a good argument if library A is considered better by the person making the argument than B, C, and D. One thing is that glog has most desirable qualities I am looking for in a logging library: allows compile-time and run-time enabling/disabling, it's relatively small, it's simple, it's effective, and is widely used. I'm sure there are other libraries that score better on either dimension, but not on all. There are two departures I chose to make from glog: (a) I added the critical log which throws an exceptions (Google wouldn't need one because they don't use exceptions), and (b) I replaced the clunky LOG_IF_EVERY_N etc. with the flexible when(), every(), after() etc. I think these are well justified choices. Andrei
May 15 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-15 16:01, Andrei Alexandrescu wrote:
 On 05/15/2011 10:26 AM, Jacob Carlborg wrote:
 On 2011-05-15 00:33, Andrei Alexandrescu wrote:
 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>
 
 said:
 So, I do think that knowing which thread is logging what could be
 very important for some programs, but I don't think that separating
 the log files is necessarily a good idea. If you did, you'd lose
 timing information (unless the time is at the beginning of every log
 line (which could also be useful), but then you'd have to read the
 times and
 compare them to see what happened before what). So, I'd be all for
 some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local
 logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels. Generally I'd want to stray from glog's major design decision as little as possible. It's an approach validated by years of experience in heavy-duty applications. Also, people coming from glog and used to its features would find it unpleasant that we decided to do things a different way without solid reasons. Andrei
Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog.
That's beside the point as the documentation could and should be changed. I've said repeatedly it's based on glog, and I think it's a good thing.
 I think that, in general, that is a poor
 argument: "Because library A does it like that we also have to do it
 like that". What about all people coming from library B, C, D and so on,
 it will be unpleasant for those as well because we didn't follow their
 particular library design.
It's a good argument if library A is considered better by the person making the argument than B, C, and D. One thing is that glog has most desirable qualities I am looking for in a logging library: allows compile-time and run-time enabling/disabling, it's relatively small, it's simple, it's effective, and is widely used. I'm sure there are other libraries that score better on either dimension, but not on all. There are two departures I chose to make from glog: (a) I added the critical log which throws an exceptions (Google wouldn't need one because they don't use exceptions), and (b) I replaced the clunky LOG_IF_EVERY_N etc. with the flexible when(), every(), after() etc. I think these are well justified choices.
I think that it makes good sense to start with an API based on an existing API which is known and heavily used and then adjust it as appropriate to our needs. In doing so, we might as well leave it the same as the original where we don't need to change it, since there is some gain for those familiar with the original. However, the real question then is where it does and doesn't make sense to change it. If enough people agree with Andrei on those decisions, then it will likely become std.log. However, if there's enough disagreement, and we can't reach an appropriate compromise on such changes, then it likely won't become std.log. Hopefully we can come a solid design based on glog with whatever changes we actually need without having to drastically change what it does in comparison to glog. That would be ideal. However, I also think that if it really looks like the general consensus is against something about how glog does things, we shouldn't be married to how glog works. So, overall, I agree with Andrei. The devil is the details, however. - Jonathan M Davis
May 15 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-05-16 01:27, Jonathan M Davis wrote:
 On 2011-05-15 16:01, Andrei Alexandrescu wrote:
 On 05/15/2011 10:26 AM, Jacob Carlborg wrote:
 On 2011-05-15 00:33, Andrei Alexandrescu wrote:
 On 05/14/2011 05:17 PM, Jonathan M Davis wrote:
 On 2011-05-14 14:56, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>

 said:
 So, I do think that knowing which thread is logging what could be
 very important for some programs, but I don't think that separating
 the log files is necessarily a good idea. If you did, you'd lose
 timing information (unless the time is at the beginning of every log
 line (which could also be useful), but then you'd have to read the
 times and
 compare them to see what happened before what). So, I'd be all for
 some
 options and extra information which could be added to each log line
 which would help debugging, but I don't think that thread-local
 logs is
 a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files.
I'd definitely vote for them all to be in the same file, but I don't generally see much benefit in having multiple log files. I like having them all in one place where you can see what happened in what order. Having them in separate log files is just going to make it harder to figure out what happened, and I think that it would become tempting (for me at least) to just log everything at exactly the same level so that they ended up in the same file.
The info log contains log messages for all levels. Generally I'd want to stray from glog's major design decision as little as possible. It's an approach validated by years of experience in heavy-duty applications. Also, people coming from glog and used to its features would find it unpleasant that we decided to do things a different way without solid reasons. Andrei
Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog.
That's beside the point as the documentation could and should be changed. I've said repeatedly it's based on glog, and I think it's a good thing.
 I think that, in general, that is a poor
 argument: "Because library A does it like that we also have to do it
 like that". What about all people coming from library B, C, D and so on,
 it will be unpleasant for those as well because we didn't follow their
 particular library design.
It's a good argument if library A is considered better by the person making the argument than B, C, and D. One thing is that glog has most desirable qualities I am looking for in a logging library: allows compile-time and run-time enabling/disabling, it's relatively small, it's simple, it's effective, and is widely used. I'm sure there are other libraries that score better on either dimension, but not on all. There are two departures I chose to make from glog: (a) I added the critical log which throws an exceptions (Google wouldn't need one because they don't use exceptions), and (b) I replaced the clunky LOG_IF_EVERY_N etc. with the flexible when(), every(), after() etc. I think these are well justified choices.
I think that it makes good sense to start with an API based on an existing API which is known and heavily used and then adjust it as appropriate to our needs. In doing so, we might as well leave it the same as the original where we don't need to change it, since there is some gain for those familiar with the original. However, the real question then is where it does and doesn't make sense to change it. If enough people agree with Andrei on those decisions, then it will likely become std.log. However, if there's enough disagreement, and we can't reach an appropriate compromise on such changes, then it likely won't become std.log. Hopefully we can come a solid design based on glog with whatever changes we actually need without having to drastically change what it does in comparison to glog. That would be ideal. However, I also think that if it really looks like the general consensus is against something about how glog does things, we shouldn't be married to how glog works. So, overall, I agree with Andrei. The devil is the details, however. - Jonathan M Davis
I agree with Jonathan, if glog is good enough we can follow its design but if it isn't, we shouldn't hesitate to make some design changes. The approach I take when designing an API for a library I'm writing I look at the API of several other libraries that does the same thing. Then I try to take the best parts and the parts I like of each library and combine them into something that make sense. -- /Jacob Carlborg
May 17 2011
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/14/2011 04:56 PM, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> said:

 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files
 is necessarily a good idea. If you did, you'd lose timing information
 (unless
 the time is at the beginning of every log line (which could also be
 useful),
 but then you'd have to read the times and compare them to see what
 happened
 before what). So, I'd be all for some options and extra information which
 could be added to each log line which would help debugging, but I
 don't think
 that thread-local logs is a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files. I'll also question whether they should be written to files at all by default (as opposed to stdin and stderr). I'm aware initLogging's
next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-05-14 18:35:32 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 On 05/14/2011 04:56 PM, Michel Fortin wrote:
 I'll also question whether they should be written to files at all by
 default (as opposed to stdin and stderr). I'm aware initLogging's
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/14/11 6:43 PM, Michel Fortin wrote:
 On 2011-05-14 18:35:32 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 On 05/14/2011 04:56 PM, Michel Fortin wrote:
 I'll also question whether they should be written to files at all by
 default (as opposed to stdin and stderr). I'm aware initLogging's
prev sibling next sibling parent reply Brad Roberts <braddr puremagic.com> writes:
On 5/14/2011 3:35 PM, Andrei Alexandrescu wrote:
 On 05/14/2011 04:56 PM, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> said:

 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files
 is necessarily a good idea. If you did, you'd lose timing information
 (unless
 the time is at the beginning of every log line (which could also be
 useful),
 but then you'd have to read the times and compare them to see what
 happened
 before what). So, I'd be all for some options and extra information which
 could be added to each log line which would help debugging, but I
 don't think
 that thread-local logs is a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files. I'll also question whether they should be written to files at all by default (as opposed to stdin and stderr). I'm aware initLogging's
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/14/11 7:13 PM, Brad Roberts wrote:
 On 5/14/2011 3:35 PM, Andrei Alexandrescu wrote:
 On 05/14/2011 04:56 PM, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>  said:

 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files
 is necessarily a good idea. If you did, you'd lose timing information
 (unless
 the time is at the beginning of every log line (which could also be
 useful),
 but then you'd have to read the times and compare them to see what
 happened
 before what). So, I'd be all for some options and extra information which
 could be added to each log line which would help debugging, but I
 don't think
 that thread-local logs is a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files. I'll also question whether they should be written to files at all by default (as opposed to stdin and stderr). I'm aware initLogging's
prev sibling parent reply Jens Mueller <jens.k.mueller gmx.de> writes:
Andrei Alexandrescu wrote:
 On 05/14/2011 04:56 PM, Michel Fortin wrote:
On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> sai=
d:
So, I do think that knowing which thread is logging what could be very
important for some programs, but I don't think that separating the log
files
is necessarily a good idea. If you did, you'd lose timing information
(unless
the time is at the beginning of every log line (which could also be
useful),
but then you'd have to read the times and compare them to see what
happened
before what). So, I'd be all for some options and extra information whi=
ch
could be added to each log line which would help debugging, but I
don't think
that thread-local logs is a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files. I'll also question whether they should be written to files at all by default (as opposed to stdin and stderr). I'm aware initLogging's documentation says: "If log=ADging is ef=ADfected with=ADout hav=ADing c=
alled
this func=ADtion, all pa=ADra=ADme=ADters are at their de=ADfault val=AD=
ues and all
log=ADging is done only to stderr." So basically, I'll get what I want if
I never call initLogging, but then I can't control verbosity and other
settings using --v and other flags passed as arguments.
=20 A server app must log to files, no question about that. We'll need to add rotation etc. in the future. But I do plan to offer ways to manually override defaults, e.g.: =20 void main(string[] args) { logtostderr =3D true; // override default initLogging(args); ... }
How do you plan to do this? Because it looks partly what gflags is doing. At least it would be useful as general feature for handling program options. I haven't found a way to define flags in a compilation unit as gflags does. I have code that generates a help string and even reading flags =66rom a files is easy. But I have no clue yet how to allow declaring flags in different compilation units. Technically I'd like to allow each flag that can be handled by std.getopt but I have no idea how to check whether getopt supports a given flag. If I knew I'd store flags in associative array where values are Algebratic!(GetoptFlagTypes). Jens
May 15 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/15/2011 10:53 AM, Jens Mueller wrote:
 Andrei Alexandrescu wrote:
 On 05/14/2011 04:56 PM, Michel Fortin wrote:
 On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>  said:

 So, I do think that knowing which thread is logging what could be very
 important for some programs, but I don't think that separating the log
 files
 is necessarily a good idea. If you did, you'd lose timing information
 (unless
 the time is at the beginning of every log line (which could also be
 useful),
 but then you'd have to read the times and compare them to see what
 happened
 before what). So, I'd be all for some options and extra information which
 could be added to each log line which would help debugging, but I
 don't think
 that thread-local logs is a great idea.
I'd even go further and question whether it makes sense to have info, warning, and errors be written to separate files. I'll also question whether they should be written to files at all by default (as opposed to stdin and stderr). I'm aware initLogging's
prev sibling next sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 14/05/2011 18:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
I far prefered log.xyz to logXyz... The latter just looks ugly in my opinion. A also notice all those functions return FileLoggers, how will this work when other backends are supported? -- Robert http://octarineparrot.com/
May 14 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/14/2011 02:50 PM, Robert Clipsham wrote:
 On 14/05/2011 18:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
I far prefered log.xyz to logXyz... The latter just looks ugly in my opinion.
There are a few problems with log.xyz. For one, std.log.log.info is terrible. Second, I found absolutely no justification to provide the dummy struct "log" just to keep five predefined logs in there. Them being individual entities allows the user to define their own logs with the same look and feel, e.g. logRemote.
 A also notice all those functions return FileLoggers, how will
 this work when other backends are supported?
I want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name). Andrei
May 14 2011
next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 14/05/2011 21:37, Andrei Alexandrescu wrote:
 On 05/14/2011 02:50 PM, Robert Clipsham wrote:
 On 14/05/2011 18:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
I far prefered log.xyz to logXyz... The latter just looks ugly in my opinion.
There are a few problems with log.xyz. For one, std.log.log.info is terrible. Second, I found absolutely no justification to provide the dummy struct "log" just to keep five predefined logs in there. Them being individual entities allows the user to define their own logs with the same look and feel, e.g. logRemote.
In which case, wouldn't xyz alone be better? Then you have std.log.info, etc. Renamed imports can be used to get log.info etc.
 A also notice all those functions return FileLoggers, how will
 this work when other backends are supported?
I want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name).
Fair enough. I keep asking as it's essential functionality for me. -- Robert http://octarineparrot.com/
May 14 2011
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-14 22:37, Andrei Alexandrescu wrote:
 On 05/14/2011 02:50 PM, Robert Clipsham wrote:
 On 14/05/2011 18:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
I far prefered log.xyz to logXyz... The latter just looks ugly in my opinion.
There are a few problems with log.xyz. For one, std.log.log.info is terrible. Second, I found absolutely no justification to provide the dummy struct "log" just to keep five predefined logs in there. Them being individual entities allows the user to define their own logs with the same look and feel, e.g. logRemote.
 A also notice all those functions return FileLoggers, how will
 this work when other backends are supported?
I want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name). Andrei
The obvious solution would be to have the logging functions returning an interface, Logger, but interfaces seem to be banned from Phobos. Ok, I see now, since templates are used this can be a problem. Hmm, templates are used EVERYWHERE in Phobos. -- /Jacob Carlborg
May 15 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/15/2011 10:22 AM, Jacob Carlborg wrote:
 On 2011-05-14 22:37, Andrei Alexandrescu wrote:
 I want to nail usability before extension. Extensibility can be provided
 via an indirection inside FileLogger (which should indeed receive a more
 appropriate name).


 Andrei
The obvious solution would be to have the logging functions returning an interface, Logger, but interfaces seem to be banned from Phobos. Ok, I see now, since templates are used this can be a problem. Hmm, templates are used EVERYWHERE in Phobos.
No need to be ironic. Interfaces are the obvious solution, and what I meant when I said "indirection" (i.e. via a reference type, either interface or class). That being said, I think your design has a number of issues that I'll get into soon. Andrei
May 15 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-05-16 01:04, Andrei Alexandrescu wrote:
 On 05/15/2011 10:22 AM, Jacob Carlborg wrote:
 On 2011-05-14 22:37, Andrei Alexandrescu wrote:
 I want to nail usability before extension. Extensibility can be provided
 via an indirection inside FileLogger (which should indeed receive a more
 appropriate name).


 Andrei
The obvious solution would be to have the logging functions returning an interface, Logger, but interfaces seem to be banned from Phobos. Ok, I see now, since templates are used this can be a problem. Hmm, templates are used EVERYWHERE in Phobos.
No need to be ironic. Interfaces are the obvious solution, and what I meant when I said "indirection" (i.e. via a reference type, either interface or class). That being said, I think your design has a number of issues that I'll get into soon. Andrei
It wasn't my intention to be ironic. I missed "indirection" and just read something about "inside FileLogger". -- /Jacob Carlborg
May 17 2011
prev sibling next sibling parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-05-14 13:04:54 -0400, Andrei Alexandrescu 
<SeeWebsiteForEmail erdani.org> said:

 Documentation:
 
 http://d-programming-language.org/phobos-prerelease/std_log.html
 
 Source:
 
 https://github.com/andralex/phobos
 
 Feedback welcome.
Shouldn't "everyMs" and "afterMs" accept any of core.time's duration types instead of being fixed in milliseconds? -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 14 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-14 16:35, Michel Fortin wrote:
 On 2011-05-14 13:04:54 -0400, Andrei Alexandrescu
 
 <SeeWebsiteForEmail erdani.org> said:
 Documentation:
 
 http://d-programming-language.org/phobos-prerelease/std_log.html
 
 Source:
 
 https://github.com/andralex/phobos
 
 Feedback welcome.
Shouldn't "everyMs" and "afterMs" accept any of core.time's duration types instead of being fixed in milliseconds?
I'd vote for that. Then again, I'm tempted to argue that we shouldn't have _any_ time-related functions which take naked numbers. There are several time- related functions in druntime and Phobos which still have versions which take naked numbers. They may all now have versions which take a core.time.Duration, but most of them still have versions which takes a naked number and which have not be scheduled for deprecation. Now, there may be a valid argument for keeping versions of some functions around which take a naked number instead of a Duration, but I really think that we should lean towards using Durationl for that sort of thing and get rid of those that take naked numbers. It's less error-prone and would increase the consistency of how times are handled in druntime and Phobos. - Jonathan M Davis
May 14 2011
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/14/11 6:35 PM, Michel Fortin wrote:
 On 2011-05-14 13:04:54 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> said:

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.
Shouldn't "everyMs" and "afterMs" accept any of core.time's duration types instead of being fixed in milliseconds?
Great idea. Then we can actually overload every() and after(). Thanks, Andrei
May 14 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-14 10:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]
 
 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.
 
 Documentation:
 
 http://d-programming-language.org/phobos-prerelease/std_log.html
 
 Source:
 
 https://github.com/andralex/phobos
 
 Feedback welcome.
A minor note on efficiency. You're currently calling hour, minute, second, etc. on the result of Clock.currTime() (which is a SysTime) and doing so in a loop. Every one of those calls has to convert the internal representation in hnsecs to the units your asking for. It would be more efficient to take the result of Clock.currTime() and then save a DateTime and FracSec with the values from that SysTime. For example, instead of auto t = Clock.currTime(); ... formattedWrite(writer, prefix, level, t.month, t.day, t.hour, t.minute, t.second, t.fracSec.usecs, tid, fdir, fname, n); you could do auto t = Clock.currTime(); auto dt = cast(DateTime)t; auto fs = t.fracSec; ... formattedWrite(writer, prefix, level, dt.month, dt.day, dt.hour, dt.minute, dt.second, fs.fracSec.usecs, tid, fdir, fname, n); It's not a big deal. SysTime has all of the functions on it, and it works the way that you're doing it. It's just less efficienty since it has to do more calculations, whereas if you get a DateTime and FracSec from it, there are far fewer calcuations to do. Actually, I should probably add a note about that to SysTime's documentation. It should be fairly obvious if you sit down and think about it, but obviously people aren't usually going to be doing that, so it's likely unreasonable to expect people to figure that out on their own short actually needing to find ways to improve the efficiency of their code date- time. In any case, I just thought that I'd point that out. I'm not sure if it will really have much of an effect (especially when I/O is going to be the bottlneck for logging, not stray date-time calculations), but logging does need to be efficient. - Jonathan M Davis
May 14 2011
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-14 19:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
Why does the user have to manually initialize the library? Why not use a static constructor or lazy initialization? Actually I don't like it at all, that the logging library is configured via command line options. Seems very odd to me in the first place. That is something that should be handled by the application that uses std.log not the library itself. The library should be configurable via regular methods, like "log.verbose = true". You could provide a shortcut that configures the library via the command line but that should be optional and not the default. -- /Jacob Carlborg
May 15 2011
next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 15/05/2011 16:15, Jacob Carlborg wrote:
 On 2011-05-14 19:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
Why does the user have to manually initialize the library? Why not use a static constructor or lazy initialization? Actually I don't like it at all, that the logging library is configured via command line options. Seems very odd to me in the first place. That is something that should be handled by the application that uses std.log not the library itself. The library should be configurable via regular methods, like "log.verbose = true". You could provide a shortcut that configures the library via the command line but that should be optional and not the default.
Agreed. -- Robert http://octarineparrot.com/
May 15 2011
prev sibling parent reply "Lars T. Kyllingstad" <public kyllingen.NOSPAMnet> writes:
On Sun, 15 May 2011 17:15:38 +0200, Jacob Carlborg wrote:

 On 2011-05-14 19:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote: [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
Why does the user have to manually initialize the library? Why not use a static constructor or lazy initialization? Actually I don't like it at all, that the logging library is configured via command line options. Seems very odd to me in the first place. That is something that should be handled by the application that uses std.log not the library itself. The library should be configurable via regular methods, like "log.verbose = true". You could provide a shortcut that configures the library via the command line but that should be optional and not the default.
I agree with this. -Lars
May 22 2011
parent so <so so.so> writes:
On Sun, 22 May 2011 21:38:26 +0300, Lars T. Kyllingstad  
<public kyllingen.nospamnet> wrote:

 On Sun, 15 May 2011 17:15:38 +0200, Jacob Carlborg wrote:

 Why does the user have to manually initialize the library? Why not use a
 static constructor or lazy initialization?

 Actually I don't like it at all, that  the logging library is configured
 via command line options. Seems very odd to me in the first place. That
 is something that should be handled by the application that uses std.log
 not the library itself. The library should be configurable via regular
 methods, like "log.verbose = true". You could provide a shortcut that
 configures the library via the command line but that should be optional
 and not the default.
I agree with this. -Lars
I overall like the library, thanks for the work! Just a question, not only about std.log but upcoming projects as well. Is adopting to a library standard which was originally designed for another language any good? I think the library designers are influenced mostly by the capabilities of a language.
May 22 2011
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-14 19:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
How about an API that looks something like this: http://pastebin.com/dLVp1GRr This API contains standard interfaces for a logger and a logging level. It contains a default logger implementation and a couple of logging levels. This API also allows you to implement custom loggers and custom logging levels. Multiple logger instances are possible with options set on each instance. Note this is just a suggestion for the API and doesn't contain any real implementation (just prints to stdout). -- /Jacob Carlborg
May 15 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/15/2011 02:54 PM, Jacob Carlborg wrote:
 On 2011-05-14 19:04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.


 Thanks,

 Andrei
How about an API that looks something like this: http://pastebin.com/dLVp1GRr This API contains standard interfaces for a logger and a logging level. It contains a default logger implementation and a couple of logging levels. This API also allows you to implement custom loggers and custom logging levels. Multiple logger instances are possible with options set on each instance. Note this is just a suggestion for the API and doesn't contain any real implementation (just prints to stdout).
Thanks for your work. I think there's an important distinction to be made. There are two "API"s being discussed. One is the client interface and the other is the extensibility interface. Jose looked into both: he provided a client interface that has formatting, levels, enabling, and such, and an extensibility interface that essentially is a simple output stream. My library explores the client interface and leaves the extensibility interface as an obvious piece of work that needs little agreement and minimal design effort. Finally, your library keeps the client interface to a minimum and focuses almost exclusively on the extensibility interface. In doing so, it makes few choices that I disagree with. Allow me to share some specific feedback. 1. It "becomes dynamic" too early. First, in order to disable logging during compilation, a barrier of aliased types is needed. The alias would choose either a "null type" that does nothing (see StaticNullLogger at https://github.com/andralex/phobos/blob/master/std/log.d), or a log that actually does something. I think your design can be adjusted to do that with relative ease. 2. It "becomes dynamic" too early from a different perspective. The interface for extensibility is identical with the interface for use and as a consequence leaves too broad functionality unimplemented. A better design is to handle a bunch of decisions (is the log dynamically enabled? every N calls? every N seconds? before N seconds have passed? after N seconds have passed?) in a lightweight front end, i.e. _before_ arguments have been evaluated (this is crucial!). Also, the front end should take care of formatting minutiae, leaving the dynamic back-end the simple task of streaming text where it's supposed to be going. I think Jose's design did the right thing there by doing enabled checks and formatting in the front-end, leaving only transport to the back-end. 3. Another consequence is that extensibility points have the signature: Logger log(string file, long line, ...); which leaves the heavyweight formatting task to the antiquated "..." interface (no static types left, meaning e.g. no structs defining toString can be logged). Even assuming that's not a problem, implementors of this function are left with a fair amount of work to do. 4. The Logger class contains info, warning, and error Level objects. Each Level object in turn contains a reference to a Logger. This design leaves some odd shrapnel behind, e.g. one can get to the critical log from the info log. 5. I've seen the notion of a default logging level elsewhere but I think it's inadequate for the info/warning/error/critical/fatal approach. It is adequate for verbosity levels, i.e. vlog and friends. For info/warning/etc. the decision of the appropriate level belongs to the caller. 6. My initial design also contained a global "log battery" containing the info, warning, etc. objects as members. I found that design stilted because it provides absolutely no benefit besides a marginal "log.info" vs. "logInfo", has no encapsulation advantage, is adverse to extensibility, and worse of all perpetuates poor object oriented design. It's best to call a spade a spade, so there should be five global objects because that's in keep with reality. Andrei
May 15 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-16 02:05, Andrei Alexandrescu wrote:
 Thanks for your work.

 I think there's an important distinction to be made. There are two
 "API"s being discussed. One is the client interface and the other is the
 extensibility interface.

 Jose looked into both: he provided a client interface that has
 formatting, levels, enabling, and such, and an extensibility interface
 that essentially is a simple output stream.

 My library explores the client interface and leaves the extensibility
 interface as an obvious piece of work that needs little agreement and
 minimal design effort.

 Finally, your library keeps the client interface to a minimum and
 focuses almost exclusively on the extensibility interface. In doing so,
 it makes few choices that I disagree with. Allow me to share some
 specific feedback.
Note that my suggestion was just a simple and incomplete suggestion on how the API could look like. I only provided "info", "warning" and "error" methods as examples, I'm not saying the API should only have these three levels.
 1. It "becomes dynamic" too early. First, in order to disable logging
 during compilation, a barrier of aliased types is needed. The alias
 would choose either a "null type" that does nothing (see
 StaticNullLogger at
 https://github.com/andralex/phobos/blob/master/std/log.d), or a log that
 actually does something. I think your design can be adjusted to do that
 with relative ease.
I didn't consider disabling logging during compilation at all. If people like the basic idea with my API then, of course, I would flesh it out and add support compile time disabling of the logging.
 2. It "becomes dynamic" too early from a different perspective. The
 interface for extensibility is identical with the interface for use and
 as a consequence leaves too broad functionality unimplemented. A better
 design is to handle a bunch of decisions (is the log dynamically
 enabled? every N calls? every N seconds? before N seconds have passed?
 after N seconds have passed?) in a lightweight front end, i.e. _before_
 arguments have been evaluated (this is crucial!). Also, the front end
 should take care of formatting minutiae, leaving the dynamic back-end
 the simple task of streaming text where it's supposed to be going. I
 think Jose's design did the right thing there by doing enabled checks
 and formatting in the front-end, leaving only transport to the back-end.

 3. Another consequence is that extensibility points have the signature:

 Logger log(string file, long line, ...);

 which leaves the heavyweight formatting task to the antiquated "..."
 interface (no static types left, meaning e.g. no structs defining
 toString can be logged). Even assuming that's not a problem,
 implementors of this function are left with a fair amount of work to do.
The problem with variadic template methods are that they're not virtual.
 4. The Logger class contains info, warning, and error Level objects.
 Each Level object in turn contains a reference to a Logger. This design
 leaves some odd shrapnel behind, e.g. one can get to the critical log
 from the info log.
I thought it was a good idea that you could chain calls like this: log.info("foo").error("bar");
 5. I've seen the notion of a default logging level elsewhere but I think
 it's inadequate for the info/warning/error/critical/fatal approach. It
 is adequate for verbosity levels, i.e. vlog and friends. For
 info/warning/etc. the decision of the appropriate level belongs to the
 caller.
Ok. Just a note, nobody is forcing you to use the default logging level.
 6. My initial design also contained a global "log battery" containing
 the info, warning, etc. objects as members. I found that design stilted
 because it provides absolutely no benefit besides a marginal "log.info"
 vs. "logInfo", has no encapsulation advantage, is adverse to
 extensibility, and worse of all perpetuates poor object oriented design.
 It's best to call a spade a spade, so there should be five global
 objects because that's in keep with reality.


 Andrei
I got the impression that you change "log.info" to "logInfo" just because you wanted user defined loggers to look the same. My suggestion shows that's not necessary. Also I tried to minimize the use of global variables. -- /Jacob Carlborg
May 17 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/17/11 4:02 AM, Jacob Carlborg wrote:
 On 2011-05-16 02:05, Andrei Alexandrescu wrote:
 Thanks for your work.

 I think there's an important distinction to be made. There are two
 "API"s being discussed. One is the client interface and the other is the
 extensibility interface.

 Jose looked into both: he provided a client interface that has
 formatting, levels, enabling, and such, and an extensibility interface
 that essentially is a simple output stream.

 My library explores the client interface and leaves the extensibility
 interface as an obvious piece of work that needs little agreement and
 minimal design effort.

 Finally, your library keeps the client interface to a minimum and
 focuses almost exclusively on the extensibility interface. In doing so,
 it makes few choices that I disagree with. Allow me to share some
 specific feedback.
Note that my suggestion was just a simple and incomplete suggestion on how the API could look like. I only provided "info", "warning" and "error" methods as examples, I'm not saying the API should only have these three levels.
[snip] I thought about this some more and I understand I sounded unfair. There is a lot of merit and there are a lot of good ideas in your code (and of course Jose's), which I didn't mention for the simple but cold reason that negative feedback is more informative. But neglecting the merits is a mistake as well. I'll incorporate some of the ideas you suggested in the next pass through std.log. Thanks, Andrei
May 17 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-17 22:15, Andrei Alexandrescu wrote:
 On 5/17/11 4:02 AM, Jacob Carlborg wrote:
 On 2011-05-16 02:05, Andrei Alexandrescu wrote:
 Thanks for your work.

 I think there's an important distinction to be made. There are two
 "API"s being discussed. One is the client interface and the other is the
 extensibility interface.

 Jose looked into both: he provided a client interface that has
 formatting, levels, enabling, and such, and an extensibility interface
 that essentially is a simple output stream.

 My library explores the client interface and leaves the extensibility
 interface as an obvious piece of work that needs little agreement and
 minimal design effort.

 Finally, your library keeps the client interface to a minimum and
 focuses almost exclusively on the extensibility interface. In doing so,
 it makes few choices that I disagree with. Allow me to share some
 specific feedback.
Note that my suggestion was just a simple and incomplete suggestion on how the API could look like. I only provided "info", "warning" and "error" methods as examples, I'm not saying the API should only have these three levels.
[snip] I thought about this some more and I understand I sounded unfair. There is a lot of merit and there are a lot of good ideas in your code (and of course Jose's), which I didn't mention for the simple but cold reason that negative feedback is more informative. But neglecting the merits is a mistake as well. I'll incorporate some of the ideas you suggested in the next pass through std.log. Thanks, Andrei
No hard feelings, I also have a tendency to just give negative feedback. -- /Jacob Carlborg
May 18 2011
next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
std.logging is still alive! After posting my first attempt at a
logging module I went back and spent a lot of time on how I could
improve the API. I would like to say that Andrei's std.log module had
a great influence on the final outcome. There are some aspect of
std.log's API that I really like. E.g. the ability to do fine grain
compile time configuration. I'll go into detail in a subsequent review
of std.log.

I also think that having competing logging module is a good thing.
This process will result in a better module for phobos and as a result
a better module for the user.

The best way to see what has changed is to look at the source code
(https://github.com/jsancio/phobos/blob/master/std/logging.d) and the
generated doc (http://jsancio.github.com/phobos/phobos/std_logging.html).
Here are some highlights:

1) I tried to minimize the amount of code the compiler has to generate
because of template. Template are only used when the module has/wants
to make compiled time decision. If you spot places where templates are
not needed please tell me.

2) Make logging decision as early as possible. Logging can be short
circuited by either the severity level, the verbose level or an user
defined condition. All those conditions are evaluated as soon as
possible and only when required. E.g. the module doesn't evaluate user
define condition if it already knows that it wont log because of the
severity.

3) A module should do one thing an do it well. This module does
logging so unlike std.log and glog it doesn't have built in mechanism
for doing 'every', 'when', 'first', etc. Instead the log and vlog
function provide a lazily evaluated bool parameter that the user can
use to perform condition logging. There are plenty of example of this
in the doc.

At the top of the doc I provided an example similar to std.log's
synopsis so you can compare the two APIs.

Disclaimer: This is a draft. Once we agree on the main API (log and
vlog). I will go back an finish the implementation, test and
documentation.

Enjoy! Let me know if you have any suggestions,
-Jose

On Wed, May 18, 2011 at 6:05 AM, Jacob Carlborg <doob me.com> wrote:
 On 2011-05-17 22:15, Andrei Alexandrescu wrote:
 On 5/17/11 4:02 AM, Jacob Carlborg wrote:
 On 2011-05-16 02:05, Andrei Alexandrescu wrote:
 Thanks for your work.

 I think there's an important distinction to be made. There are two
 "API"s being discussed. One is the client interface and the other is the
 extensibility interface.

 Jose looked into both: he provided a client interface that has
 formatting, levels, enabling, and such, and an extensibility interface
 that essentially is a simple output stream.

 My library explores the client interface and leaves the extensibility
 interface as an obvious piece of work that needs little agreement and
 minimal design effort.

 Finally, your library keeps the client interface to a minimum and
 focuses almost exclusively on the extensibility interface. In doing so,
 it makes few choices that I disagree with. Allow me to share some
 specific feedback.
Note that my suggestion was just a simple and incomplete suggestion on how the API could look like. I only provided "info", "warning" and "error" methods as examples, I'm not saying the API should only have these three levels.
[snip] I thought about this some more and I understand I sounded unfair. There is a lot of merit and there are a lot of good ideas in your code (and of course Jose's), which I didn't mention for the simple but cold reason that negative feedback is more informative. But neglecting the merits is a mistake as well. I'll incorporate some of the ideas you suggested in the next pass through std.log. Thanks, Andrei
No hard feelings, I also have a tendency to just give negative feedback. -- /Jacob Carlborg
May 18 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/18/11 8:00 AM, Jose Armando Garcia wrote:
 I also think that having competing logging module is a good thing.
 This process will result in a better module for phobos and as a result
 a better module for the user.
Clearly there are advantages to competing proposals, but I have mixed feelings about the whole thing, with the negative probably being stronger than the positive. At the end of the day one of us will have their work go to waste. Generally nobody wants their work to go to waste, and in particular I think I'd harm the community's interests by working on redundant stuff when so many other things are in need of attention. The reason I started std.log was out of desperation that everybody wanted to talk about it instead of working on it, and because I figured nobody would implement it the way I thought it needs to be done anyway. That's why I wrote on Apr 21st:
 Again, I'd _much_ rather prefer if someone just implemented this:

 http://google-glog.googlecode.com/svn/trunk/doc/glog.html

 It's simple, to the point, and brings the bacon home.

 In fact I'm putting dibs on this. I'll implement the thing and make a
 proposal.
That message was meant to prevent exactly what's happening now. Honestly it hurts me that of all things possible, a new and talented contributor (two, to count Jacob's effort on his prototype) chose to work squarely on this one artifact. Right now the two APIs are converging and start differing in minor details, which makes it painfully obvious that at the end of the day two people are working in separation on virtually identical code. I can't afford this. I am ceasing work on std.log (feel free to copy from my code) and I encourage you to work towards a formal proposal. In doing that, I'll be upfront in saying that I'll very strongly advocate staying close to the client interface of std.log as it is now. In particular, every departure from glog (to which both designs now owe a lot) for equivalent functionality is gratuitous unless thoroughly justified. In detail: * initializeLogging(SharedLogger.getCreator(args[0])); adds too much cognitive load, literally at line one. Now I need to know what a shared logger is and what a creator is. Just pass the entire command line and let the log subsystem pick its parameters. Don't use a delegate unless you can't do without. If client code wants to do configuration work, give them functions, don't ask them for a callback. The callback complicates things for no reason. * The name initializeLogging is a gratuitous departure from glog. Use initLogging. * Keep the glog flags as they are. In all likelihood any user of glog would want to define such flags, so we may as well spare them the work. * Pick the logging directory like glog does. * Add programmatic setting of flag names and values before calling initLogging. I think that's a good idea that doesn't depart from glog's design (google cmdline parser uses global names a la FLAGS_xxx). That would allow users to change a flag's name or disable it entirely (by assigning null to them). Assigning to a flag's value prior to calling initLogging would change its default. Assigning to a flag's value after initLogging forces the flag. To simply prevent log to get to any flags, client can call initLogging(args[0 .. 1]). * The obvious action to do with a log is to write to it. I don't want to write: log!info.write(stuff); I want to write: logInfo(stuff); or, fine, log!info(stuff); * The names LOGGING_FATAL_DISABLED etc. are gratuitous departures from glog. Do what glog does adapted to D's naming convention, hence strip_log_xxx. * I don't want to write log!info(args.length > 1).write("Arguments: ", args[1 .. $]); Putting the condition there makes no sense without the manual. I want to write logInfo.when(args.length > 1)("Arguments: ", args[1 .. $]); or log!info.when(args.length > 1)("Arguments: ", args[1 .. $]); which omits the obvious "write" but adds the non-obvious "when". * Factoring out every, first, etc. is an interesting idea but I found no use for it outside logging. (That doesn't mean there isn't any, it just means we should think of it because cool things may happen.) That shouldn't harm except when combined with the point above we're forced to: logInfo.when(every(1000))("text"); which is self-explanatory but rather verbose. In all honesty log!info(every(9)).write("Every nine"); isn't that easy on the eyes either. * Define "after" in addition to "every" and "first", and overload them all for core.Duration. It's rather simple, for example for "every" you'd have something like: static ulong lastTimeInHnsecs; immutable ulong now = Clock.currTime.stdTime; if (dur!"hnsecs"(now - lastTimeInHnsecs) < d) { return nullLogger; // no logging this time } lastTimeInHnsecs = now; return this; // will log * I peeked at the implementation and you allocate one new string for each logged message. You must keep a buffer in thread-local store and reuse it with each call. * The way I see a nice implementation would be (inspired from Jens' work) via a class that defines the client-level methods as final, and has 2-3 extension methods that do the work. That way there's no need for awkward extra names (Logged/Logger, ouch) - one class encapsulates them all. * Call your proposal std.log :o). Thanks, Andrei
May 18 2011
next sibling parent reply Jens Mueller <jens.k.mueller gmx.de> writes:
Andrei Alexandrescu wrote:
 On 5/18/11 8:00 AM, Jose Armando Garcia wrote:
I also think that having competing logging module is a good thing.
This process will result in a better module for phobos and as a result
a better module for the user.
Clearly there are advantages to competing proposals, but I have mixed feelings about the whole thing, with the negative probably being stronger than the positive. At the end of the day one of us will have their work go to waste. Generally nobody wants their work to go to waste, and in particular I think I'd harm the community's interests by working on redundant stuff when so many other things are in need of attention. The reason I started std.log was out of desperation that everybody wanted to talk about it instead of working on it, and because I figured nobody would implement it the way I thought it needs to be done anyway. That's why I wrote on Apr 21st:
Again, I'd _much_ rather prefer if someone just implemented this:

http://google-glog.googlecode.com/svn/trunk/doc/glog.html

It's simple, to the point, and brings the bacon home.

In fact I'm putting dibs on this. I'll implement the thing and make a
proposal.
That message was meant to prevent exactly what's happening now. Honestly it hurts me that of all things possible, a new and talented contributor (two, to count Jacob's effort on his prototype) chose to work squarely on this one artifact. Right now the two APIs are converging and start differing in minor details, which makes it painfully obvious that at the end of the day two people are working in separation on virtually identical code. I can't afford this. I am ceasing work on std.log (feel free to copy from my code) and I encourage you to work towards a formal proposal. In doing that, I'll be upfront in saying that I'll very strongly advocate staying close to the client interface of std.log as it is now. In particular, every departure from glog (to which both designs now owe a lot) for equivalent functionality is gratuitous unless thoroughly justified.
Yeah. If two proposals converge to one it makes no sense anymore. But I believe your proposal made std.log go into the very right direction. Sometimes it just better to have two proposals in very beginning to see what approach is better. But now there is no need for two proposals. Jose is heading in a better direction thanks to your proposal.
 In detail:
 
 * initializeLogging(SharedLogger.getCreator(args[0])); adds too much
 cognitive load, literally at line one. Now I need to know what a
 shared logger is and what a creator is. Just pass the entire command
 line and let the log subsystem pick its parameters. Don't use a
 delegate unless you can't do without. If client code wants to do
 configuration work, give them functions, don't ask them for a
 callback. The callback complicates things for no reason.
I don't like it, too. It's too complicated. Meaning some people won't use it. It needs to be simple.
 * The name initializeLogging is a gratuitous departure from glog.
 Use initLogging.
 
 * Keep the glog flags as they are. In all likelihood any user of
 glog would want to define such flags, so we may as well spare them
 the work.
 
 * Pick the logging directory like glog does.
 
 * Add programmatic setting of flag names and values before calling
 initLogging. I think that's a good idea that doesn't depart from
 glog's design (google cmdline parser uses global names a la
 FLAGS_xxx). That would allow users to change a flag's name or
 disable it entirely (by assigning null to them). Assigning to a
 flag's value prior to calling initLogging would change its default.
 Assigning to a flag's value after initLogging forces the flag. To
 simply prevent log to get to any flags, client can call
 initLogging(args[0 .. 1]).
Seems useful.
 * The obvious action to do with a log is to write to it. I don't
 want to write:
 
 log!info.write(stuff);
 
 I want to write:
 
 logInfo(stuff);
 
 or, fine,
 
 log!info(stuff);
Agree. Saying write should be needless.
 * The names LOGGING_FATAL_DISABLED etc. are gratuitous departures
 from glog. Do what glog does adapted to D's naming convention, hence
 strip_log_xxx.
 
 * I don't want to write
 
 log!info(args.length > 1).write("Arguments: ", args[1 .. $]);
 
 Putting the condition there makes no sense without the manual. I
 want to write
 
 logInfo.when(args.length > 1)("Arguments: ", args[1 .. $]);
 
 or
 
 log!info.when(args.length > 1)("Arguments: ", args[1 .. $]);
 
 which omits the obvious "write" but adds the non-obvious "when".
So your point is than when should be explicit because it's not obvious. Seems right to me. Because if something gets more space (here saying "when") it will get more attention. I think as was already said having the condition also in the log file should be helpful. We should try to have it in the log file.
 * Factoring out every, first, etc. is an interesting idea but I
 found no use for it outside logging. (That doesn't mean there isn't
 any, it just means we should think of it because cool things may
 happen.) That shouldn't harm except when combined with the point
 above we're forced to:
 
 logInfo.when(every(1000))("text");
 
 which is self-explanatory but rather verbose. In all honesty
 log!info(every(9)).write("Every nine"); isn't that easy on the eyes
 either.
I believe stand-alone every etc. are really interesting. logInfo.when(every(1000) && myVar > 1)("text"); and logInfo.when(myVar > 1 && every(1000))("text"); vs. logInfo.every(1000).when(myVar > 1)("text"); and logInfo.when(myVar > 1).every(1000)("text"); I don't know yet which is easier to read. The first on gives me the condition in one view whereas with the second one have to scan the whole line. The stand-alone version allow writing unforeseen condition which is good in regard to flexibility. I believe one should add when/every/after etc. as non-stand-alone to ease a simple interface but also provide the non-stand-alone versions to allow composing more advanced conditions. But this depends on how useful such composing is in practice.
 * Define "after" in addition to "every" and "first", and overload
 them all for core.Duration. It's rather simple, for example for
 "every" you'd have something like:
 
   static ulong lastTimeInHnsecs;
   immutable ulong now = Clock.currTime.stdTime;
   if (dur!"hnsecs"(now - lastTimeInHnsecs) < d)
   {
     return nullLogger; // no logging this time
   }
   lastTimeInHnsecs = now;
   return this; // will log

 * I peeked at the implementation and you allocate one new string for
 each logged message. You must keep a buffer in thread-local store
 and reuse it with each call.
 
 * The way I see a nice implementation would be (inspired from Jens'
 work) via a class that defines the client-level methods as final,
 and has 2-3 extension methods that do the work. That way there's no
 need for awkward extra names (Logged/Logger, ouch) - one class
 encapsulates them all.
I'm puzzled. I haven't done any work in that regard. Maybe you mean a different Jens. My inspiration (if existent) was little.
 * Call your proposal std.log :o).
Jose what do you think? I believe it's not far to go from your and Andrei's work to a formal review. Jens
May 19 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/19/11 2:56 AM, Jens Mueller wrote:
 Andrei Alexandrescu wrote:
 * The way I see a nice implementation would be (inspired from Jens'
 work) via a class that defines the client-level methods as final,
 and has 2-3 extension methods that do the work. That way there's no
 need for awkward extra names (Logged/Logger, ouch) - one class
 encapsulates them all.
I'm puzzled. I haven't done any work in that regard. Maybe you mean a different Jens. My inspiration (if existent) was little.
It was Jacob. Apologies to both. Andrei
May 19 2011
prev sibling next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
Just wanted to let everyone know that I am working on having a review
wordy std.log. I am almost done with the implementation. I am
currently working on improving the documentation. Is there a link that
describes the review process. I would like to get std.log as close to
final to minimize the back and forth.

Also, I will reply to the rest of Andrei's email and Jens's email when
we have something to look at (the code and doc in github).

Thanks,
-Jose

On Wed, May 18, 2011 at 1:09 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 5/18/11 8:00 AM, Jose Armando Garcia wrote:
 I also think that having competing logging module is a good thing.
 This process will result in a better module for phobos and as a result
 a better module for the user.
Clearly there are advantages to competing proposals, but I have mixed feelings about the whole thing, with the negative probably being stronger than the positive. At the end of the day one of us will have their work go to waste. General=
ly
 nobody wants their work to go to waste, and in particular I think I'd har=
m
 the community's interests by working on redundant stuff when so many othe=
r
 things are in need of attention. The reason I started std.log was out of
 desperation that everybody wanted to talk about it instead of working on =
it,
 and because I figured nobody would implement it the way I thought it need=
s
 to be done anyway. That's why I wrote on Apr 21st:

 Again, I'd _much_ rather prefer if someone just implemented this:

 http://google-glog.googlecode.com/svn/trunk/doc/glog.html

 It's simple, to the point, and brings the bacon home.

 In fact I'm putting dibs on this. I'll implement the thing and make a
 proposal.
That message was meant to prevent exactly what's happening now. Honestly =
it
 hurts me that of all things possible, a new and talented contributor (two=
,
 to count Jacob's effort on his prototype) chose to work squarely on this =
one
 artifact.

 Right now the two APIs are converging and start differing in minor detail=
s,
 which makes it painfully obvious that at the end of the day two people ar=
e
 working in separation on virtually identical code. I can't afford this.

 I am ceasing work on std.log (feel free to copy from my code) and I
 encourage you to work towards a formal proposal. In doing that, I'll be
 upfront in saying that I'll very strongly advocate staying close to the
 client interface of std.log as it is now. In particular, every departure
 from glog (to which both designs now owe a lot) for equivalent functional=
ity
 is gratuitous unless thoroughly justified. In detail:

 * initializeLogging(SharedLogger.getCreator(args[0])); adds too much
 cognitive load, literally at line one. Now I need to know what a shared
 logger is and what a creator is. Just pass the entire command line and le=
t
 the log subsystem pick its parameters. Don't use a delegate unless you ca=
n't
 do without. If client code wants to do configuration work, give them
 functions, don't ask them for a callback. The callback complicates things
 for no reason.

 * The name initializeLogging is a gratuitous departure from glog. Use
 initLogging.

 * Keep the glog flags as they are. In all likelihood any user of glog wou=
ld
 want to define such flags, so we may as well spare them the work.

 * Pick the logging directory like glog does.

 * Add programmatic setting of flag names and values before calling
 initLogging. I think that's a good idea that doesn't depart from glog's
 design (google cmdline parser uses global names a la FLAGS_xxx). That wou=
ld
 allow users to change a flag's name or disable it entirely (by assigning
 null to them). Assigning to a flag's value prior to calling initLogging
 would change its default. Assigning to a flag's value after initLogging
 forces the flag. To simply prevent log to get to any flags, client can ca=
ll
 initLogging(args[0 .. 1]).

 * The obvious action to do with a log is to write to it. I don't want to
 write:

 log!info.write(stuff);

 I want to write:

 logInfo(stuff);

 or, fine,

 log!info(stuff);

 * The names LOGGING_FATAL_DISABLED etc. are gratuitous departures from gl=
og.
 Do what glog does adapted to D's naming convention, hence strip_log_xxx.

 * I don't want to write

 log!info(args.length > 1).write("Arguments: ", args[1 .. $]);

 Putting the condition there makes no sense without the manual. I want to
 write

 logInfo.when(args.length > 1)("Arguments: ", args[1 .. $]);

 or

 log!info.when(args.length > 1)("Arguments: ", args[1 .. $]);

 which omits the obvious "write" but adds the non-obvious "when".

 * Factoring out every, first, etc. is an interesting idea but I found no =
use
 for it outside logging. (That doesn't mean there isn't any, it just means=
we
 should think of it because cool things may happen.) That shouldn't harm
 except when combined with the point above we're forced to:

 logInfo.when(every(1000))("text");

 which is self-explanatory but rather verbose. In all honesty
 log!info(every(9)).write("Every nine"); isn't that easy on the eyes eithe=
r.
 * Define "after" in addition to "every" and "first", and overload them al=
l
 for core.Duration. It's rather simple, for example for "every" you'd have
 something like:

 =A0static ulong lastTimeInHnsecs;
 =A0immutable ulong now =3D Clock.currTime.stdTime;
 =A0if (dur!"hnsecs"(now - lastTimeInHnsecs) < d)
 =A0{
 =A0 =A0return nullLogger; // no logging this time
 =A0}
 =A0lastTimeInHnsecs =3D now;
 =A0return this; // will log

 * I peeked at the implementation and you allocate one new string for each
 logged message. You must keep a buffer in thread-local store and reuse it
 with each call.

 * The way I see a nice implementation would be (inspired from Jens' work)
 via a class that defines the client-level methods as final, and has 2-3
 extension methods that do the work. That way there's no need for awkward
 extra names (Logged/Logger, ouch) - one class encapsulates them all.

 * Call your proposal std.log :o).


 Thanks,

 Andrei
May 24 2011
parent Johannes Pfau <spam example.com> writes:
Jose Armando Garcia wrote:
Just wanted to let everyone know that I am working on having a review
wordy std.log. I am almost done with the implementation. I am
currently working on improving the documentation. Is there a link that
describes the review process. I would like to get std.log as close to
final to minimize the back and forth.

Also, I will reply to the rest of Andrei's email and Jens's email when
we have something to look at (the code and doc in github).

Thanks,
-Jose
I think the review process is meant to be similar to the boost review process, Andrei posted this link a few times: http://www.boost.org/community/reviews.html -- Johannes Pfau
May 24 2011
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
The implementation and documentation for std.log is ready for viewing.
You can take a look at the doc at
http://jsancio.github.com/phobos/phobos/std_log.html. The source code
is at https://github.com/jsancio/phobos/blob/master/std/log.d.

I had to make some changes to druntime to get the thread id for
printing. The module will work without the changes but you wont to see
thread ids in your log messages. You can apply the attached patch to
your druntime if you want to see thread id in the log.

Some comments below.

Let me know if you have any comments or suggestions! Thanks,
-Jose

On Wed, May 18, 2011 at 1:09 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 5/18/11 8:00 AM, Jose Armando Garcia wrote:
 I also think that having competing logging module is a good thing.
 This process will result in a better module for phobos and as a result
 a better module for the user.
Clearly there are advantages to competing proposals, but I have mixed feelings about the whole thing, with the negative probably being stronger than the positive. At the end of the day one of us will have their work go to waste. General=
ly
 nobody wants their work to go to waste, and in particular I think I'd har=
m
 the community's interests by working on redundant stuff when so many othe=
r
 things are in need of attention. The reason I started std.log was out of
 desperation that everybody wanted to talk about it instead of working on =
it,
 and because I figured nobody would implement it the way I thought it need=
s
 to be done anyway. That's why I wrote on Apr 21st:

 Again, I'd _much_ rather prefer if someone just implemented this:

 http://google-glog.googlecode.com/svn/trunk/doc/glog.html

 It's simple, to the point, and brings the bacon home.

 In fact I'm putting dibs on this. I'll implement the thing and make a
 proposal.
That message was meant to prevent exactly what's happening now. Honestly =
it
 hurts me that of all things possible, a new and talented contributor (two=
,
 to count Jacob's effort on his prototype) chose to work squarely on this =
one
 artifact.

 Right now the two APIs are converging and start differing in minor detail=
s,
 which makes it painfully obvious that at the end of the day two people ar=
e
 working in separation on virtually identical code. I can't afford this.

 I am ceasing work on std.log (feel free to copy from my code) and I
 encourage you to work towards a formal proposal. In doing that, I'll be
 upfront in saying that I'll very strongly advocate staying close to the
 client interface of std.log as it is now. In particular, every departure
 from glog (to which both designs now owe a lot) for equivalent functional=
ity
 is gratuitous unless thoroughly justified. In detail:

 * initializeLogging(SharedLogger.getCreator(args[0])); adds too much
 cognitive load, literally at line one. Now I need to know what a shared
 logger is and what a creator is. Just pass the entire command line and le=
t
 the log subsystem pick its parameters. Don't use a delegate unless you ca=
n't
 do without. If client code wants to do configuration work, give them
 functions, don't ask them for a callback. The callback complicates things
 for no reason.
Done.
 * The name initializeLogging is a gratuitous departure from glog. Use
 initLogging.
Done.
 * Keep the glog flags as they are. In all likelihood any user of glog wou=
ld
 want to define such flags, so we may as well spare them the work.
Done.
 * Pick the logging directory like glog does.
Done.
 * Add programmatic setting of flag names and values before calling
 initLogging. I think that's a good idea that doesn't depart from glog's
 design (google cmdline parser uses global names a la FLAGS_xxx). That wou=
ld
 allow users to change a flag's name or disable it entirely (by assigning
 null to them). Assigning to a flag's value prior to calling initLogging
 would change its default. Assigning to a flag's value after initLogging
 forces the flag. To simply prevent log to get to any flags, client can ca=
ll
 initLogging(args[0 .. 1]).
Done. Given how std.log's command line parsing currently works the user can change an option's default but that easily changeable if we really want this.
 * The obvious action to do with a log is to write to it. I don't want to
 write:

 log!info.write(stuff);

 I want to write:

 logInfo(stuff);

 or, fine,

 log!info(stuff);
Done.
 * The names LOGGING_FATAL_DISABLED etc. are gratuitous departures from gl=
og.
 Do what glog does adapted to D's naming convention, hence strip_log_xxx.
Done.
 * I don't want to write

 log!info(args.length > 1).write("Arguments: ", args[1 .. $]);

 Putting the condition there makes no sense without the manual. I want to
 write

 logInfo.when(args.length > 1)("Arguments: ", args[1 .. $]);

 or

 log!info.when(args.length > 1)("Arguments: ", args[1 .. $]);

 which omits the obvious "write" but adds the non-obvious "when".
Done.
 * Factoring out every, first, etc. is an interesting idea but I found no =
use
 for it outside logging. (That doesn't mean there isn't any, it just means=
we
 should think of it because cool things may happen.) That shouldn't harm
 except when combined with the point above we're forced to:

 logInfo.when(every(1000))("text");

 which is self-explanatory but rather verbose. In all honesty
 log!info(every(9)).write("Every nine"); isn't that easy on the eyes eithe=
r.

I went with factoring out every, first, etc because I found it to be a
cleaner design and easier to test. We can discuss this further if we
want to make it an integral part of the library.

 * Define "after" in addition to "every" and "first", and overload them al=
l
 for core.Duration. It's rather simple, for example for "every" you'd have
 something like:

 =A0static ulong lastTimeInHnsecs;
 =A0immutable ulong now =3D Clock.currTime.stdTime;
 =A0if (dur!"hnsecs"(now - lastTimeInHnsecs) < d)
 =A0{
 =A0 =A0return nullLogger; // no logging this time
 =A0}
 =A0lastTimeInHnsecs =3D now;
 =A0return this; // will log
Done. When implementing this I noticed that total!"hnsecs" performed some unnecessary computations. I should use your code (to use dur!"hnsecs") instead. I'll see if that code path is smarter.
 * I peeked at the implementation and you allocate one new string for each
 logged message. You must keep a buffer in thread-local store and reuse it
 with each call.
Done.
 * The way I see a nice implementation would be (inspired from Jens' work)
 via a class that defines the client-level methods as final, and has 2-3
 extension methods that do the work. That way there's no need for awkward
 extra names (Logged/Logger, ouch) - one class encapsulates them all.
I fixed the Logged/Logger problem in the design but I still didn't use class. Didn't see the need to use polymorphism but I could be wrong...
 * Call your proposal std.log :o).
Done.
 Thanks,

 Andrei
May 28 2011
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Clever use of __FILE__ and __LINE__ to create unique instantiations of
the every() template. :)
May 28 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 28.05.2011 20:08, schrieb Andrej Mitrovic:
 Clever use of __FILE__ and __LINE__ to create unique instantiations of
 the every() template. :)
does this belong in this thread? furthermore __FILE__ and __LINE__ isn't enough for every(...) ; every(...);
May 28 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/28/11, Daniel Gibson <metalcaedes gmail.com> wrote:
 Am 28.05.2011 20:08, schrieb Andrej Mitrovic:
 Clever use of __FILE__ and __LINE__ to create unique instantiations of
 the every() template. :)
does this belong in this thread?
I was just commenting the implementation.
May 28 2011
parent Daniel Gibson <metalcaedes gmail.com> writes:
Am 28.05.2011 20:19, schrieb Andrej Mitrovic:
 On 5/28/11, Daniel Gibson<metalcaedes gmail.com>  wrote:
 Am 28.05.2011 20:08, schrieb Andrej Mitrovic:
 Clever use of __FILE__ and __LINE__ to create unique instantiations of
 the every() template. :)
does this belong in this thread?
I was just commenting the implementation.
Ah ok. I just remembered every from another thread (where using __LINE__ and __FILE__ was discussed) :)
May 28 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-28 10:30, Jose Armando Garcia wrote:
 The implementation and documentation for std.log is ready for viewing.
 You can take a look at the doc at
 http://jsancio.github.com/phobos/phobos/std_log.html. The source code
 is at https://github.com/jsancio/phobos/blob/master/std/log.d.
 
 I had to make some changes to druntime to get the thread id for
 printing. The module will work without the changes but you wont to see
 thread ids in your log messages. You can apply the attached patch to
 your druntime if you want to see thread id in the log.
 
 Some comments below.
 
 Let me know if you have any comments or suggestions! Thanks,
 -Jose
I'd suggest starting a new thread on it or it's likely that a lot of people will miss this. - Jonathan M Davis
May 28 2011
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
This is a review of std.log. Overall, I really like the API exposed by
this module because it allows efficient compile time and run time
configuration. I have limited the review to the API and how the API
affects the implementation. I will review the implementation once the
API is close to final.

1) I think this was pointed out before. I don't really like that the
module can only be configure through the command line by passing the
list of command line arguments. The user should be able to configure
the module programmatically.

2) Not a fan of the top level symbols logInfo, logFatal, etc but it is
not a big deal.

3) opCall and format used template arguments for file and line yet
they are never used at compile time. This leads to unnecessary
template instantiations.

4) I know that when() and every() are really cool features but should
they be first class citizens in a logging module? What if the user
wants 'whenTheMoonIsFull(country)'? Including as part of the module
could be better argued if std.log generates special messages for them
which is what I think glog does. I have been thinking of ways of doing
this in std.logging. E.g. 'logInfo.every(2)("Message")' would generate
the following log line "... 2nd call ... Message."

5) General thought that applies to both std.log and std.logging: It
would be interesting to allow some configuration after initialization.
For example it would be unreasonable to allow configuration of things
that were already externalized like the name of the log file. But
maybe the user should be able to change the severity level and vlog
configuration.

Overall it looks good. As I said before I have a lot of comments on
the implementation but will hold them until we have a final API.

Thanks,
-Jose

On Wed, May 18, 2011 at 10:00 AM, Jose Armando Garcia <jsancio gmail.com> wrote:
 std.logging is still alive! After posting my first attempt at a
 logging module I went back and spent a lot of time on how I could
 improve the API. I would like to say that Andrei's std.log module had
 a great influence on the final outcome. There are some aspect of
 std.log's API that I really like. E.g. the ability to do fine grain
 compile time configuration. I'll go into detail in a subsequent review
 of std.log.

 I also think that having competing logging module is a good thing.
 This process will result in a better module for phobos and as a result
 a better module for the user.

 The best way to see what has changed is to look at the source code
 (https://github.com/jsancio/phobos/blob/master/std/logging.d) and the
 generated doc (http://jsancio.github.com/phobos/phobos/std_logging.html).
 Here are some highlights:

 1) I tried to minimize the amount of code the compiler has to generate
 because of template. Template are only used when the module has/wants
 to make compiled time decision. If you spot places where templates are
 not needed please tell me.

 2) Make logging decision as early as possible. Logging can be short
 circuited by either the severity level, the verbose level or an user
 defined condition. All those conditions are evaluated as soon as
 possible and only when required. E.g. the module doesn't evaluate user
 define condition if it already knows that it wont log because of the
 severity.

 3) A module should do one thing an do it well. This module does
 logging so unlike std.log and glog it doesn't have built in mechanism
 for doing 'every', 'when', 'first', etc. Instead the log and vlog
 function provide a lazily evaluated bool parameter that the user can
 use to perform condition logging. There are plenty of example of this
 in the doc.

 At the top of the doc I provided an example similar to std.log's
 synopsis so you can compare the two APIs.

 Disclaimer: This is a draft. Once we agree on the main API (log and
 vlog). I will go back an finish the implementation, test and
 documentation.

 Enjoy! Let me know if you have any suggestions,
 -Jose

 On Wed, May 18, 2011 at 6:05 AM, Jacob Carlborg <doob me.com> wrote:
 On 2011-05-17 22:15, Andrei Alexandrescu wrote:
 On 5/17/11 4:02 AM, Jacob Carlborg wrote:
 On 2011-05-16 02:05, Andrei Alexandrescu wrote:
 Thanks for your work.

 I think there's an important distinction to be made. There are two
 "API"s being discussed. One is the client interface and the other is the
 extensibility interface.

 Jose looked into both: he provided a client interface that has
 formatting, levels, enabling, and such, and an extensibility interface
 that essentially is a simple output stream.

 My library explores the client interface and leaves the extensibility
 interface as an obvious piece of work that needs little agreement and
 minimal design effort.

 Finally, your library keeps the client interface to a minimum and
 focuses almost exclusively on the extensibility interface. In doing so,
 it makes few choices that I disagree with. Allow me to share some
 specific feedback.
Note that my suggestion was just a simple and incomplete suggestion on how the API could look like. I only provided "info", "warning" and "error" methods as examples, I'm not saying the API should only have these three levels.
[snip] I thought about this some more and I understand I sounded unfair. There is a lot of merit and there are a lot of good ideas in your code (and of course Jose's), which I didn't mention for the simple but cold reason that negative feedback is more informative. But neglecting the merits is a mistake as well. I'll incorporate some of the ideas you suggested in the next pass through std.log. Thanks, Andrei
No hard feelings, I also have a tendency to just give negative feedback. -- /Jacob Carlborg
May 18 2011
prev sibling next sibling parent Jonas Drewsen <jdrewsen nospam.com> writes:
On 14/05/11 19.04, Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]

 I updated my std.log draft. Added a lot of features including formatted
 writing, delayed logging, and a variety of configuration options.
 Replaced the redundant log.xyz with logXyz. The implementation is
 getting close to reviewable form.

 Documentation:

 http://d-programming-language.org/phobos-prerelease/std_log.html

 Source:

 https://github.com/andralex/phobos

 Feedback welcome.
I like it! Some minor suggestions: The command line flags seem inconsistent in their naming e.g --minloglevel vs. --log_dir (the latter using underscores). Also single letter flags are usually written with a single '-' in front instead of '--' at least on posix platforms. /Jonas
May 16 2011
prev sibling parent Jens Mueller <jens.k.mueller gmx.de> writes:
Andrei Alexandrescu wrote:
 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
 [snip]
 
 I updated my std.log draft. Added a lot of features including
 formatted writing, delayed logging, and a variety of configuration
 options. Replaced the redundant log.xyz with logXyz. The
 implementation is getting close to reviewable form.
 
 Documentation:
 
 http://d-programming-language.org/phobos-prerelease/std_log.html
 
 Source:
 
 https://github.com/andralex/phobos
 
 Feedback welcome.
I started to test it out. Some things to consider: * If I miss a minus on a program option that option will be silently missed. E.g. I wrote -minloglevel 0 instead of --minloglevel 0 and was quite puzzled that I didn't get all messages. * Rename TEST_TMPDIR to LOG_TMPDIR or LOG_DIR? * I believe printing a ulong as thread id is too wasteful and makes the output harder to read. * I would arrange the loggers in increasing order of importance in the documentation (and source), i.e. logInfo, logWarning, ... And at very last: vlog. In the same order as done in the synopsis. * I'm unsure whether the logging levels should better be implemented using enum instead of dchars[]. Because 'I', 'W', 'E', 'C', 'F' are used several times in the source. * Instead of logInfo, logWarning, logError etc. just naming them info, warn, error etc. may be an option. I think it's quite obvious that these are logging statements. No need for the prefix log? * Even though vlog is short maybe logVerbose is more consistent. But admittedly it's quite long. I'm trying to read linker map files to evaluate how much code is generated when using the strip_log_* version options. Is there some good documentation on how to read those files? I believe I will have to read some basic literature about linker and loaders. Jens
May 16 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/7/2011 1:43 PM, Jose Armando Garcia wrote:
 My intent, and hopefully we will get there with your help, is to
 include this in Phobos for D2.
Thanks for doing the hard work of designing and laying out an implementation. Please, though, posting the source code as a news group message is not very efficient. Much better is to create an account with github, and post it there. Github has a lot of nice features that make collaboration, commenting, and incorporation easy, while a n.g. posting has none of that.
May 09 2011
parent Jose Armando Garcia <jsancio gmail.com> writes:
Thanks! Will do.

On Mon, May 9, 2011 at 4:11 PM, Walter Bright
<newshound2 digitalmars.com> wrote:
 On 5/7/2011 1:43 PM, Jose Armando Garcia wrote:
 My intent, and hopefully we will get there with your help, is to
 include this in Phobos for D2.
Thanks for doing the hard work of designing and laying out an implementation. Please, though, posting the source code as a news group message is not very efficient. Much better is to create an account with github, and post it there. Github has a lot of nice features that make collaboration, commenting, and incorporation easy, while a n.g. posting has none of that.
May 10 2011
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
Hey folks,

For the past couple of days I took the liberty of partially
implementing a logging module for D. I say partially because all the
features that I want to implement are not currently implement. You
should really look at the implementation more as a proof of concept
even thought most of the code will be used in the final
implementation.

That been said I am really interested in getting some feedback on the
API. That includes high-level design (e.g. using a thread to perform
logging. On that note I am planning to also have a shared memory
implementation), interfaces and the documentation.

When making comment be aware that the design goals of the module are:
1) Provide a logging mechanism that is easy to use in the common case.
2) The module should allow for as much configuration as possible at
compile time and execution time without breaking design goal 1.
3) It should be possible to extend or replace the backend without
breaking the semantic exposed by the API.

I am fairly new to the D language so any comment on how I can take
advantage of D idiom or D features in the API or implementation would
be greatly appreciated.

My intent, and hopefully we will get there with your help, is to
include this in Phobos for D2.

logging.d - http://ubuntuone.com/p/rfL/
logging.html - http://ubuntuone.com/p/rfM/

Thanks,
-Jose

On Mon, Apr 25, 2011 at 12:03 AM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 04/24/2011 02:23 PM, Sean Cavanaugh wrote:
 On 4/20/2011 11:09 AM, Robert Clipsham wrote:
 Hey folks,

 I've just finished porting my web framework from D1/Tango to D2/Phobos,
 and in the transition lost logging functionality. As I'll be writing a
 logging library anyway, I wondered if there'd be interest in a std.log?
 If so, is there a current logging library we would like it to be based
 on, or should we design from scratch?

 I know there has been discussion about Google's
 http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another
 candidate may be http://logging.apache.org/log4j/ . Do we want a
 comprehensive logging library, or just the basics? (Possibly with some
 method for extension if needed).
I just wanted to mention Pantheios as a C++ logging system to take look at as well, I didn't see it mentioned in this thread and it seems to have all the major requirements for frontend/backend chaining and whatnot that people have brought up. The code is on sourceforge to boot.
I think Pantheios is an example of library design gone bad. It is fascinatingly overengineered. Andrei
May 07 2011
prev sibling parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Sat, May 7, 2011 at 4:17 PM, Jose Armando Garcia <jsancio gmail.com>wrote:

 Hey folks,

 For the past couple of days I took the liberty of partially
 implementing a logging module for D. I say partially because all the
 features that I want to implement are not currently implement. You
 should really look at the implementation more as a proof of concept
 even thought most of the code will be used in the final
 implementation.

 That been said I am really interested in getting some feedback on the
 API. That includes high-level design (e.g. using a thread to perform
 logging. On that note I am planning to also have a shared memory
 implementation), interfaces and the documentation.

 When making comment be aware that the design goals of the module are:
 1) Provide a logging mechanism that is easy to use in the common case.
 2) The module should allow for as much configuration as possible at
 compile time and execution time without breaking design goal 1.
 3) It should be possible to extend or replace the backend without
 breaking the semantic exposed by the API.

 I am fairly new to the D language so any comment on how I can take
 advantage of D idiom or D features in the API or implementation would
 be greatly appreciated.

 My intent, and hopefully we will get there with your help, is to
 include this in Phobos for D2.

 logging.d - http://ubuntuone.com/p/rfL/
 logging.html - http://ubuntuone.com/p/rfM/

 Thanks,
 -Jose
I'll be sure to try it out in the next few days. Passing messages to a separate logging thread seems like it might be a overkill, but it could work. I do like that you can get the file and line included with messages. One thing I'll miss from Log4J and its siblings is that typing log.info("message") is a lot more intuitive than log(LogLevel.info, "message"). I don't think that's a major gripe though.
May 07 2011
parent reply dsimcha <dsimcha yahoo.com> writes:
On 5/7/2011 5:55 PM, Andrew Wiley wrote:
 I'll be sure to try it out in the next few days. Passing messages to a
 separate logging thread seems like it might be a overkill, but it could
 work.
Can you explain why you did this? I admittedly don't know much about logging but my gut instinct is that it's overengineering. Unless there's a good reason that I didn't foresee, I'd much rather just keep things like logging simple and stupid.
May 07 2011
parent reply Jose Armando Garcia <jsancio gmail.com> writes:
"Eat your own dog food". D goes to great extend to discourage memory
sharing and instead favor message passing. So I figure we should eat
our own dog food and use message passing in Phobos.

I know that is not a technical argument so let me do the following:
implement log buffering, implement a shared memory backend and do a
performance comparison of the two approaches on my crappy netbook
(which will be unfair but I don't currently have access to a
multi-core multi-process machine).

Thanks!
-Jose

On Sat, May 7, 2011 at 8:25 PM, dsimcha <dsimcha yahoo.com> wrote:
 On 5/7/2011 5:55 PM, Andrew Wiley wrote:
 I'll be sure to try it out in the next few days. Passing messages to a
 separate logging thread seems like it might be a overkill, but it could
 work.
Can you explain why you did this? =A0I admittedly don't know much about logging but my gut instinct is that it's overengineering. =A0Unless there=
's a
 good reason that I didn't foresee, I'd much rather just keep things like
 logging simple and stupid.
May 07 2011
parent reply dsimcha <dsimcha yahoo.com> writes:
Ok, there's clearly been some misunderstanding here.  My real point was, 
why do you need this threading at all?

On 5/7/2011 9:01 PM, Jose Armando Garcia wrote:
 "Eat your own dog food". D goes to great extend to discourage memory
 sharing and instead favor message passing. So I figure we should eat
 our own dog food and use message passing in Phobos.

 I know that is not a technical argument so let me do the following:
 implement log buffering, implement a shared memory backend and do a
 performance comparison of the two approaches on my crappy netbook
 (which will be unfair but I don't currently have access to a
 multi-core multi-process machine).

 Thanks!
 -Jose

 On Sat, May 7, 2011 at 8:25 PM, dsimcha<dsimcha yahoo.com>  wrote:
 On 5/7/2011 5:55 PM, Andrew Wiley wrote:
 I'll be sure to try it out in the next few days. Passing messages to a
 separate logging thread seems like it might be a overkill, but it could
 work.
Can you explain why you did this? I admittedly don't know much about logging but my gut instinct is that it's overengineering. Unless there's a good reason that I didn't foresee, I'd much rather just keep things like logging simple and stupid.
May 07 2011
next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Sat, May 7, 2011 at 11:03 PM, dsimcha <dsimcha yahoo.com> wrote:

 Ok, there's clearly been some misunderstanding here.  My real point was,
 why do you need this threading at all?
It's definitely overkill for a single threaded application, but for things like the application I'm working on, which is multithreaded and already uses message passing between threads, I think it would fit in quite nicely. My question would be whether it's pluggable enough to allow the simple case of a single threaded program that doesn't need message passing to be implemented.
May 08 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
 On Sat, May 7, 2011 at 11:03 PM, dsimcha <dsimcha yahoo.com> wrote:
 Ok, there's clearly been some misunderstanding here.  My real point was,
 why do you need this threading at all?
It's definitely overkill for a single threaded application, but for things like the application I'm working on, which is multithreaded and already uses message passing between threads, I think it would fit in quite nicely. My question would be whether it's pluggable enough to allow the simple case of a single threaded program that doesn't need message passing to be implemented.
Honestly, I would hope that whatever the logging did with threads would be entirely internal and invisible. At most, the logger should indicate which thread the log message came from. How it's thread safe should be invisible and irrelevant to anyone using the logger. Why should I care whether it's using message passing, shared variables, or whatever internally? Ideally, it wouldn't need to worry about threading at all, but I'm not sure how likely that is. I believe that writeln should be thread-safe, but I'm not sure that file stuff would be, and presumably the logger needs to be able to do both of those. - Jonathan M Davis
May 08 2011
prev sibling next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
I am not sure I follow. Writing to disk is slower than writing to
memory so you want to hide some of the cost of logging by either
buffering the write/log requests or messaging the requests to another
thread to do the logging for you. Does that answer your question?

On Sun, May 8, 2011 at 1:03 AM, dsimcha <dsimcha yahoo.com> wrote:
 Ok, there's clearly been some misunderstanding here. =A0My real point was=
, why
 do you need this threading at all?

 On 5/7/2011 9:01 PM, Jose Armando Garcia wrote:
 "Eat your own dog food". D goes to great extend to discourage memory
 sharing and instead favor message passing. So I figure we should eat
 our own dog food and use message passing in Phobos.

 I know that is not a technical argument so let me do the following:
 implement log buffering, implement a shared memory backend and do a
 performance comparison of the two approaches on my crappy netbook
 (which will be unfair but I don't currently have access to a
 multi-core multi-process machine).

 Thanks!
 -Jose

 On Sat, May 7, 2011 at 8:25 PM, dsimcha<dsimcha yahoo.com> =A0wrote:
 On 5/7/2011 5:55 PM, Andrew Wiley wrote:
 I'll be sure to try it out in the next few days. Passing messages to a
 separate logging thread seems like it might be a overkill, but it coul=
d
 work.
Can you explain why you did this? =A0I admittedly don't know much about logging but my gut instinct is that it's overengineering. =A0Unless the=
re's
 a
 good reason that I didn't foresee, I'd much rather just keep things lik=
e
 logging simple and stupid.
May 08 2011
parent reply dsimcha <dsimcha yahoo.com> writes:
On 5/8/2011 11:45 AM, Jose Armando Garcia wrote:
 I am not sure I follow. Writing to disk is slower than writing to
 memory so you want to hide some of the cost of logging by either
 buffering the write/log requests or messaging the requests to another
 thread to do the logging for you. Does that answer your question?
I thought that might be the reason. Makes sense if you have so much logging that it's a significant bottleneck, but I can't believe people write code like that.
May 08 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
 On 5/8/2011 11:45 AM, Jose Armando Garcia wrote:
 I am not sure I follow. Writing to disk is slower than writing to
 memory so you want to hide some of the cost of logging by either
 buffering the write/log requests or messaging the requests to another
 thread to do the logging for you. Does that answer your question?
I thought that might be the reason. Makes sense if you have so much logging that it's a significant bottleneck, but I can't believe people write code like that.
They do at least some of the time. Constructing strings to log can be slow regardless of whether you're outputting them or not, and waiting for them to be outputted can slow things down quite a bit. So, if you add a lot of logging to your code to be sure of what's going on, it can really slow things down, and sometimes you _need_ that sort of logging. And sometimes, even if you don't or you can't afford it, someone naively does it and causes a bottleneck. A lot of it depends on what type of program you're writing and who's writing it, but logging can be a definite bottleneck. And it can be very surprising how much a bottleneck it can be. If you're smart about it, you won't generally end up with logging being a large bottleneck, but logging CPU-intensive code is generally problematic because it _will_ become a bottleneck, and when you have larger projects (especially with a lot of people on them), it can become far too easy for logging code to be called for more often than you'd expect. - Jonathan M Davis
May 08 2011
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2011-05-08 18:24:12 -0400, Jonathan M Davis <jmdavisProg gmx.com> said:

 On 5/8/2011 11:45 AM, Jose Armando Garcia wrote:
 I am not sure I follow. Writing to disk is slower than writing to
 memory so you want to hide some of the cost of logging by either
 buffering the write/log requests or messaging the requests to another
 thread to do the logging for you. Does that answer your question?
I thought that might be the reason. Makes sense if you have so much logging that it's a significant bottleneck, but I can't believe people write code like that.
They do at least some of the time. Constructing strings to log can be slow regardless of whether you're outputting them or not, and waiting for them to be outputted can slow things down quite a bit. So, if you add a lot of logging to your code to be sure of what's going on, it can really slow things down, and sometimes you _need_ that sort of logging. And sometimes, even if you don't or you can't afford it, someone naively does it and causes a bottleneck. A lot of it depends on what type of program you're writing and who's writing it, but logging can be a definite bottleneck. And it can be very surprising how much a bottleneck it can be. If you're smart about it, you won't generally end up with logging being a large bottleneck, but logging CPU-intensive code is generally problematic because it _will_ become a bottleneck, and when you have larger projects (especially with a lot of people on them), it can become far too easy for logging code to be called for more often than you'd expect.
True. But on the other hand, if your program crashes, you lost the most valuable log entries -- those just before the crash -- as they're waiting in the logger thread's queue when the crash happens. So I don't think logging in a separate thread should be the default. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 08 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-08 15:45, Michel Fortin wrote:
 On 2011-05-08 18:24:12 -0400, Jonathan M Davis <jmdavisProg gmx.com> said:
 On 5/8/2011 11:45 AM, Jose Armando Garcia wrote:
 I am not sure I follow. Writing to disk is slower than writing to
 memory so you want to hide some of the cost of logging by either
 buffering the write/log requests or messaging the requests to another
 thread to do the logging for you. Does that answer your question?
I thought that might be the reason. Makes sense if you have so much logging that it's a significant bottleneck, but I can't believe people write code like that.
They do at least some of the time. Constructing strings to log can be slow regardless of whether you're outputting them or not, and waiting for them to be outputted can slow things down quite a bit. So, if you add a lot of logging to your code to be sure of what's going on, it can really slow things down, and sometimes you _need_ that sort of logging. And sometimes, even if you don't or you can't afford it, someone naively does it and causes a bottleneck. A lot of it depends on what type of program you're writing and who's writing it, but logging can be a definite bottleneck. And it can be very surprising how much a bottleneck it can be. If you're smart about it, you won't generally end up with logging being a large bottleneck, but logging CPU-intensive code is generally problematic because it _will_ become a bottleneck, and when you have larger projects (especially with a lot of people on them), it can become far too easy for logging code to be called for more often than you'd expect.
True. But on the other hand, if your program crashes, you lost the most valuable log entries -- those just before the crash -- as they're waiting in the logger thread's queue when the crash happens. So I don't think logging in a separate thread should be the default.
Oh, I'm not claiming that using a separate thread is the best way to do things. In fact, my first inclination would be very much _not_ to use a separate thread for logging. I wasn't trying to claim that that was the best approach. I was just pointing out that logging can definitely become a major bottleneck. Logging should be made as efficient as we reasonably can. What the best approach to that is, I don't know. Creating a separate thread might be it, or it might not. I doubt that it is, but I can see why someone would think of doing it. Your reason as to why not to do that though is a very good one. - Jonathan M Davis
May 08 2011
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
Yes. The current implementation doesn't support this because share
memory logging is not implement but in the future you should be able
to:

initializeLogging(ActorLogger.getCreator(args[0]));
// or...
initializeLogging(SharedLogger.getCreator(args[0]));

Where ActorLogger implements logging with message passing and
SharedLogger with a shared buffer. Maybe we can also provide an
implementation that assumes a single threading environment.

On Sun, May 8, 2011 at 6:00 AM, Andrew Wiley <wiley.andrew.j gmail.com> wro=
te:
 On Sat, May 7, 2011 at 11:03 PM, dsimcha <dsimcha yahoo.com> wrote:
 Ok, there's clearly been some misunderstanding here. =A0My real point wa=
s,
 why do you need this threading at all?
It's definitely overkill for a single threaded application, but for thing=
s
 like the application I'm working on, which is multithreaded and already u=
ses
 message passing between threads, I think it would fit in quite nicely.
 My question would be whether it's pluggable enough to allow the simple ca=
se
 of a single threaded program that doesn't need message passing to be
 implemented.
May 08 2011
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
Good point and I agree that most users don't care and just want it to
work... I'll change the API to reflect this.

On Sun, May 8, 2011 at 6:09 AM, Jonathan M Davis <jmdavisProg gmx.com> wrot=
e:
 On Sat, May 7, 2011 at 11:03 PM, dsimcha <dsimcha yahoo.com> wrote:
 Ok, there's clearly been some misunderstanding here. =A0My real point =
was,
 why do you need this threading at all?
It's definitely overkill for a single threaded application, but for thin=
gs
 like the application I'm working on, which is multithreaded and already
 uses message passing between threads, I think it would fit in quite
 nicely. My question would be whether it's pluggable enough to allow the
 simple case of a single threaded program that doesn't need message passi=
ng
 to be implemented.
Honestly, I would hope that whatever the logging did with threads would b=
e
 entirely internal and invisible. At most, the logger should indicate whic=
h
 thread the log message came from. How it's thread safe should be invisibl=
e and
 irrelevant to anyone using the logger. Why should I care whether it's usi=
ng
 message passing, shared variables, or whatever internally? Ideally, it
 wouldn't need to worry about threading at all, but I'm not sure how likel=
y
 that is. I believe that writeln should be thread-safe, but I'm not sure t=
hat
 file stuff would be, and presumably the logger needs to be able to do bot=
h of
 those.

 - Jonathan M Davis
May 08 2011