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
next sibling 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 =

=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
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
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 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; }

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

haven't check it): http://d.puremagic.com/issues/show_bug.cgi?id=5329 -- Dmitry Olshansky
Apr 20 2011
prev sibling next sibling parent 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
prev sibling next sibling parent "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
prev sibling next sibling parent 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
prev sibling next sibling 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 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
prev sibling next sibling parent "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
prev sibling next sibling parent 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
prev sibling next 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
next sibling 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 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 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 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 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 =



 why do you need this threading at all?

It's definitely overkill for a single threaded application, but for thin=


 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=


 to be implemented.

Honestly, I would hope that whatever the logging did with threads would b=

 entirely internal and invisible. At most, the logger should indicate whic=

 thread the log message came from. How it's thread safe should be invisibl=

 irrelevant to anyone using the logger. Why should I care whether it's usi=

 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=

 that is. I believe that writeln should be thread-safe, but I'm not sure t=

 file stuff would be, and presumably the logger needs to be able to do bot=

 those.

 - Jonathan M Davis

May 08 2011
prev sibling 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 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
prev sibling 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.

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.

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

I don't think the positional parameters are odd (C# has them with another syntax and Tango uses the same syntax as C#), I think they're 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

I don't think the positional parameters are odd (C# has them with another syntax and Tango uses the same syntax as C#), I think they're 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 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

I don't think the positional parameters are odd (C# has them with another syntax and Tango uses the same syntax as C#), I think they're 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 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? :<

I like it as well, the same syntax used by C# and Tango. -- /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. One possibility is to provide a nice2ugly template that transforms C# 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
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. One possibility is to provide a nice2ugly template that transforms C# 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 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.

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

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.

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 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
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 next 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
next sibling 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
next sibling parent 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
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 documentation says: "If log­ging is ef­fected with­out hav­ing called this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all log­ging 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. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 14 2011
next sibling 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 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
next sibling 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 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 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
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 documentation says: "If log­ging is ef­fected with­out hav­ing called this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all log­ging 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.

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.: void main(string[] args) { logtostderr = true; // override default initLogging(args); ... } Andrei
May 14 2011
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
 documentation says: "If log­ging is ef­fected with­out hav­ing called
 this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all
 log­ging 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.

A server app must log to files, no question about that. We'll need to add rotation etc. in the future.

No question about that. What I'm questioning is whether the typical use case for logging will be a server app. Ideally, I think we should encourage people to add logs everywhere it makes sense, if only as a debugging aid. If the default behaviour is to write logs to files it starts to look like a specialized tools for servers and such and it appears less relevant for other use cases.
 But I do plan to offer ways to manually override defaults, e.g.:
 
 void main(string[] args)
 {
      logtostderr = true; // override default
      initLogging(args);
      ...
 }

The default value for "logtostderr" should be reversed. Let's not make a server application the default use case for std.log, shall we? Even if that was the idea, the default is currently to save files in /tmp (or equivalent), which does not seem very appropriate for a server to me. I think logging to files should be enabled only explicitly by providing the default logging directory as an argument: initLogging(args, "/logdir"); -- Michel Fortin michel.fortin michelf.com http://michelf.com/
May 14 2011
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
 documentation says: "If log­ging is ef­fected with­out hav­ing called
 this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all
 log­ging 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.

A server app must log to files, no question about that. We'll need to add rotation etc. in the future.

No question about that. What I'm questioning is whether the typical use case for logging will be a server app. Ideally, I think we should encourage people to add logs everywhere it makes sense, if only as a debugging aid. If the default behaviour is to write logs to files it starts to look like a specialized tools for servers and such and it appears less relevant for other use cases.

In fact it may as well be the case that logging is for servers first. For casual use there's always writeln. Andrei
May 14 2011
prev sibling next sibling 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 documentation says: "If log­ging is ef­fected with­out hav­ing called this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all log­ging 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.

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

Depends on the app. I desire logs for my server to be sent over a socket to a centralized aggregator. But then I've got, um, well, a _lot_ of servers.

We'll need to provide socket streaming support. Andrei
May 14 2011
prev sibling 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 documentation says: "If log­ging is ef­fected with­out hav­ing called this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all log­ging 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.

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.: void main(string[] args) { logtostderr = 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 from 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

The way the Google flags library does that is by planting registration functions globally. Then initGoogle(argc, argv) at the beginning of main takes care of calling all registration functions. We could add such a hooking capability to getopt, but the current std.log design doesn't need one - it just calls getopt itself and cherry picks the parameters it's interested in. Andrei
May 15 2011
prev sibling parent 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
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
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 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 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
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 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.

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.

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 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 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 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 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 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 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
prev sibling parent 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=


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=



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=


this func=ADtion, all pa=ADra=ADme=ADters are at their de=ADfault val=AD=


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.

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
prev sibling next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
--bcaec547c9956f2d5f04a2b5a8f8
Content-Type: text/plain; charset=ISO-8859-1

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

--bcaec547c9956f2d5f04a2b5a8f8 Content-Type: text/html; charset=US-ASCII; name="logging.html" Content-Disposition: attachment; filename="logging.html" Content-Transfer-Encoding: base64 X-Attachment-Id: f_gnf06z0k0 PGh0bWw+PGhlYWQ+DQogICAgICAgIDxNRVRBIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29u dGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04Ij4NCiAgICAgICAgPHRpdGxlPnN0ZC5sb2dn aW5nPC90aXRsZT4NCiAgICAgICAgPC9oZWFkPjxib2R5Pg0KICAgICAgICA8aDE+c3RkLmxvZ2dp bmc8L2gxPg0KICAgICAgICA8IS0tIEdlbmVyYXRlZCBieSBEZG9jIGZyb20gc3JjL3N0ZC9sb2dn aW5nLmQgLS0+DQpJbXBsZW1lbnRzIGFwcGxpY2F0aW9uIGxldmVsIGxvZ2dpbmcgbWVjaGFuaXNt Lg0KPGJyPjxicj4NClRoaXMgbW9kdWxlIGRlZmluZXMgYSBzZXQgb2YgZnVuY3Rpb25zIHVzZWZ1 bCBmb3IgbWFueSBjb21tb24gbG9nZ2luZyB0YXNrcy4gIFRoZSBtb2R1bGUgbXVzdCBiZSBpbml0 aWFsaXplZCAoaWRlYWxseSBpbiBzaW5nbGUgdGhyZWFkZWQgbW9kZSkgYnkgY2FsbGluZyA8Yj48 dT5pbml0aWFsaXplTG9nZ2luZzwvdT48L2I+LiBNZXNzYWdlcyBvZiBkaWZmZXJlbnQgc2V2ZXJp dHkgbGV2ZWwgYXJlIGxvZ2dlZCBieSBjYWxsaW5nIHRoZSB0ZW1wbGF0ZSBmdW5jdGlvbnMgPGI+ PHU+bG9nPC91PjwvYj4gYW5kIDxiPjx1PmxvZ2Y8L3U+PC9iPi4gVmVyYm9zZSBtZXNzYWdlcyBj YW4gYmUgbG9nZ2VkIGJ5IGNhbGxpbmcgdGhlIHRlbXBsYXRlIGZ1bmN0aW9ucyAgPGI+PHU+dmxv ZzwvdT48L2I+IGFuZCA8Yj48dT52bG9nZjwvdT48L2I+Lg0KDQo8YnI+PGJyPg0KPGI+RXhhbXBs ZXM6PC9iPjxicj4NCjxwcmUgY2xhc3M9ImRfY29kZSI+PGZvbnQgY29sb3I9Ymx1ZT5pbXBvcnQ8 L2ZvbnQ+IHN0ZC48dT5sb2dnaW5nPC91PjsNCg0KPGZvbnQgY29sb3I9Ymx1ZT5pbnQ8L2ZvbnQ+ IG1haW4oc3RyaW5nW10gYXJncykNCnsNCiAgIGluaXRpYWxpemVMb2dnaW5nKEFjdG9yTG9nZ2Vy LmdldENyZWF0b3IoYXJnc1swXSkpOw0KDQogICA8Zm9udCBjb2xvcj1ncmVlbj4vLyAuLi4NCjwv Zm9udD4gICBsb2dmKExldmVsLmluZm8sIDxmb250IGNvbG9yPXJlZD4iTG9nIG1lc3NhZ2UgZnJv bSAlcyI8L2ZvbnQ+LCBhcmdzWzBdKTsNCn0NCjwvcHJlPg0KDQo8YnI+PGJyPg0KPGI+Tm90ZTo8 L2I+PGJyPg0KTG9nZ2luZyBjYW4gYmUgZGlzYWJsZSBhdCBjb21waWxlIHRpbWUgYnkgZGVmaW5p bmcgdGhlIExPR0dJTkdfRElTQUJMRUQgdmVyc2lvbi4NCg0KPGJyPjxicj4NCg0KPGRsPjxkdD48 YmlnPmVudW0gPHU+TGV2ZWw8L3U+Ow0KPC9iaWc+PC9kdD4NCjxkZD5EZWZpbmVzIHRoZSBzZXZl cml0eSBsZXZlbHMgc3VwcG9ydGVkIGJ5IHRoZSBsb2dnaW5nIGxpYnJhcnkuDQo8YnI+PGJyPg0K TG9nZ2luZyBtZXNzYWdlcyBvZiBzZXZlcml0eSBsZXZlbCA8dT5MZXZlbDwvdT4uZmF0YWwgd2ls bCBhbHNvIGNhdXNlIHRoZSBwcm9ncmFtIHRvIGhhbHQuIE1lc3NhZ2VzIG9mIGEgZ2l2ZW4gc2V2 ZXJpdHkgd2lsbCBiZSB3cml0dGVuIGluIHRoZSBsb2cgZmlsZSBvZiB0aGF0IHNldmVyaXR5IGFu ZCB0aGUgbG9nIGZpbGVzIG9mIGxvd2VyIHNldmVyaXR5Ljxicj48YnI+DQoNCjxkbD48ZHQ+PGJp Zz48dT5mYXRhbDwvdT48YnI+PHU+ZXJyb3I8L3U+PGJyPjx1Pndhcm5pbmc8L3U+PGJyPjx1Pmlu Zm88L3U+PC9iaWc+PC9kdD4NCjxkZD48YnI+PGJyPg0KPC9kZD4NCjwvZGw+DQo8L2RkPg0KPGR0 PjxiaWc+dm9pZCA8dT5pbml0aWFsaXplTG9nZ2luZzwvdT4oc2hhcmVkKExvZ2dlcikgZGVsZWdh dGUoKSA8aT5sb2dDcmVhdG9yPC9pPiwgTG9nQ29uZmlnIDxpPmxvZ0NvbmZpZzwvaT4gPSBMb2dD b25maWcobnVsbCxjYXN0KExldmVsKTEsbnVsbCxudWxsKSk7DQo8L2JpZz48L2R0Pg0KPGRkPklu aXRpYWxpemVzIHRoZSBsb2dnaW5nIGluZnJhc3RydWN0dXJlLg0KPGJyPjxicj4NClRoaXMgZnVu Y3Rpb24gbXVzdCBiZSBjYWxsZWQgb3VuY2UgYmVmb3JlIGNhbGxpbmcgYW55IG9mIHRoZSBsb2dn aW5nIGZ1bmN0aW9ucy4NCg0KPGJyPjxicj4NCjxiPlBhcmFtczo8L2I+PGJyPg0KPHRhYmxlPjx0 cj48dGQ+c2hhcmVkKExvZ2dlcikgZGVsZWdhdGUoKSA8aT5sb2dDcmVhdG9yPC9pPjwvdGQ+DQo8 dGQ+RGVsZWdhdGUgd2hpY2ggY3JlYXRlcyB0aGUgTG9nZ2VyIHVzZWQgYnkgdGhlIG1vZHVsZS48 L3RkPjwvdHI+DQo8dHI+PHRkPkxvZ0NvbmZpZyA8aT5sb2dDb25maWc8L2k+PC90ZD4NCjx0ZD5N b2R1bGUgY29uZmlndXJhdGlvbiBvYmplY3QuPC90ZD48L3RyPg0KPC90YWJsZT48YnI+DQo8Yj5T ZWUgQWxzbzo8L2I+PGJyPg0KTG9nQ29uZmlnPGJyPjxicj4NCg0KPC9kZD4NCjxkdD48YmlnPnZv aWQgPHU+bG9nZjwvdT4oc3RyaW5nIGZpbGUgPSBfX0ZJTEVfXywgaW50IGxpbmUgPSBfX0xJTkVf XywgVC4uLikoTGV2ZWwgPGk+bGV2ZWw8L2k+LCBsYXp5IFQgPGk+YXJnczwvaT4pOw0KPC9iaWc+ PC9kdD4NCjxkZD5Mb2dzIGEgZm9ybWF0dGVkIG1lc3NhZ2UuDQo8YnI+PGJyPg0KTG9ncyBhIGZv cm1hdHRlZCBtZXNzYWdlIGlmIDxpPmxldmVsPC9pPiBpcyBvZiBoaWdoZXIgb3IgZXF1YWwgc2V2 ZXJpdHkgYXMgdGhhdCBzcGVjaWZpZWQgaW4gdGhlIDxiPjx1PkxvZ0NvbmZpZzwvdT48L2I+IG9i amVjdCBwYXNzZWQgdG8gPGI+PHU+aW5pdGlhbGl6ZUxvZ2dpbmc8L3U+PC9iPi4NCjxicj48YnI+ DQoNClRoZSBmaXJzdCBwYXJhbWV0ZXIgaW4gPGk+YXJnczwvaT4gd2lsbCBiZSB1c2VkIGFzIHRo ZSBmb3JtYXQgc3RyaW5nLiBTZWUgPGI+PHU+c3RkLmZvcm1hdC5mb3JtYXR0ZWRXcml0ZTwvdT48 L2I+IGZvciBhIGRlc2NyaXB0aW9uIG9mIHRoZSBmb3JtYXQgc3RyaW5nLjxicj48YnI+DQoNCjwv ZGQ+DQo8ZHQ+PGJpZz52b2lkIDx1PmxvZzwvdT4oc3RyaW5nIGZpbGUgPSBfX0ZJTEVfXywgaW50 IGxpbmUgPSBfX0xJTkVfXywgVC4uLikoTGV2ZWwgPGk+bGV2ZWw8L2k+LCBsYXp5IFQgPGk+YXJn czwvaT4pOw0KPC9iaWc+PC9kdD4NCjxkZD5Mb2dzIGEgbWVzc2FnZQ0KPGJyPjxicj4NCkxvZ3Mg YSBtZXNzYWdlIGlmIDxpPmxldmVsPC9pPiBpcyBvZiBoaWdoZXIgb3IgZXF1YWwgc2V2ZXJpdHkg YXMgdGhhdCBzcGVjaWZpZWQgaW4gdGhlIDxiPjx1PkxvZ0NvbmZpZzwvdT48L2I+IG9iamVjdCBw YXNzZWQgdG8gPGI+PHU+aW5pdGlhbGl6ZUxvZ2dpbmc8L3U+PC9iPi48YnI+PGJyPg0KDQo8L2Rk Pg0KPGR0PjxiaWc+dm9pZCA8dT52bG9nZjwvdT4oc3RyaW5nIGZpbGUgPSBfX0ZJTEVfXywgaW50 IGxpbmUgPSBfX0xJTkVfXywgVC4uLikodWludCA8aT5sZXZlbDwvaT4sIGxhenkgVCA8aT5hcmdz PC9pPik7DQo8L2JpZz48L2R0Pg0KPGRkPkxvZ3MgYSBmb3JtYXR0ZWQgdmVyYm9zZSBtZXNzYWdl DQo8YnI+PGJyPg0KTG9ncyBhIGZvcm1hdHRlZCB2ZXJib3NlIG1lc3NhZ2UgaWYgdGhlIDxiPmZp bGU8L2I+IGFuZCA8aT5sZXZlbDwvaT4gbWF0Y2hlcyBvbmUgb2YgdGhlIGVudHJpZXMgc3BlY2lm aWVkIGluIHRoZSA8Yj48dT52TG9nQ29uZmlnczwvdT48L2I+IHByb3BlcnR5IG9mIHRoZSA8Yj48 dT5Mb2dDb25maWc8L3U+PC9iPiBvYmplY3QgcGFzc2VkIHRvIDxiPjx1PmluaXRpYWxpemVMb2dn aW5nPC91PjwvYj4uDQo8YnI+PGJyPg0KDQpUaGUgZmlyc3QgcGFyYW1ldGVyIGluIDxpPmFyZ3M8 L2k+IHdpbGwgYmUgdXNlZCBhcyB0aGUgZm9ybWF0IHN0cmluZy4gU2VlIDxiPjx1PnN0ZC5mb3Jt YXQuZm9ybWF0dGVkV3JpdGU8L3U+PC9iPiBmb3IgYSBkZXNjcmlwdGlvbiBvZiB0aGUgZm9ybWF0 IHN0cmluZy48YnI+PGJyPg0KDQo8L2RkPg0KPGR0PjxiaWc+dm9pZCA8dT52bG9nPC91PihzdHJp bmcgZmlsZSA9IF9fRklMRV9fLCBpbnQgbGluZSA9IF9fTElORV9fLCBULi4uKSh1aW50IDxpPmxl dmVsPC9pPiwgbGF6eSBUIDxpPmFyZ3M8L2k+KTsNCjwvYmlnPjwvZHQ+DQo8ZGQ+TG9ncyBhIHZl cmJvc2UgbWVzc2FnZQ0KPGJyPjxicj4NCkxvZ3MgYSB2ZXJib3NlIG1lc3NhZ2UgaWYgdGhlIDxi PmZpbGU8L2I+IGFuZCA8aT5sZXZlbDwvaT4gbWF0Y2hlcyBvbmUgb2YgdGhlIGVudHJpZXMgc3Bl Y2lmaWVkIGluIHRoZSA8Yj48dT52TG9nQ29uZmlnczwvdT48L2I+IHByb3BlcnR5IG9mIHRoZSA8 Yj48dT5Mb2dDb25maWc8L3U+PC9iPiBvYmplY3QgcGFzc2VkIHRvIDxiPjx1PmluaXRpYWxpemVM b2dnaW5nPC91PjwvYj4uPGJyPjxicj4NCg0KPC9kZD4NCjxkdD48YmlnPnN0cnVjdCA8dT5Mb2dD b25maWc8L3U+Ow0KPC9iaWc+PC9kdD4NCjxkZD5Db25maWd1cmF0aW9uIHN0cnVjdCBmb3IgdGhl IG1vZHVsZS4NCjxicj48YnI+DQpUaGlzIG9iamVjdCBtdXN0IGJlIHVzZWQgdG8gY29uZmlndXJl IHRoZSBsb2dnaW5nIG1vZHVsZSBhdCBpbml0aWFsaXphdGlvbi4gIEFsbCB0aGUgcHJvcGVydGll cyBhcmUgb3B0aW9uYWwgYW5kIGNhbiBiZSB1c2UgdG8gY29uZmlndXJlIHRoZSBmcmFtZXdvcmsn cyBiZWhhdmlvci48YnI+PGJyPg0KDQo8ZGw+PGR0PjxiaWc+dm9pZCA8dT5sZXZlbDwvdT4oTGV2 ZWwgPHU+bGV2ZWw8L3U+KTsNCjwvYmlnPjwvZHQ+DQo8ZGQ+TGV2ZWwgdG8gdXNlIGZvciBsb2dn aW5nLg0KPGJyPjxicj4NClRoZSBsb2dnaW5nIGZyYW1ld29yayB3aWxsIG9ubHkgbG9nIG1lc3Nh Z2VzIHdpdGggYSBzZXZlcml0eSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHZhbHVlIG9m IHRoaXMgcHJvcGVydHkuPGJyPjxicj4NCg0KPC9kZD4NCjxkdD48YmlnPnZvaWQgPHU+dkxvZ0Nv bmZpZ3M8L3U+KFZMb2dDb25maWdbXSA8dT52TG9nQ29uZmlnczwvdT4pOw0KPC9iaWc+PC9kdD4N CjxkZD5WZXJib3NlIGxvZ2dpbmcgY29uZmlndXJhdGlvbi4NCjxicj48YnI+DQpNZXNzYWdlcyBs b2dnZWQgYnkgdXNpbmcgdGhlIHRlbXBsYXRlIGZ1bmN0aW9uIDxiPjx1PnZsb2c8L3U+PC9iPiBv ciA8Yj48dT52bG9nZjwvdT48L2I+IHdpbGwgYmUgZmlsdGVyZWQgYnkgY29tcGFyaW5nIGFnYWlu c3QgZWFjaCBWTG9nQ29uZmlnIHVudGlsIGEgbWF0Y2ggaXMgZm91bmQuIElmIG5vIG1hdGNoIGlz IGZvdW5kIHRoZSB2ZXJib3NlIG1lc3NhZ2Ugd2lsbCBub3QgZ2V0IGxvZ2dlZC4NCg0KPGJyPjxi cj4NCjxiPlNlZSBBbHNvOjwvYj48YnI+DQpWTG9nQ29uZmlnPGJyPjxicj4NCg0KPC9kZD4NCjxk dD48YmlnPnZvaWQgPHU+ZmF0YWxIYW5kbGVyPC91Pih2b2lkIGZ1bmN0aW9uKCkgPHU+ZmF0YWxI YW5kbGVyPC91Pik7DQo8L2JpZz48L2R0Pg0KPGRkPkZ1bmN0aW9uIHBvaW50ZXIgZm9yIGhhbmRs aW5nIGxvZyBtZXNzYWdlIHdpdGggYSBzZXZlcml0eSBvZiBmYXRhbC4NCjxicj48YnI+DQpUaGlz IGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGJ5IHRoZSB0aHJlYWQgdHJ5aW5nIHRvIGxvZyBhIGZh dGFsIG1lc3NhZ2UgYnkgdXNpbmcgPGI+PHU+bG9nPC91PjwvYj4gb3IgPGI+PHU+bG9nZjwvdT48 L2I+LiBUaGUgZnVuY3Rpb24gPGk+PHU+ZmF0YWxIYW5kbGVyPC91PjwvaT4gc2hvdWxkIG5vdCBy ZXR1cm47IG90aGVyd2lzZSB0aGUgZnJhbWV3b3JrIHdpbGwgYXNzZXJ0KDxiPmZhbHNlPC9iPiku PGJyPjxicj4NCg0KPC9kZD4NCjwvZGw+DQo8L2RkPg0KPGR0PjxiaWc+c3RydWN0IDx1PlZMb2dD b25maWc8L3U+Ow0KPC9iaWc+PC9kdD4NCjxkZD5TdHJ1Y3R1cmUgZm9yIGNvbmZpZ3VyaW5nIHZl cmJvc2UgbG9nZ2luZy4NCjxicj48YnI+DQpUaGlzIHN0cnVjdHVyZSBpcyB1c2VkIHRvIGNvbnRy b2wgdmVyYm9zZSBsb2dnaW5nIG9uIGEgcGVyIG1vZHVsZSBiYXNpcy4gQSB2ZXJib3NlIG1lc3Nh Z2Ugd2l0aCBsZXZlbCA8aT54PC9pPiB3aWxsIGdldCBsb2dnZWQgYXQgc2V2ZXJpdHkgbGV2ZWwg TGV2ZWwuaW5mbyBpZiB0aGVyZSBpcyBhIDx1PlZMb2dDb25maWc8L3U+IGVudHJ5IHRoYXQgbWF0 Y2hlcyB0byB0aGUgc291cmNlIGZpbGUgYW5kIHRoZSB2ZXJib3NlIGxldmVsIG9mIHRoYXQgZW50 cnkgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDxpPng8L2k+Ljxicj48YnI+DQoNCjxkbD48 ZHQ+PGJpZz5zdGF0aWMgVkxvZ0NvbmZpZ1tdIDx1PmNyZWF0ZTwvdT4oc3RyaW5nIDxpPmNvbmZp ZzwvaT4pOw0KPC9iaWc+PC9kdD4NCjxkZD5DcmVhdGVzIGFuIGFycmF5IG9mIDxiPjx1PlZMb2dD b25maWc8L3U+PC9iPiBiYXNlZCBvbiBhIGNvbmZpZ3VyYXRpb24gc3RyaW5nLg0KPGJyPjxicj4N ClRoZSBmb3JtYXQgb2YgdGhlIGNvbmZpZ3VyYXRpb24gc3RyaW5nIGlzIGFzIGZvbGxvdyAiPGI+ W3BhdHRlcm5dPC9iPj08Yj5bbGV2ZWxdPC9iPiwuLi4iLCB3aGVyZSA8Yj5bcGF0dGVybl08L2I+ IG1heSBjb250YWluIGFueSBjaGFyYWN0ZXIgYWxsb3dlZCBpbiBhIGZpbGUgbmFtZSBhbmQgPGI+ W2xldmVsXTwvYj4gbXVzdCBiZSBjb252ZXJ0aWJsZSB0byBhbiBwb3NpdGl2ZSBpbnRlZ2VyIChn cmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gemVybykuIElmIDxiPltwYXR0ZXJuXTwvYj4gY29udGFp bnMgYSAnKicgdGhlbiBpdCBtdXN0IGJlIGF0IHRoZSBzdGFydCBvciB0aGUgZW5kLiBJZiA8Yj5b cGF0dGVybl08L2I+IGVuZHMgd2l0aCBhICcqJyB0aGVuIGl0IHdpbGwgbWF0Y2ggYW55IHNvdXJj ZSBmaWxlIG5hbWUgdGhhdCBzdGFydHMgd2l0aCB0aGUgcmVzdCBvZiA8Yj5bcGF0dGVybl08L2I+ LiBJZiA8Yj5bcGF0dGVybl08L2I+IHN0YXJ0cyB3aXRoIGEgJyonIHRoZW4gaXQgd2lsbCBtYXRj aCBhbnkgc291cmNlIGZpbGUgbmFtZSB0aGF0IGVuZHMgd2l0aCBhIHRoZSByZXN0IG9mIDxiPltw YXR0ZXJuXTwvYj4uDQo8YnI+PGJyPg0KDQpGb3IgZXZlcnkgPGI+W3BhdHRlcm5dPC9iPj08Yj5b bGV2ZWxdPC9iPiBpbiB0aGUgY29uZmlndXJhdGlvbiBzdHJpbmcgYSA8Yj48dT5WTG9nQ29uZmln PC91PjwvYj4gd2lsbCBiZSBjcmVhdGVkIGFuZCBpbmNsdWRlZCBpbiB0aGUgcmV0dXJuZWQgYXJy YXkuPGJyPjxicj4NCg0KPC9kZD4NCjwvZGw+DQo8L2RkPg0KPGR0PjxiaWc+YWJzdHJhY3QgaW50 ZXJmYWNlIDx1PkxvZ2dlcjwvdT47DQo8L2JpZz48L2R0Pg0KPGRkPkV4dGVuc2lvbiBwb2ludCBm b3IgdGhlIG1vZHVsZS48YnI+PGJyPg0KDQo8ZGw+PGR0PjxiaWc+YWJzdHJhY3Qgdm9pZCA8dT5s b2c8L3U+KExldmVsIDxpPmxldmVsPC9pPiwgc3RyaW5nIDxpPm1zZzwvaT4pOw0KPC9iaWc+PC9k dD4NCjxkZD5Mb2dzIGEgbWVzc2FnZS4NCjxicj48YnI+DQpUaGUgbWV0aG9kIGlzIGNhbGxlZCBi eSB0aGUgbG9nZ2luZyBtb2R1bGUgd2hlbmV2ZXIgaXQgZGVjaWRlcyB0aGF0IGEgbWVzc2FnZSBz aG91bGQgYmUgbG9nZ2VkLiBJdCBpcyByZWNvbW1lbmQgdGhhdCB0aGUgaW1wbGVtZW50YXRpb24g b2YgdGhpcyBtZXRob2QgZG9lc24ndCBwZXJmb3JtIGFueSBmaWx0ZXJpbmcgYmFzZWQgb24gPGk+ bGV2ZWw8L2k+IHNpbmNlIGF0IHRoaXMgcG9pbnQgYWxsIGNvbmZpZ3VyZWQgZmlsdGVycyB3ZXJl IGFwcGxpZWQuDQo8YnI+PGJyPg0KDQpUaGUgbWV0aG9kIGlzIGFsbG93IHRvIHJldHVybiBpbW1l ZGlhdGVseSB3aXRob3V0IHBlcnNpc3RpbmcgdGhlIG1lc3NhZ2UuPGJyPjxicj4NCg0KPC9kZD4N CjxkdD48YmlnPmFic3RyYWN0IHZvaWQgPHU+Zmx1c2g8L3U+KCk7DQo8L2JpZz48L2R0Pg0KPGRk PkZsdXNoZXMgcGVuZGluZyBsb2cgb3BlcmF0aW9ucy4NCjxicj48YnI+DQpUaGUgbWV0aG9kIGlz IGNhbGxlZCBieSB0aGUgbG9nZ2luZyBmcmFtZXdvcmsgd2hlbmV2ZXIgaXQgcmVxdWlyZXMgdGhh dCB0aGUgcGVyc2lzdGVuY2Ugb2YgYWxsIHByZXZpb3VzIGxvZyBtZXNzYWdlcy4gRm9yIGV4YW1w bGUgdGhlIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiB0aGUgY2xpZW50IGxvZ3MgYSBmYXRhbCBtZXNz YWdlLg0KPGJyPjxicj4NCg0KVGhlIG1ldGhvZCBtdXN0IG5vdCByZXR1cm4gdW50aWwgYWxsIHBl bmRpbmcgbG9nIG9wZXJhdGlvbnMgY29tcGxldGUuPGJyPjxicj4NCg0KPC9kZD4NCjwvZGw+DQo8 L2RkPg0KPGR0PjxiaWc+Y2xhc3MgPHU+QWN0b3JMb2dnZXI8L3U+OiBzdGQubG9nZ2luZy5Mb2dn ZXI7DQo8L2JpZz48L2R0Pg0KPGRkPkltcGxlbWVudHMgYW4gYWN0b3IgYmFzZWQgbG9nZ2luZyBi YWNrZW5kLg0KPGJyPjxicj4NCkxvZyBtZXNzYWdlcyBhcmUgc2VudCB0byBhIGxvZ2dpbmcgdGhy ZWFkIHdoaWNoIGlzIHJlc3BvbnNpYmxlIGZvciBwZXJzaXN0aW5nIGxvZyBtZXNzYWdlcy4gTWVz c2FnZXMgb2YgYSBnaXZlbiBzZXZlcml0eSB3aWxsIGJlIHdyaXR0ZW4gaW4gdGhlIGxvZyBmaWxl IG9mIHRoYXQgc2V2ZXJpdHkgYW5kIGluIHRoZSBsb2cgZmlsZXMgb2YgbG93ZXIgc2V2ZXJpdHku IFRoZSBmaWxlIG5hbWVzIG9mIHRoZSBsb2cgZmlsZXMgY3JlYXRlZCB3aWxsIGZvbGxvdyB0aGUg Zm9sbG93aW5nIHBhdHRlcm4gIjxiPltuYW1lXTwvYj4ubG9nLjxiPltsZXZlbF08L2I+LjxiPlt0 aW1lXTwvYj4iLiBUaGUgc3RyaW5nIDxiPltuYW1lXTwvYj4gaXMgdGhlIHBhcmFtZXRlciA8aT5u YW1lPC9pPiBwYXNzZWQgdG8gPGI+PHU+Z2V0Q3JlYXRvcjwvdT48L2I+LiBUaGUgc3RyaW5nIDxi Plt0aW1lXTwvYj4gaXMgdGhlIHRpbWUgd2hlbiB0aGUgbG9nZ2VyIHdhcyBjcmVhdGVkLiBUaGUg c3RyaW5nIDxiPltsZXZlbF08L2I+IGlzIHRoZSBzZXZlcml0eSBvZiB0aGUgbG9nIGZpbGUuIEEg ZmlsZSBmb3Igc2V2ZXJpdHkgbGV2ZWwgJ3gnIHdpbGwgY29udGFpbiBhbGwgbG9nIG1lc3NhZ2Vz IG9mIGdyZWF0ZXIgb3IgZXF1YWwgc2V2ZXJpdHkuPGJyPjxicj4NCg0KPGRsPjxkdD48YmlnPnN0 YXRpYyBzaGFyZWQoTG9nZ2VyKSBkZWxlZ2F0ZSgpIDx1PmdldENyZWF0b3I8L3U+KHN0cmluZyA8 aT5uYW1lPC9pPik7DQo8L2JpZz48L2R0Pg0KPGRkPlJldHVybnMgYSBkZWxlZ2F0ZSBmb3IgY3Jl YXRpbmcgYW4gQWN0b3JMb2dnZXIuDQo8YnI+PGJyPg0KVGhlIG1ldGhvZCB3aWxsIGFsd2F5cyBy ZXR1cm4gYSBkaWZmZXJlbnQgZGVsZWdhdGUgYnV0IGEgZ2l2ZW4gZGVsZWdhdGUgd2lsbCBhbHdh eXMgcmV0dXJuIHRoZSBzYW1lIDxiPjx1PkFjdG9yTG9nZ2VyPC91PjwvYj4uDQoNCjxicj48YnI+ DQo8Yj5QYXJhbXM6PC9iPjxicj4NCjx0YWJsZT48dHI+PHRkPnN0cmluZyA8aT5uYW1lPC9pPjwv dGQ+DQo8dGQ+TmFtZSB0byB1c2Ugd2hlbiBjcmVhdGluZyBsb2cgZmlsZXM8L3RkPjwvdHI+DQo8 L3RhYmxlPjxicj4NCg0KPC9kZD4NCjwvZGw+DQo8L2RkPg0KPC9kbD4NCg0KICAgICAgICA8aHI+ PHNtYWxsPlBhZ2UgZ2VuZXJhdGVkIGJ5IDxhIGhyZWY9Imh0dHA6Ly93d3cuZGlnaXRhbG1hcnMu Y29tL2QvMi4wL2Rkb2MuaHRtbCI+RGRvYzwvYT4uIDwvc21hbGw+DQogICAgICAgIDwvYm9keT48 L2h0bWw+DQo= --bcaec547c9956f2d5f04a2b5a8f8 Content-Type: application/octet-stream; name="logging.d" Content-Disposition: attachment; filename="logging.d" Content-Transfer-Encoding: base64 X-Attachment-Id: f_gnf07l7r1 Ly8gV3JpdHRlbiBpbiB0aGUgRCBwcm9ncmFtbWluZyBsYW5ndWFnZS4KCi8rKwpJbXBsZW1lbnRz IGFwcGxpY2F0aW9uIGxldmVsIF9sb2dnaW5nIG1lY2hhbmlzbS4KClRoaXMgbW9kdWxlIGRlZmlu ZXMgYSBzZXQgb2YgZnVuY3Rpb25zIHVzZWZ1bCBmb3IgbWFueSBjb21tb24gX2xvZ2dpbmcgdGFz a3MuICBUaGUgbW9kdWxlIG11c3QgYmUgaW5pdGlhbGl6ZWQgKGlkZWFsbHkgaW4gc2luZ2xlIHRo cmVhZGVkIG1vZGUpIGJ5IGNhbGxpbmcgJChEIGluaXRpYWxpemVMb2dnaW5nKS4gTWVzc2FnZXMg b2YgZGlmZmVyZW50IHNldmVyaXR5IGxldmVsIGFyZSBsb2dnZWQgYnkgY2FsbGluZyB0aGUgdGVt cGxhdGUgZnVuY3Rpb25zICQoRCBsb2cpIGFuZCAkKEQgbG9nZikuIFZlcmJvc2UgbWVzc2FnZXMg Y2FuIGJlIGxvZ2dlZCBieSBjYWxsaW5nIHRoZSB0ZW1wbGF0ZSBmdW5jdGlvbnMgICQoRCB2bG9n KSBhbmQgJChEIHZsb2dmKS4KCkV4YW1wbGVzOgotLS0KaW1wb3J0IHN0ZC5sb2dnaW5nOwoKaW50 IG1haW4oc3RyaW5nW10gYXJncykKewogICBpbml0aWFsaXplTG9nZ2luZyhBY3RvckxvZ2dlci5n ZXRDcmVhdG9yKGFyZ3NbMF0pKTsKCiAgIC8vIC4uLgogICBsb2dmKExldmVsLmluZm8sICJMb2cg bWVzc2FnZSBmcm9tICVzIiwgYXJnc1swXSk7Cn0KLS0tCgpOb3RlOgpMb2dnaW5nIGNhbiBiZSBk aXNhYmxlIGF0IGNvbXBpbGUgdGltZSBieSBkZWZpbmluZyB0aGUgTE9HR0lOR19ESVNBQkxFRCB2 ZXJzaW9uLgoKTWFjcm9zOgpEID0gJChCJChVICQwKSkKKy8KbW9kdWxlIHN0ZC5sb2dnaW5nOwoK aW1wb3J0IGNvcmUuYXRvbWljIDogY2FzOwppbXBvcnQgc3RkLnN0ZGlvIDogRmlsZTsKaW1wb3J0 IHN0ZC5jb252IDogdGV4dCwgdG87CmltcG9ydCBzdGQuZGF0ZXRpbWU6IENsb2NrLCBEYXRlVGlt ZTsKaW1wb3J0IHN0ZC5leGNlcHRpb24gOiBlbmZvcmNlOwppbXBvcnQgc3RkLmNvbmN1cnJlbmN5 IDogc3Bhd24sCiAgICAgICAgICAgICAgICAgICAgICAgICBUaWQsCiAgICAgICAgICAgICAgICAg ICAgICAgICBzZW5kLAogICAgICAgICAgICAgICAgICAgICAgICAgcmVjZWl2ZSwKICAgICAgICAg ICAgICAgICAgICAgICAgIE93bmVyVGVybWluYXRlZCwKICAgICAgICAgICAgICAgICAgICAgICAg IHRoaXNUaWQsCiAgICAgICAgICAgICAgICAgICAgICAgICByZWNlaXZlT25seTsKaW1wb3J0IHN0 ZC50cmFpdHMgOiBFbnVtTWVtYmVyczsKaW1wb3J0IHN0ZC5hcnJheSA6IGFwcGVuZGVyLCBhcnJh eTsKaW1wb3J0IHN0ZC5mb3JtYXQgOiBmb3JtYXR0ZWRXcml0ZTsKaW1wb3J0IHN0ZC5hbGdvcml0 aG0gOiBlbmRzV2l0aCwgc3RhcnRzV2l0aCwgc3BsaXR0ZXI7Cgp2ZXJzaW9uKHVuaXR0ZXN0KQp7 CiAgIGltcG9ydCBzdGQuZmlsZSA6IHJlbW92ZTsKICAgaW1wb3J0IGNvcmUuZXhjZXB0aW9uIDog QXNzZXJ0RXJyb3I7Cn0KCnZlcnNpb24oTE9HR0lOR19ESVNBQkxFRCkge30KZWxzZSB7IHZlcnNp b24gPSBMT0dHSU5HOyB9CgovKysKRGVmaW5lcyB0aGUgc2V2ZXJpdHkgbGV2ZWxzIHN1cHBvcnRl ZCBieSB0aGUgbG9nZ2luZyBsaWJyYXJ5LgoKTG9nZ2luZyBtZXNzYWdlcyBvZiBzZXZlcml0eSBs ZXZlbCBMZXZlbC5mYXRhbCB3aWxsIGFsc28gY2F1c2UgdGhlIHByb2dyYW0gdG8gaGFsdC4gTWVz c2FnZXMgb2YgYSBnaXZlbiBzZXZlcml0eSB3aWxsIGJlIHdyaXR0ZW4gaW4gdGhlIGxvZyBmaWxl IG9mIHRoYXQgc2V2ZXJpdHkgYW5kIHRoZSBsb2cgZmlsZXMgb2YgbG93ZXIgc2V2ZXJpdHkuCisv CmVudW0gTGV2ZWwKewogICBmYXRhbCA9IDAsIC8vLwogICBlcnJvciwgLy8vIGRpdHRvCiAgIHdh cm5pbmcsIC8vLyBkaXR0bwogICBpbmZvIC8vLyBkaXR0bwp9CgovKysKSW5pdGlhbGl6ZXMgdGhl IGxvZ2dpbmcgaW5mcmFzdHJ1Y3R1cmUuCgpUaGlzIGZ1bmN0aW9uIG11c3QgYmUgY2FsbGVkIG91 bmNlIGJlZm9yZSBjYWxsaW5nIGFueSBvZiB0aGUgbG9nZ2luZyBmdW5jdGlvbnMuCgpQYXJhbXM6 CiAgIGxvZ0NyZWF0b3IgPSBEZWxlZ2F0ZSB3aGljaCBjcmVhdGVzIHRoZSBMb2dnZXIgdXNlZCBi eSB0aGUgbW9kdWxlLgogICBsb2dDb25maWcgPSBNb2R1bGUgY29uZmlndXJhdGlvbiBvYmplY3Qu IAoKU2VlX0Fsc286CiAgIExvZ0NvbmZpZworLwp2b2lkIGluaXRpYWxpemVMb2dnaW5nKHNoYXJl ZChMb2dnZXIpIGRlbGVnYXRlKCkgbG9nQ3JlYXRvciwKICAgICAgICAgICAgICAgICAgICAgICBM b2dDb25maWcgbG9nQ29uZmlnID0gTG9nQ29uZmlnKCkpCnsKICAgX2ludGVybmFsLmluaXQobG9n Q3JlYXRvciwgbG9nQ29uZmlnKTsKfQoKLysrCkxvZ3MgYSBmb3JtYXR0ZWQgbWVzc2FnZS4KCkxv Z3MgYSBmb3JtYXR0ZWQgbWVzc2FnZSBpZiAkKEkgbGV2ZWwpIGlzIG9mIGhpZ2hlciBvciBlcXVh bCBzZXZlcml0eSBhcyB0aGF0IHNwZWNpZmllZCBpbiB0aGUgJChEIExvZ0NvbmZpZykgb2JqZWN0 IHBhc3NlZCB0byAkKEQgaW5pdGlhbGl6ZUxvZ2dpbmcpLgoKVGhlIGZpcnN0IHBhcmFtZXRlciBp biAkKEkgYXJncykgd2lsbCBiZSB1c2VkIGFzIHRoZSBmb3JtYXQgc3RyaW5nLiBTZWUgJChEIHN0 ZC5mb3JtYXQuZm9ybWF0dGVkV3JpdGUpIGZvciBhIGRlc2NyaXB0aW9uIG9mIHRoZSBmb3JtYXQg c3RyaW5nLgorLwp2b2lkIGxvZ2Yoc3RyaW5nIGZpbGUgPSBfX0ZJTEVfXywKICAgICAgICAgIGlu dCBsaW5lID0gX19MSU5FX18sCiAgICAgICAgICBULi4uKQogICAgICAgICAoTGV2ZWwgbGV2ZWws CiAgICAgICAgICBsYXp5IFQgYXJncykKewogICB2ZXJzaW9uKExPR0dJTkcpIF9pbnRlcm5hbC5s b2coZmlsZSwgbGluZSwgbGV2ZWwsIHRydWUsIGFyZ3MpOwp9CgovKysKTG9ncyBhIG1lc3NhZ2UK CkxvZ3MgYSBtZXNzYWdlIGlmICQoSSBsZXZlbCkgaXMgb2YgaGlnaGVyIG9yIGVxdWFsIHNldmVy aXR5IGFzIHRoYXQgc3BlY2lmaWVkIGluIHRoZSAkKEQgTG9nQ29uZmlnKSBvYmplY3QgcGFzc2Vk IHRvICQoRCBpbml0aWFsaXplTG9nZ2luZykuCisvCnZvaWQgbG9nKHN0cmluZyBmaWxlID0gX19G SUxFX18sCiAgICAgICAgIGludCBsaW5lID0gX19MSU5FX18sCiAgICAgICAgIFQuLi4pCiAgICAg ICAgKExldmVsIGxldmVsLAogICAgICAgICBsYXp5IFQgYXJncykKewogICB2ZXJzaW9uKExPR0dJ TkcpIF9pbnRlcm5hbC5sb2coZmlsZSwgbGluZSwgbGV2ZWwsIGZhbHNlLCBhcmdzKTsKfQoKLysr CkxvZ3MgYSBmb3JtYXR0ZWQgdmVyYm9zZSBtZXNzYWdlCgpMb2dzIGEgZm9ybWF0dGVkIHZlcmJv c2UgbWVzc2FnZSBpZiB0aGUgJChCIGZpbGUpIGFuZCAkKEkgbGV2ZWwpIG1hdGNoZXMgb25lIG9m IHRoZSBlbnRyaWVzIHNwZWNpZmllZCBpbiB0aGUgJChEIHZMb2dDb25maWdzKSBwcm9wZXJ0eSBv ZiB0aGUgJChEIExvZ0NvbmZpZykgb2JqZWN0IHBhc3NlZCB0byAkKEQgaW5pdGlhbGl6ZUxvZ2dp bmcpLgoKVGhlIGZpcnN0IHBhcmFtZXRlciBpbiAkKEkgYXJncykgd2lsbCBiZSB1c2VkIGFzIHRo ZSBmb3JtYXQgc3RyaW5nLiBTZWUgJChEIHN0ZC5mb3JtYXQuZm9ybWF0dGVkV3JpdGUpIGZvciBh IGRlc2NyaXB0aW9uIG9mIHRoZSBmb3JtYXQgc3RyaW5nLgorLwp2b2lkIHZsb2dmKHN0cmluZyBm aWxlID0gX19GSUxFX18sCiAgICAgICAgICAgaW50IGxpbmUgPSBfX0xJTkVfXywKICAgICAgICAg ICBULi4uKQogICAgICAgICAgKHVpbnQgbGV2ZWwsCiAgICAgICAgICAgbGF6eSBUIGFyZ3MpCnsK ICAgdmVyc2lvbihMT0dHSU5HKSBfaW50ZXJuYWwudmxvZyhmaWxlLCBsaW5lLCBsZXZlbCwgdHJ1 ZSwgYXJncyk7Cn0KCi8rKwpMb2dzIGEgdmVyYm9zZSBtZXNzYWdlCgpMb2dzIGEgdmVyYm9zZSBt ZXNzYWdlIGlmIHRoZSAkKEIgZmlsZSkgYW5kICQoSSBsZXZlbCkgbWF0Y2hlcyBvbmUgb2YgdGhl IGVudHJpZXMgc3BlY2lmaWVkIGluIHRoZSAkKEQgdkxvZ0NvbmZpZ3MpIHByb3BlcnR5IG9mIHRo ZSAkKEQgTG9nQ29uZmlnKSBvYmplY3QgcGFzc2VkIHRvICQoRCBpbml0aWFsaXplTG9nZ2luZyku CisvCnZvaWQgdmxvZyhzdHJpbmcgZmlsZSA9IF9fRklMRV9fLAogICAgICAgICAgaW50IGxpbmUg PSBfX0xJTkVfXywKICAgICAgICAgIFQuLi4pCiAgICAgICAgICh1aW50IGxldmVsLAogICAgICAg ICAgbGF6eSBUIGFyZ3MpCnsKICAgdmVyc2lvbihMT0dHSU5HKSBfaW50ZXJuYWwudmxvZyhmaWxl LCBsaW5lLCBsZXZlbCwgZmFsc2UsIGFyZ3MpOwp9CgovKysKQ29uZmlndXJhdGlvbiBzdHJ1Y3Qg Zm9yIHRoZSBtb2R1bGUuCgpUaGlzIG9iamVjdCBtdXN0IGJlIHVzZWQgdG8gY29uZmlndXJlIHRo ZSBsb2dnaW5nIG1vZHVsZSBhdCBpbml0aWFsaXphdGlvbi4gIEFsbCB0aGUgcHJvcGVydGllcyBh cmUgb3B0aW9uYWwgYW5kIGNhbiBiZSB1c2UgdG8gY29uZmlndXJlIHRoZSBmcmFtZXdvcmsncyBi ZWhhdmlvci4KKy8Kc3RydWN0IExvZ0NvbmZpZwp7Ci8rKwpMZXZlbCB0byB1c2UgZm9yIF9sb2dn aW5nLgoKVGhlIGxvZ2dpbmcgZnJhbWV3b3JrIHdpbGwgb25seSBsb2cgbWVzc2FnZXMgd2l0aCBh IHNldmVyaXR5IGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byB0aGUgdmFsdWUgb2YgdGhpcyBwcm9w ZXJ0eS4KKy8KICAgQHByb3BlcnR5IHZvaWQgbGV2ZWwoTGV2ZWwgbGV2ZWwpCiAgIHsKICAgICAg X2xldmVsID0gbGV2ZWw7CiAgIH0KCi8rKwpWZXJib3NlIGxvZ2dpbmcgY29uZmlndXJhdGlvbi4K Ck1lc3NhZ2VzIGxvZ2dlZCBieSB1c2luZyB0aGUgdGVtcGxhdGUgZnVuY3Rpb24gJChEIHZsb2cp IG9yICQoRCB2bG9nZikgd2lsbCBiZSBmaWx0ZXJlZCBieSBjb21wYXJpbmcgYWdhaW5zdCBlYWNo IFZMb2dDb25maWcgdW50aWwgYSBtYXRjaCBpcyBmb3VuZC4gSWYgbm8gbWF0Y2ggaXMgZm91bmQg dGhlIHZlcmJvc2UgbWVzc2FnZSB3aWxsIG5vdCBnZXQgbG9nZ2VkLgoKU2VlX0Fsc286CiAgIFZM b2dDb25maWcKKy8KICAgQHByb3BlcnR5IHZvaWQgdkxvZ0NvbmZpZ3MoVkxvZ0NvbmZpZ1tdIHZM b2dDb25maWdzKQogICB7CiAgICAgIF92TG9nQ29uZmlncyA9IHZMb2dDb25maWdzOwogICB9Cgov KysKRnVuY3Rpb24gcG9pbnRlciBmb3IgaGFuZGxpbmcgbG9nIG1lc3NhZ2Ugd2l0aCBhIHNldmVy aXR5IG9mIGZhdGFsLgoKVGhpcyBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBieSB0aGUgdGhyZWFk IHRyeWluZyB0byBsb2cgYSBmYXRhbCBtZXNzYWdlIGJ5IHVzaW5nICQoRCBsb2cpIG9yICQoRCBs b2dmKS4gVGhlIGZ1bmN0aW9uICQoSSBmYXRhbEhhbmRsZXIpIHNob3VsZCBub3QgcmV0dXJuOyBv dGhlcndpc2UgdGhlIGZyYW1ld29yayB3aWxsIGFzc2VydChmYWxzZSkuCisvCiAgIEBwcm9wZXJ0 eSB2b2lkIGZhdGFsSGFuZGxlcih2b2lkIGZ1bmN0aW9uKCkgZmF0YWxIYW5kbGVyKQogICB7CiAg ICAgIF9mYXRhbEhhbmRsZXIgPSBmYXRhbEhhbmRsZXI7CiAgIH0KCiAgIHByaXZhdGUgc3RyaW5n IF9uYW1lOwogICBwcml2YXRlIExldmVsIF9sZXZlbCA9IExldmVsLmVycm9yOwogICBwcml2YXRl IFZMb2dDb25maWdbXSBfdkxvZ0NvbmZpZ3M7CiAgIHByaXZhdGUgdm9pZCBmdW5jdGlvbigpIF9m YXRhbEhhbmRsZXI7Cn0KCi8rCnRlbXBsYXRlIGlzTG9nV3JpdGVyKFcpCnsKICAgZW51bSBib29s IGlzTG9nV3JpdGVyID0gaXModHlwZW9mKAogICAgICB7CiAgICAgICAgIFcgdzsKICAgICAgICAg dy5sb2coTGV2ZWwubWF4LCAiIik7CiAgICAgICAgIHcuZmx1c2goKTsKICAgICAgfSgpKSk7Cn0K Ky8KCnVuaXR0ZXN0CnsKICAgLy8gVGVzdCBsZXZlbCBmaWx0ZXJpbmcKICAgY2xhc3MgTGV2ZWxG aWx0ZXIgOiBMb2dnZXIKICAgewogICAgICBzaGFyZWQgdm9pZCBsb2coTGV2ZWwgbGV2ZWwsIHN0 cmluZyBtc2cpCiAgICAgIHsKICAgICAgICAgY2FsbGVkID0gdHJ1ZTsKICAgICAgICAgbGFzdExl dmVsID0gbGV2ZWw7CiAgICAgICAgIGxhc3RNc2cgPSBtc2c7CiAgICAgIH0KCiAgICAgIHNoYXJl ZCB2b2lkIGZsdXNoKCkKICAgICAgewogICAgICAgICBmbHVzaENhbGxlZCA9IHRydWU7CiAgICAg IH0KCiAgICAgIHNoYXJlZCB2b2lkIGNsZWFyKCkKICAgICAgewogICAgICAgICBsYXN0TXNnID0g c3RyaW5nLmluaXQ7CiAgICAgICAgIGxhc3RMZXZlbCA9IExldmVsLmluaXQ7CiAgICAgICAgIGNh bGxlZCA9IGZhbHNlOwogICAgICAgICBmbHVzaENhbGxlZCA9IGZhbHNlOwogICAgICB9CgogICAg ICBzdHJpbmcgbGFzdE1zZzsKICAgICAgTGV2ZWwgbGFzdExldmVsOwogICAgICBib29sIGNhbGxl ZDsKICAgICAgYm9vbCBmbHVzaENhbGxlZDsKICAgfQoKICAgTG9nQ29uZmlnIGxvZ0NvbmZpZzsK ICAgbG9nQ29uZmlnLmxldmVsID0gTGV2ZWwud2FybmluZzsKICAgbG9nQ29uZmlnLnZMb2dDb25m aWdzID0gVkxvZ0NvbmZpZy5jcmVhdGUoIipsb2dnaW5nLmQ9MiIpOwoKICAgYXV0byBsb2dnZXIg PSBjYXN0KHNoYXJlZCkgbmV3IExldmVsRmlsdGVyKCk7CiAgIEludGVybmFsTG9nZ2luZyBsb2dn aW5nOwoKICAgbG9nZ2luZy5pbml0KHsgcmV0dXJuIGNhc3Qoc2hhcmVkKExvZ2dlcikpIGxvZ2dl cjsgfSwKICAgICAgICAgICAgICAgIGxvZ0NvbmZpZyk7CgogICBhdXRvIGxvZ2dlZE1lc3NhZ2Ug PSAibG9nZ2VkIG1lc3NhZ2UiOwoKICAgLy8gVGVzdCBsb2dnaW5nIGFuZCBsZXZlbCBmaWx0ZXJp bmcKICAgbG9nZ2luZy5sb2coInBhY2thZ2UvbG9nZ2luZy5kIiwgMTEsIExldmVsLmluZm8sIGZh bHNlLCBsb2dnZWRNZXNzYWdlKTsKICAgYXNzZXJ0KCFsb2dnZXIuY2FsbGVkKTsKCiAgIGxvZ2dl ci5jbGVhcigpOwogICBsb2dnaW5nLmxvZygicGFja2FnZS9sb2dnaW5nLmQiLCAxMSwgTGV2ZWwu d2FybmluZywgZmFsc2UsIGxvZ2dlZE1lc3NhZ2UpOwogICBhc3NlcnQobG9nZ2VyLmNhbGxlZCk7 CiAgIGFzc2VydChsb2dnZXIubGFzdExldmVsID09IExldmVsLndhcm5pbmcgJiYKICAgICAgICAg IGVuZHNXaXRoKGxvZ2dlci5sYXN0TXNnLCBsb2dnZWRNZXNzYWdlKSk7CgogICBsb2dnZXIuY2xl YXIoKTsKICAgbG9nZ2luZy5sb2coInBhY2thZ2UvbG9nZ2luZy5kIiwgMTEsIExldmVsLmVycm9y LCBmYWxzZSwgbG9nZ2VkTWVzc2FnZSk7CiAgIGFzc2VydChsb2dnZXIuY2FsbGVkKTsKICAgYXNz ZXJ0KGxvZ2dlci5sYXN0TGV2ZWwgPT0gTGV2ZWwuZXJyb3IgJiYKICAgICAgICAgIGVuZHNXaXRo KGxvZ2dlci5sYXN0TXNnLCBsb2dnZWRNZXNzYWdlKSk7CgogICBsb2dnZXIuY2xlYXIoKTsKICAg bG9nZ2luZy5sb2coInBhY2thZ2UvbG9nZ2luZy5kIiwgMTEsIExldmVsLmVycm9yLCBmYWxzZSwg bG9nZ2VkTWVzc2FnZSk7CiAgIGFzc2VydChsb2dnZXIuY2FsbGVkKTsKICAgYXNzZXJ0KGxvZ2dl ci5sYXN0TGV2ZWwgPT0gTGV2ZWwuZXJyb3IgJiYKICAgICAgICAgIGVuZHNXaXRoKGxvZ2dlci5s YXN0TXNnLCBsb2dnZWRNZXNzYWdlKSk7CgogICAvLyBYWFggdGhpcyBpcyB1Z2x5LiBGaXggdGhp cyB0ZXN0LiBsb29rIGludG8gdXNpbmcgYXNzZXJ0VGhyb3duCiAgIGxvZ2dlci5jbGVhcigpOwog ICB0cnkKICAgewogICAgICBsb2dnaW5nLmxvZygicGFja2FnZS9sb2dnaW5nLmQiLCAxMSwgTGV2 ZWwuZmF0YWwsIGZhbHNlLCBsb2dnZWRNZXNzYWdlKTsKICAgICAgYXNzZXJ0KGZhbHNlKTsKICAg fQogICBjYXRjaCAoQXNzZXJ0RXJyb3IgZSkge30KICAgYXNzZXJ0KGxvZ2dlci5jYWxsZWQpOwog ICBhc3NlcnQobG9nZ2VyLmxhc3RMZXZlbCA9PSBMZXZlbC5mYXRhbCAmJgogICAgICAgICAgZW5k c1dpdGgobG9nZ2VyLmxhc3RNc2csIGxvZ2dlZE1lc3NhZ2UpKTsKICAgYXNzZXJ0KGxvZ2dlci5m bHVzaENhbGxlZCk7CgogICBsb2dnZXIuY2xlYXIoKTsKICAgbG9nZ2luZy5sb2coInBhY2thZ2Uv bG9nZ2luZy5kIiwKICAgICAgICAgICAgICAgMTEsCiAgICAgICAgICAgICAgIExldmVsLndhcm5p bmcsCiAgICAgICAgICAgICAgIHRydWUsCiAgICAgICAgICAgICAgICIlcyIsCiAgICAgICAgICAg ICAgIGxvZ2dlZE1lc3NhZ2UpOwogICBhc3NlcnQobG9nZ2VyLmNhbGxlZCk7CiAgIGFzc2VydChs b2dnZXIubGFzdExldmVsID09IExldmVsLndhcm5pbmcgJiYKICAgICAgICAgIGVuZHNXaXRoKGxv Z2dlci5sYXN0TXNnLCBsb2dnZWRNZXNzYWdlKSk7CgogICAvLyBUZXN0IHZsb2dnaW5nIGFuZCBt b2R1bGUgZmlsdGVyaW5nCiAgIGxvZ2dlci5jbGVhcigpOwogICBsb2dnaW5nLnZsb2coInBhY2th Z2UvbG9nZ2luZy5kIiwgMTEsIDIsIGZhbHNlLCBsb2dnZWRNZXNzYWdlKTsKICAgYXNzZXJ0KGxv Z2dlci5jYWxsZWQpOwogICBhc3NlcnQobG9nZ2VyLmxhc3RMZXZlbCA9PSBMZXZlbC5pbmZvICYm CiAgICAgICAgICBlbmRzV2l0aChsb2dnZXIubGFzdE1zZywgbG9nZ2VkTWVzc2FnZSkpOwoKICAg bG9nZ2VyLmNsZWFyKCk7CiAgIGxvZ2dpbmcudmxvZygicGFja2FnZS9sb2dnaW5nLmQiLCAxMSwg MywgZmFsc2UsIGxvZ2dlZE1lc3NhZ2UpOwogICBhc3NlcnQoIWxvZ2dlci5jYWxsZWQpOwoKICAg bG9nZ2VyLmNsZWFyKCk7CiAgIGxvZ2dpbmcudmxvZygibm90X3RoaXNfZmlsZSIsIDIyLCAwLCBm YWxzZSwgbG9nZ2VkTWVzc2FnZSk7CiAgIGFzc2VydCghbG9nZ2VyLmNhbGxlZCk7IAoKICAgbG9n Z2VyLmNsZWFyKCk7CiAgIGxvZ2dpbmcudmxvZygicGFja2FnZS9sb2dnaW5nLmQiLCAxMSwgMiwg dHJ1ZSwgbG9nZ2VkTWVzc2FnZSk7CiAgIGFzc2VydChsb2dnZXIuY2FsbGVkKTsKICAgYXNzZXJ0 KGxvZ2dlci5sYXN0TGV2ZWwgPT0gTGV2ZWwuaW5mbyAmJgoJICBlbmRzV2l0aChsb2dnZXIubGFz dE1zZywgbG9nZ2VkTWVzc2FnZSkpOwp9Cgpwcml2YXRlIHNoYXJlZCBzdHJ1Y3QgSW50ZXJuYWxM b2dnaW5nCnsKICAgdm9pZCBpbml0KHNoYXJlZChMb2dnZXIpIGRlbGVnYXRlKCkgbG9nQ3JlYXRv ciwKICAgICAgICAgICAgIExvZ0NvbmZpZyBsb2dDb25maWcpCiAgIHsgCiAgICAgIGVuZm9yY2Uo Y2FzKCZfaW5pdGlhbGl6ZWQsIGZhbHNlLCB0cnVlKSk7CgogICAgICBfdkxvZ0NvbmZpZ3MgPSBs b2dDb25maWcuX3ZMb2dDb25maWdzLmlkdXA7CiAgICAgIF9sb2dnZXIgPSBsb2dDcmVhdG9yKCk7 CiAgICAgIF9sZXZlbCA9IGxvZ0NvbmZpZy5fbGV2ZWw7CiAgICAgIF9mYXRhbEhhbmRsZXIgPSAg bG9nQ29uZmlnLl9mYXRhbEhhbmRsZXIgPyAKICAgICAgICAgICAgICAgICAgICAgICBsb2dDb25m aWcuX2ZhdGFsSGFuZGxlciA6CiAgICAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24ge307CiAg IH0KCiAgIHZvaWQgdmxvZyhULi4uKQogICAgICAgICAgICAoc3RyaW5nIGZpbGUsCiAgICAgICAg ICAgICBpbnQgbGluZSwKICAgICAgICAgICAgIHVpbnQgbGV2ZWwsCiAgICAgICAgICAgICBib29s IGZvcm1hdHRlZCwKICAgICAgICAgICAgIGxhenkgVCBhcmdzKQogICBpbgogICB7CiAgICAgIGFz c2VydChfaW5pdGlhbGl6ZWQpOwogICB9CiAgIGJvZHkKICAgewoKICAgICAgaWYobG9nTWF0Y2hl cyhmaWxlLCBsZXZlbCwgX3ZMb2dDb25maWdzKSkKICAgICAgewogICAgICAgICAvLyBUT0RPOiBm aXggY29yZS5UaHJlYWQgc28gdGhhdCBUaHJlYWRBZGRyIGlzIGV4cG9zZQogICAgICAgICBfbG9n Z2VyLmxvZyhMZXZlbC5pbmZvLAogICAgICAgICAgICAgICAgICAgICBmb3JtYXQoZmlsZSwgbGlu ZSwgdG8hc3RyaW5nKGxldmVsKSwgMCwgZm9ybWF0dGVkLCBhcmdzKSk7CiAgICAgIH0KICAgfQoK ICAgdm9pZCBsb2coVC4uLikKICAgICAgICAgICAoc3RyaW5nIGZpbGUsCiAgICAgICAgICAgIGlu dCBsaW5lLAogICAgICAgICAgICBMZXZlbCBsZXZlbCwKICAgICAgICAgICAgYm9vbCBmb3JtYXR0 ZWQsCiAgICAgICAgICAgIGxhenkgVCBhcmdzKQogICBpbgogICB7CiAgICAgIGFzc2VydChfaW5p dGlhbGl6ZWQpOwogICB9CiAgIGJvZHkKICAgewogICAgICBpZihsZXZlbCA8PSBfbGV2ZWwpCiAg ICAgIHsKICAgICAgICAgc2NvcGUoZXhpdCkKICAgICAgICAgewogICAgICAgICAgICBpZihsZXZl bCA9PSBMZXZlbC5mYXRhbCkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAvKwogICAgICAg ICAgICAgICAgKyBUaGUgb3RoZXIgb2YgdGhlIHNjb3BlKGV4aXQpIGlzIGltcG9ydGFudC4gV2Ug d2FudAogICAgICAgICAgICAgICAgKyBfZmF0YWxIYW5kbGVyIHRvIHJ1biBiZWZvcmUgdGhlIGFz c2VydC4KICAgICAgICAgICAgICAgICsvCiAgICAgICAgICAgICAgIHNjb3BlKGV4aXQpIGFzc2Vy dChmYWxzZSk7CiAgICAgICAgICAgICAgIHNjb3BlKGV4aXQpIF9mYXRhbEhhbmRsZXIoKTsKICAg ICAgICAgICAgICAgX2xvZ2dlci5mbHVzaCgpOwogICAgICAgICAgICB9CiAgICAgICAgIH0KCiAg ICAgICAgIC8vIFRPRE86IGZpeCBjb3JlLlRocmVhZCBzbyB0aGF0IFRocmVhZEFkZHIgaXMgZXhw b3NlCiAgICAgICAgIF9sb2dnZXIubG9nKGxldmVsLAogICAgICAgICAgICAgICAgICAgICBmb3Jt YXQoZmlsZSwgbGluZSwgdG8hc3RyaW5nKGxldmVsKSwgMCwgZm9ybWF0dGVkLCBhcmdzKSk7CiAg ICAgIH0KICAgfQoKICAgcHJpdmF0ZSBib29sIF9pbml0aWFsaXplZDsKICAgcHJpdmF0ZSBMb2dn ZXIgX2xvZ2dlcjsKICAgcHJpdmF0ZSBMZXZlbCBfbGV2ZWw7CiAgIHByaXZhdGUgaW1tdXRhYmxl KFZMb2dDb25maWcpW10gX3ZMb2dDb25maWdzOwogICBwcml2YXRlIF9fZ3NoYXJlZCB2b2lkIGZ1 bmN0aW9uKCkgX2ZhdGFsSGFuZGxlcjsKfQoKdW5pdHRlc3QKewogICAvLyBUZXN0IGVxdWFscwog ICBWTG9nQ29uZmlnW10gY29uZmlncyA9IFsgVkxvZ0NvbmZpZygicGFja2FnZS9tb2R1bGUiLAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBWTG9nQ29uZmlnLk1hdGNoaW5n LmVxdWFscywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgMSkgXTsKICAg YXNzZXJ0KGxvZ01hdGNoZXMoInBhY2thZ2UvbW9kdWxlIiwgMSwgY29uZmlncykpOwogICBhc3Nl cnQobG9nTWF0Y2hlcygicGFja2FnZS9tb2R1bGUuZCIsIDEsIGNvbmZpZ3MpKTsKICAgYXNzZXJ0 KGxvZ01hdGNoZXMoInBhY2thZ2UvbW9kdWxlIiwgMCwgY29uZmlncykpOwoKICAgYXNzZXJ0KCFs b2dNYXRjaGVzKCJtb2R1bGUiLCAxLCBjb25maWdzKSk7CiAgIGFzc2VydCghbG9nTWF0Y2hlcygi cGFja2FnZS9tb2R1bGUiLCAyLCBjb25maWdzKSk7CgogICAvLyBUZXN0IHN0YXJ0c1dpdGgKICAg Y29uZmlnc1swXS5fcGF0dGVybiA9ICJwYWNrYWdlIjsKICAgY29uZmlnc1swXS5fbWF0Y2hpbmcg PSBWTG9nQ29uZmlnLk1hdGNoaW5nLnN0YXJ0c1dpdGgsCiAgIGNvbmZpZ3NbMF0uX2xldmVsID0g MTsKICAgYXNzZXJ0KGxvZ01hdGNoZXMoInBhY2thZ2UvbW9kdWxlIiwgMSwgY29uZmlncykpOwog ICBhc3NlcnQobG9nTWF0Y2hlcygicGFja2FnZS9tb2R1bGUuZCIsIDEsIGNvbmZpZ3MpKTsKICAg YXNzZXJ0KGxvZ01hdGNoZXMoInBhY2thZ2UvbW9kdWxlIiwgMCwgY29uZmlncykpOwogICBhc3Nl cnQobG9nTWF0Y2hlcygicGFja2FnZS9hbm90aGVyLmQiLCAxLCBjb25maWdzKSk7CgogICBhc3Nl cnQoIWxvZ01hdGNoZXMoIm1vZHVsZSIsIDEsIGNvbmZpZ3MpKTsKICAgYXNzZXJ0KCFsb2dNYXRj aGVzKCJhbm90aGVyL3BhY2thZ2UvbW9kdWxlIiwgMSwgY29uZmlncykpOwogICBhc3NlcnQoIWxv Z01hdGNoZXMoInBhY2thZ2UvbW9kdWxlLmQiLCAyLCBjb25maWdzKSk7CgogICAvLyBUZXN0IGVu ZHNXaXRoCiAgIGNvbmZpZ3NbMF0uX3BhdHRlcm4gPSAibW9kdWxlIjsKICAgY29uZmlnc1swXS5f bWF0Y2hpbmcgPSBWTG9nQ29uZmlnLk1hdGNoaW5nLmVuZHNXaXRoLAogICBjb25maWdzWzBdLl9s ZXZlbCA9IDE7CiAgIGFzc2VydChsb2dNYXRjaGVzKCJwYWNrYWdlL21vZHVsZSIsIDEsIGNvbmZp Z3MpKTsKICAgYXNzZXJ0KGxvZ01hdGNoZXMoInBhY2thZ2UvbW9kdWxlLmQiLCAxLCBjb25maWdz KSk7CiAgIGFzc2VydChsb2dNYXRjaGVzKCJwYWNrYWdlL21vZHVsZSIsIDAsIGNvbmZpZ3MpKTsK ICAgYXNzZXJ0KGxvZ01hdGNoZXMoIm1vZHVsZSIsIDEsIGNvbmZpZ3MpKTsKCiAgIGFzc2VydCgh bG9nTWF0Y2hlcygiYW5vdGhlciIsIDEsIGNvbmZpZ3MpKTsKICAgYXNzZXJ0KCFsb2dNYXRjaGVz KCJwYWNrYWdlL21vZHVsZSIsIDIsIGNvbmZpZ3MpKTsKfQoKcHJpdmF0ZSBib29sIGxvZ01hdGNo ZXMoc3RyaW5nIGZpbGUsCiAgICAgICAgICAgICAgICAgICAgICAgIHVpbnQgbGV2ZWwsCiAgICAg ICAgICAgICAgICAgICAgICAgIGNvbnN0IFZMb2dDb25maWdbXSBjb25maWdzKQp7CiAgIGZvcmVh Y2goY29uZmlnOyBjb25maWdzKQogICB7CiAgICAgIGlmKGNvbmZpZy5tYXRjaChmaWxlLCBsZXZl bCkpIHJldHVybiB0cnVlOwogICB9CgogICByZXR1cm4gZmFsc2U7Cn0gCgpwcml2YXRlIHN0cmlu ZyBmb3JtYXQoVC4uLikKICAgICAgICAgICAgICAgICAgICAgKHN0cmluZyBmaWxlLAogICAgICAg ICAgICAgICAgICAgICAgaW50IGxpbmUsCiAgICAgICAgICAgICAgICAgICAgICBzdHJpbmcgbGV2 ZWwsCiAgICAgICAgICAgICAgICAgICAgICBpbnQgdGhyZWFkSWQsCiAgICAgICAgICAgICAgICAg ICAgICBib29sIGZvcm1hdFN0cmluZywKICAgICAgICAgICAgICAgICAgICAgIFQgYXJncykKewog ICBhdXRvIHdyaXRlciA9IGFwcGVuZGVyIXN0cmluZygpOwogICBmb3JtYXR0ZWRXcml0ZSh3cml0 ZXIsCiAgICAgICAgICAgICAgICAgICIlczolZDolczolZCAiLAogICAgICAgICAgICAgICAgICBm aWxlLAogICAgICAgICAgICAgICAgICBsaW5lLAogICAgICAgICAgICAgICAgICBsZXZlbCwKICAg ICAgICAgICAgICAgICAgdGhyZWFkSWQpOwogICBpZiAoZm9ybWF0U3RyaW5nKQogICB7CiAgICAg IGZvcm1hdHRlZFdyaXRlKHdyaXRlciwgYXJnc1swXSwgYXJnc1sxIC4uICRdKTsKICAgfQogICBl bHNlCiAgIHsKICAgICAgd3JpdGVyLnB1dCh0ZXh0KGFyZ3MpKTsKICAgfQoKICAgcmV0dXJuIHdy aXRlci5kYXRhOwp9Cgp1bml0dGVzdAp7CiAgIGF1dG8gcmVzdWx0ID0gVkxvZ0NvbmZpZy5jcmVh dGUoIm1vZHVsZT0xLCphbm90aGVyPTMsZXZlbio9MiIpOwogICBhc3NlcnQocmVzdWx0Lmxlbmd0 aCA9PSAzKTsKICAgYXNzZXJ0KHJlc3VsdFswXS5fcGF0dGVybiA9PSAibW9kdWxlIik7CiAgIGFz c2VydChyZXN1bHRbMF0uX21hdGNoaW5nID09IFZMb2dDb25maWcuTWF0Y2hpbmcuZXF1YWxzKTsK ICAgYXNzZXJ0KHJlc3VsdFswXS5fbGV2ZWwgPT0gMSk7CgogICBhc3NlcnQocmVzdWx0WzFdLl9w YXR0ZXJuID09ICJhbm90aGVyIik7CiAgIGFzc2VydChyZXN1bHRbMV0uX21hdGNoaW5nID09IFZM b2dDb25maWcuTWF0Y2hpbmcuZW5kc1dpdGgpOwogICBhc3NlcnQocmVzdWx0WzFdLl9sZXZlbCA9 PSAzKTsKCiAgIGFzc2VydChyZXN1bHRbMl0uX3BhdHRlcm4gPT0gImV2ZW4iKTsKICAgYXNzZXJ0 KHJlc3VsdFsyXS5fbWF0Y2hpbmcgPT0gVkxvZ0NvbmZpZy5NYXRjaGluZy5zdGFydHNXaXRoKTsK ICAgYXNzZXJ0KHJlc3VsdFsyXS5fbGV2ZWwgPT0gMik7CgogICB0cnkKICAgewogICAgICBWTG9n Q29uZmlnLmNyZWF0ZSgibW9kdWxlPTIsIik7CiAgICAgIGFzc2VydChmYWxzZSk7CiAgIH0KICAg Y2F0Y2ggKEV4Y2VwdGlvbiBlKSB7fQoKICAgdHJ5CiAgIHsKICAgICAgVkxvZ0NvbmZpZy5jcmVh dGUoIm1vZHVsZT1hIik7CiAgICAgIGFzc2VydChmYWxzZSk7CiAgIH0KICAgY2F0Y2ggKEV4Y2Vw dGlvbiBlKSB7fQoKICAgdHJ5CiAgIHsKICAgICAgVkxvZ0NvbmZpZy5jcmVhdGUoIm1vZHVsZT0y LGFub3RoZXI9Iik7CiAgICAgIGFzc2VydChmYWxzZSk7CiAgIH0KICAgY2F0Y2ggKEV4Y2VwdGlv biBlKSB7fQoKICAgdHJ5CiAgIHsKICAgICAgVkxvZ0NvbmZpZy5jcmVhdGUoIm1vZHVsZT0yLGFu byp0aGVyPTMiKTsKICAgICAgYXNzZXJ0KGZhbHNlKTsKICAgfQogICBjYXRjaCAoRXhjZXB0aW9u IGUpIHt9CgogICB0cnkKICAgewogICAgICBWTG9nQ29uZmlnLmNyZWF0ZSgibW9kdWxlPTIsKmFu b3RoZXIqPTMiKTsKICAgICAgYXNzZXJ0KGZhbHNlKTsKICAgfQogICBjYXRjaCAoRXhjZXB0aW9u IGUpIHt9Cn0KCi8rKwpTdHJ1Y3R1cmUgZm9yIGNvbmZpZ3VyaW5nIHZlcmJvc2UgbG9nZ2luZy4K ClRoaXMgc3RydWN0dXJlIGlzIHVzZWQgdG8gY29udHJvbCB2ZXJib3NlIGxvZ2dpbmcgb24gYSBw ZXIgbW9kdWxlIGJhc2lzLiBBIHZlcmJvc2UgbWVzc2FnZSB3aXRoIGxldmVsICQoSSB4KSB3aWxs IGdldCBsb2dnZWQgYXQgc2V2ZXJpdHkgbGV2ZWwgTGV2ZWwuaW5mbyBpZiB0aGVyZSBpcyBhIFZM b2dDb25maWcgZW50cnkgdGhhdCBtYXRjaGVzIHRvIHRoZSBzb3VyY2UgZmlsZSBhbmQgdGhlIHZl cmJvc2UgbGV2ZWwgb2YgdGhhdCBlbnRyeSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gJChJ IHgpLgorLwpzdHJ1Y3QgVkxvZ0NvbmZpZwp7CiAgIHByaXZhdGUgZW51bSBNYXRjaGluZwogICB7 CiAgICAgIHN0YXJ0c1dpdGgsCiAgICAgIGVuZHNXaXRoLAogICAgICBlcXVhbHMKICAgfSAKCi8r KwpDcmVhdGVzIGFuIGFycmF5IG9mICQoRCBWTG9nQ29uZmlnKSBiYXNlZCBvbiBhIGNvbmZpZ3Vy YXRpb24gc3RyaW5nLgoKVGhlIGZvcm1hdCBvZiB0aGUgY29uZmlndXJhdGlvbiBzdHJpbmcgaXMg YXMgZm9sbG93ICIkKEIgW3BhdHRlcm5dKT0kKEIgW2xldmVsXSksLi4uIiwgd2hlcmUgJChCIFtw YXR0ZXJuXSkgbWF5IGNvbnRhaW4gYW55IGNoYXJhY3RlciBhbGxvd2VkIGluIGEgZmlsZSBuYW1l IGFuZCAkKEIgW2xldmVsXSkgbXVzdCBiZSBjb252ZXJ0aWJsZSB0byBhbiBwb3NpdGl2ZSBpbnRl Z2VyIChncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gemVybykuIElmICQoQiBbcGF0dGVybl0pIGNv bnRhaW5zIGEgJyonIHRoZW4gaXQgbXVzdCBiZSBhdCB0aGUgc3RhcnQgb3IgdGhlIGVuZC4gSWYg JChCIFtwYXR0ZXJuXSkgZW5kcyB3aXRoIGEgJyonIHRoZW4gaXQgd2lsbCBtYXRjaCBhbnkgc291 cmNlIGZpbGUgbmFtZSB0aGF0IHN0YXJ0cyB3aXRoIHRoZSByZXN0IG9mICQoQiBbcGF0dGVybl0p LiBJZiAkKEIgW3BhdHRlcm5dKSBzdGFydHMgd2l0aCBhICcqJyB0aGVuIGl0IHdpbGwgbWF0Y2gg YW55IHNvdXJjZSBmaWxlIG5hbWUgdGhhdCBlbmRzIHdpdGggYSB0aGUgcmVzdCBvZiAkKEIgW3Bh dHRlcm5dKS4KCkZvciBldmVyeSAkKEIgW3BhdHRlcm5dKT0kKEIgW2xldmVsXSkgaW4gdGhlIGNv bmZpZ3VyYXRpb24gc3RyaW5nIGEgJChEIFZMb2dDb25maWcpIHdpbGwgYmUgY3JlYXRlZCBhbmQg aW5jbHVkZWQgaW4gdGhlIHJldHVybmVkIGFycmF5LgorLwogICBzdGF0aWMgVkxvZ0NvbmZpZ1td IGNyZWF0ZShzdHJpbmcgY29uZmlnKQogICB7CiAgICAgIFZMb2dDb25maWdbXSByZXN1bHQ7CiAg ICAgIGZvcmVhY2goZW50cnk7IHNwbGl0dGVyKGNvbmZpZywgIiwiKSkKICAgICAgewogICAgICAg ICBlbmZvcmNlKGVudHJ5ICE9ICIiKTsKICAgICAgICAgYXV0byBlbnRyeVBhcnRzID0gYXJyYXko c3BsaXR0ZXIoZW50cnksICI9IikpOwogICAgICAgICBlbmZvcmNlKGVudHJ5UGFydHMubGVuZ3Ro ID09IDIpOwoKICAgICAgICAgYXV0byBtb2QgPSBhcnJheShzcGxpdHRlcihlbnRyeVBhcnRzWzBd LCAiKiIpKTsKICAgICAgICAgZW5mb3JjZShtb2QubGVuZ3RoID09IDEgfHwgbW9kLmxlbmd0aCA9 PSAyKTsKICAgICAgICAgCiAgICAgICAgIGlmKG1vZC5sZW5ndGggPT0gMSAmJiBtb2RbMF0gIT0g IiIpCiAgICAgICAgIHsKICAgICAgICAgICAgVkxvZ0NvbmZpZyBsb2dDb25maWcgPSBWTG9nQ29u ZmlnKG1vZFswXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg IE1hdGNoaW5nLmVxdWFscywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHRvIXVpbnQoZW50cnlQYXJ0c1sxXSkpOwogICAgICAgICAgICByZXN1bHQgfj0gbG9n Q29uZmlnOwogICAgICAgICB9CiAgICAgICAgIGVsc2UgaWYobW9kWzBdICE9ICIiICYmIG1vZFsx XSA9PSAiIikKICAgICAgICAgewogICAgICAgICAgICBWTG9nQ29uZmlnIGxvZ0NvbmZpZyA9IFZM b2dDb25maWcobW9kWzBdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgTWF0Y2hpbmcuc3RhcnRzV2l0aCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIHRvIXVpbnQoZW50cnlQYXJ0c1sxXSkpOwogICAgICAgICAgICByZXN1 bHQgfj0gbG9nQ29uZmlnOwogICAgICAgICB9CiAgICAgICAgIGVsc2UgaWYobW9kWzBdID09ICIi ICYmIG1vZFsxXSAhPSAiIikKICAgICAgICAgewogICAgICAgICAgICBWTG9nQ29uZmlnIGxvZ0Nv bmZpZyA9IFZMb2dDb25maWcobW9kWzFdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgTWF0Y2hpbmcuZW5kc1dpdGgsCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICB0byF1aW50KGVudHJ5UGFydHNbMV0pKTsKICAgICAgICAg ICAgcmVzdWx0IH49IGxvZ0NvbmZpZzsKICAgICAgICAgfQogICAgICAgICBlbHNlCiAgICAgICAg IHsKICAgICAgICAgICAgZW5mb3JjZShmYWxzZSk7CiAgICAgICAgIH0KICAgICAgfQoKICAgICAg cmV0dXJuIHJlc3VsdDsKICAgfQoKICAgcHJpdmF0ZSBib29sIG1hdGNoKHN0cmluZyBmaWxlLCB1 aW50IGxldmVsKSBjb25zdAogICB7IAogICAgICBhdXRvIG1hdGNoID0gZmFsc2U7CiAgICAgIC8v IFhYWCBmaWxlIGJ1dCBhZ2FpbnN0IHN0YXJ0V2l0aC9lbmRzV2l0aCBmb3Igbm90IGFsbG93aW5n IGNvbnN0CiAgICAgIGF1dG8gcGF0dGVybiA9IGNhc3Qoc3RyaW5nKSBfcGF0dGVybjsKCiAgICAg IGZpbmFsIHN3aXRjaChfbWF0Y2hpbmcpCiAgICAgIHsKICAgICAgICAgY2FzZSBWTG9nQ29uZmln Lk1hdGNoaW5nLnN0YXJ0c1dpdGg6CiAgICAgICAgICAgIG1hdGNoID0gc3RhcnRzV2l0aChmaWxl LCBwYXR0ZXJuKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWwgPD0gX2xldmVsOyAK ICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgIGNhc2UgVkxvZ0NvbmZpZy5NYXRjaGluZy5lbmRz V2l0aDoKICAgICAgICAgICAgbWF0Y2ggPSAoZW5kc1dpdGgoZmlsZSwgcGF0dGVybikgfHwKICAg ICAgICAgICAgICAgICAgICAgZW5kc1dpdGgoZmlsZSwgcGF0dGVybiB+ICIuZCIpKSAmJiAKICAg ICAgICAgICAgICAgICAgICBsZXZlbCA8PSBfbGV2ZWw7IAogICAgICAgICAgICBicmVhazsKICAg ICAgICAgY2FzZSBWTG9nQ29uZmlnLk1hdGNoaW5nLmVxdWFsczoKICAgICAgICAgICAgbWF0Y2gg PSAoZmlsZSA9PSBwYXR0ZXJuIHx8CiAgICAgICAgICAgICAgICAgICAgIGZpbGUgPT0gcGF0dGVy biB+ICIuZCIpICYmCiAgICAgICAgICAgICAgICAgICAgbGV2ZWwgPD0gX2xldmVsOyAKICAgICAg ICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIHJldHVybiBtYXRjaDsKICAgfQoKICAgcHJpdmF0 ZSB0aGlzKHN0cmluZyBwYXR0ZXJuLCBNYXRjaGluZyBtYXRjaGluZywgdWludCBsZXZlbCkKICAg ewogICAgICBfcGF0dGVybiA9IHBhdHRlcm47CiAgICAgIF9tYXRjaGluZyA9IG1hdGNoaW5nOwog ICAgICBfbGV2ZWwgPSBsZXZlbDsKICAgfQoKICAgcHJpdmF0ZSBzdHJpbmcgX3BhdHRlcm47CiAg IHByaXZhdGUgTWF0Y2hpbmcgX21hdGNoaW5nOwogICBwcml2YXRlIHVpbnQgX2xldmVsOwp9Cgov KysKRXh0ZW5zaW9uIHBvaW50IGZvciB0aGUgbW9kdWxlLgorLwpzaGFyZWQgaW50ZXJmYWNlIExv Z2dlcgp7Ci8rKwpMb2dzIGEgbWVzc2FnZS4KClRoZSBtZXRob2QgaXMgY2FsbGVkIGJ5IHRoZSBs b2dnaW5nIG1vZHVsZSB3aGVuZXZlciBpdCBkZWNpZGVzIHRoYXQgYSBtZXNzYWdlIHNob3VsZCBi ZSBsb2dnZWQuIEl0IGlzIHJlY29tbWVuZCB0aGF0IHRoZSBpbXBsZW1lbnRhdGlvbiBvZiB0aGlz IG1ldGhvZCBkb2Vzbid0IHBlcmZvcm0gYW55IGZpbHRlcmluZyBiYXNlZCBvbiBsZXZlbCBzaW5j ZSBhdCB0aGlzIHBvaW50IGFsbCBjb25maWd1cmVkIGZpbHRlcnMgd2VyZSBhcHBsaWVkLgoKVGhl IG1ldGhvZCBpcyBhbGxvdyB0byByZXR1cm4gaW1tZWRpYXRlbHkgd2l0aG91dCBwZXJzaXN0aW5n IHRoZSBtZXNzYWdlLgorLwogICB2b2lkIGxvZyhMZXZlbCBsZXZlbCwgc3RyaW5nIG1zZyk7Cgov KysKRmx1c2hlcyBwZW5kaW5nIGxvZyBvcGVyYXRpb25zLgoKVGhlIG1ldGhvZCBpcyBjYWxsZWQg YnkgdGhlIGxvZ2dpbmcgZnJhbWV3b3JrIHdoZW5ldmVyIGl0IHJlcXVpcmVzIHRoYXQgdGhlIHBl cnNpc3RlbmNlIG9mIGFsbCBwcmV2aW91cyBsb2cgbWVzc2FnZXMuIEZvciBleGFtcGxlIHRoZSBt ZXRob2QgaXMgY2FsbGVkIHdoZW4gdGhlIGNsaWVudCBsb2dzIGEgZmF0YWwgbWVzc2FnZS4KClRo ZSBtZXRob2QgbXVzdCBub3QgcmV0dXJuIHVudGlsIGFsbCBwZW5kaW5nIGxvZyBvcGVyYXRpb25z IGNvbXBsZXRlLgorLwogICB2b2lkIGZsdXNoKCk7Cn0KCi8rKwpJbXBsZW1lbnRzIGFuIGFjdG9y IGJhc2VkIGxvZ2dpbmcgYmFja2VuZC4KCkxvZyBtZXNzYWdlcyBhcmUgc2VudCB0byBhIGxvZ2dp bmcgdGhyZWFkIHdoaWNoIGlzIHJlc3BvbnNpYmxlIGZvciBwZXJzaXN0aW5nIGxvZyBtZXNzYWdl cy4gTWVzc2FnZXMgb2YgYSBnaXZlbiBzZXZlcml0eSB3aWxsIGJlIHdyaXR0ZW4gaW4gdGhlIGxv ZyBmaWxlIG9mIHRoYXQgc2V2ZXJpdHkgYW5kIGluIHRoZSBsb2cgZmlsZXMgb2YgbG93ZXIgc2V2 ZXJpdHkuIFRoZSBmaWxlIG5hbWVzIG9mIHRoZSBsb2cgZmlsZXMgY3JlYXRlZCB3aWxsIGZvbGxv dyB0aGUgZm9sbG93aW5nIHBhdHRlcm4gIiQoQiBbbmFtZV0pLmxvZy4kKEIgW2xldmVsXSkuJChC IFt0aW1lXSkiLiBUaGUgc3RyaW5nICQoQiBbbmFtZV0pIGlzIHRoZSBwYXJhbWV0ZXIgJChJIG5h bWUpIHBhc3NlZCB0byAkKEQgZ2V0Q3JlYXRvcikuIFRoZSBzdHJpbmcgJChCIFt0aW1lXSkgaXMg dGhlIHRpbWUgd2hlbiB0aGUgbG9nZ2VyIHdhcyBjcmVhdGVkLiBUaGUgc3RyaW5nICQoQiBbbGV2 ZWxdKSBpcyB0aGUgc2V2ZXJpdHkgb2YgdGhlIGxvZyBmaWxlLiBBIGZpbGUgZm9yIHNldmVyaXR5 IGxldmVsICd4JyB3aWxsIGNvbnRhaW4gYWxsIGxvZyBtZXNzYWdlcyBvZiBncmVhdGVyIG9yIGVx dWFsIHNldmVyaXR5LgorLwoKLy8gWFhYIEFsbG93IHN0b3JpbmcgZmlsZSBpbiBhIGRpZmYgZGly Ci8vIFhYWCBBbGxvdyB0aGUgY29uZmlndXJhdGlvbiBvZiB0aGUgbG9nIGZpbGUgbmFtZQpjbGFz cyBBY3RvckxvZ2dlciA6IExvZ2dlcgp7CiAgIHByaXZhdGUgc3RydWN0IEZsdXNoIHt9CgogICBw cml2YXRlIHRoaXMoc3RyaW5nIG5hbWUpCiAgIHsKICAgICAgX2FjdG9yID0gc3Bhd24oJmxvZ2dl ck1haW4sIG5hbWUpOwogICB9CgovKysKUmV0dXJucyBhIGRlbGVnYXRlIGZvciBjcmVhdGluZyBh biBBY3RvckxvZ2dlci4KClRoZSBtZXRob2Qgd2lsbCBhbHdheXMgcmV0dXJuIGEgZGlmZmVyZW50 IGRlbGVnYXRlIGJ1dCBhIGdpdmVuIGRlbGVnYXRlIHdpbGwgYWx3YXlzIHJldHVybiB0aGUgc2Ft ZSAkKEQgQWN0b3JMb2dnZXIpLgoKUGFyYW1zOgogICBuYW1lID0gTmFtZSB0byB1c2Ugd2hlbiBj cmVhdGluZyBsb2cgZmlsZXMKKy8KICAgc3RhdGljIHNoYXJlZChMb2dnZXIpIGRlbGVnYXRlKCkg Z2V0Q3JlYXRvcihzdHJpbmcgbmFtZSkKICAgewogICAgICBzaGFyZWQoTG9nZ2VyKSBjcmVhdG9y KCkKICAgICAgeyAKICAgICAgICAgc3RhdGljIExvZ2dlciBsb2dnZXI7CiAgICAgICAgIGxvZ2dl ciA9IGxvZ2dlciA/IGxvZ2dlciA6IG5ldyBBY3RvckxvZ2dlcihuYW1lKTsKICAgICAgICAgcmV0 dXJuIGNhc3Qoc2hhcmVkKExvZ2dlcikpIGxvZ2dlcjsKICAgICAgfQoKICAgICAgcmV0dXJuICZj cmVhdG9yOwogICB9CgogICBzaGFyZWQgdm9pZCBsb2coTGV2ZWwgbGV2ZWwsIHN0cmluZyBtc2cp CiAgIHsKICAgICAgc2VuZChjYXN0KFRpZCkgX2FjdG9yLCBsZXZlbCwgbXNnKTsKICAgfQoKICAg c2hhcmVkIHZvaWQgZmx1c2goKQogICB7CiAgICAgIHNlbmQoY2FzdChUaWQpIF9hY3RvciwgdGhp c1RpZCwgRmx1c2goKSk7CiAgICAgIHJlY2VpdmVPbmx5IUZsdXNoKCk7CiAgIH0KCiAgIHByaXZh dGUgVGlkIF9hY3RvcjsKfQoKcHJpdmF0ZSB2b2lkIGxvZ2dlck1haW4oc3RyaW5nIG5hbWUpCnsK ICAgYXV0byBsb2dnZXIgPSBuZXcgTXVsdGlGaWxlV3JpdGVyKG5hbWUpOwogICBhdXRvIGRvbmUg PSBmYWxzZTsKCiAgIHZvaWQgbG9nKExldmVsIGxldmVsLCBzdHJpbmcgbWVzc2FnZSkKICAgewog ICAgICBsb2dnZXIubG9nKGxldmVsLCBtZXNzYWdlKTsKICAgfQoKICAgdm9pZCBmbHVzaChUaWQg c2VuZGVyLCBBY3RvckxvZ2dlci5GbHVzaCBmbHVzaCkKICAgewogICAgICBsb2dnZXIuZmx1c2go KTsKICAgICAgc2VuZChzZW5kZXIsIGZsdXNoKTsKICAgfQoKICAgdm9pZCB0ZXJtaW5hdGUoT3du ZXJUZXJtaW5hdGVkIGUpCiAgIHsKICAgICAgZG9uZSA9IHRydWU7CiAgIH0KCiAgIHdoaWxlKCFk b25lKQogICB7CiAgICAgIHJlY2VpdmUoJmxvZywgJmZsdXNoLCAmdGVybWluYXRlKTsKICAgfQp9 Cgp1bml0dGVzdAp7CiAgIHZvaWQgcmVtb3ZlVGVzdExvZ3MoRmlsZVtdIHdyaXRlcnMpCiAgIHsK ICAgICAgZm9yZWFjaChyZWYgd3JpdGVyOyB3cml0ZXJzKQogICAgICB7CiAgICAgICAgIGF1dG8g bmFtZSA9IHdyaXRlci5uYW1lOwogICAgICAgICB3cml0ZXIuY2xvc2UoKTsKICAgICAgICAgcmVt b3ZlKG5hbWUpOwogICAgICB9CiAgIH0KCiAgIGF1dG8gbXNncyA9IFsiZmF0YWwgbWVzc2FnZSIs CiAgICAgICAgICAgICAgICAiZXJyb3IgbWVzc2FnZSIsCiAgICAgICAgICAgICAgICAid2Fybmlu ZyBtZXNzYWdlIiwKICAgICAgICAgICAgICAgICJpbmZvIG1lc3NhZ2UiXTsKCiAgIGF1dG8gbG9n Z2VyID0gbmV3IE11bHRpRmlsZVdyaXRlcigibG9nZ2luZ19sZXZlbF91bml0dGVzdCIpOwogICBz Y29wZShleGl0KSByZW1vdmVUZXN0TG9ncyhsb2dnZXIuX3dyaXRlcnMpOwoKICAgZm9yZWFjaChs ZXZlbDsgRW51bU1lbWJlcnMhTGV2ZWwpCiAgIHsKICAgICAgbG9nZ2VyLmxvZyhsZXZlbCwgbXNn c1tsZXZlbF0pOwogICB9CgogICAvKwogICAgKyBDaGVjayB0aGUgY29udGVudCBvZiB0aGUgZmls ZXM6IGZvciBldmVyeSBmaWxlIGZvciBzZXZlcml0eSBsZXZlbCAneCcKICAgICsgdGhlcmUgc2hv dWxkIGJlIGEgbWVzc2FnZSBmcm9tIGEgc2V2ZXJpdHkgbGV2ZWwgPD0gJ3gnLiAKICAgICsvCiAg IGZvcmVhY2goZmlsZUxldmVsOyBFbnVtTWVtYmVycyFMZXZlbCkKICAgewogICAgICBhdXRvIGZp bGUgPSBGaWxlKGxvZ2dlci5fd3JpdGVyc1tmaWxlTGV2ZWxdLm5hbWUsICJyIik7CiAgICAgIGZv cihhdXRvIGxldmVsID0gTGV2ZWwubWluOyBsZXZlbCA8PSBmaWxlTGV2ZWw7ICsrbGV2ZWwpCiAg ICAgIHsKICAgICAgICAgYXNzZXJ0KGZpbGUucmVhZGxuKCkgPT0gKG1zZ3NbbGV2ZWxdIH4gIlxu IikpOwogICAgICB9CiAgIH0KfQoKcHJpdmF0ZSBjbGFzcyBNdWx0aUZpbGVXcml0ZXIKewogICB0 aGlzKHN0cmluZyBuYW1lKQogICB7CiAgICAgIGF1dG8gdGltZSA9IGNhc3QoRGF0ZVRpbWUpIENs b2NrLmN1cnJUaW1lKCk7CgogICAgICAvLyBDcmVhdGUgZmlsZSBmb3IgZXZlcnkgbGV2ZWwKICAg ICAgZm9yZWFjaChhTGV2ZWw7IEVudW1NZW1iZXJzIUxldmVsKQogICAgICB7CiAgICAgICAgIGF1 dG8gZmlsZW5hbWUgPSB0ZXh0KG5hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIu bG9nLiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFMZXZlbCwKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIi4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1l LnRvSVNPU3RyaW5nKCkpOwogICAgICAgICBfd3JpdGVyc1thTGV2ZWxdID0gRmlsZShmaWxlbmFt ZSwgInciKTsKICAgICAgfQogICB9CgogICB2b2lkIGxvZyhMZXZlbCBsZXZlbCwgc3RyaW5nIG1z ZykKICAgewogICAgICBmb3IoTGV2ZWwgYUxldmVsID0gbGV2ZWw7IGFMZXZlbCA8PSBMZXZlbC5t YXg7ICsrYUxldmVsKQogICAgICB7CiAgICAgICAgIF93cml0ZXJzW2FMZXZlbF0ud3JpdGVsbiht c2cpOwogICAgICB9CiAgIH0KCiAgIHZvaWQgZmx1c2goKSB7fQoKICAgcHJpdmF0ZSBGaWxlW0xl dmVsLm1heCArIDFdIF93cml0ZXJzOwp9CgovK3VuaXR0ZXN0CnsKICAgZmluYWwgY2xhc3MgQnVm ZmVyTW9jawogICB7CiAgICAgIHZvaWQgbG9nKExldmVsIGxldmVsLCBzdHJpbmcgbXNnKQogICAg ICB7CiAgICAgICAgIF9jYWxsZWQgPSB0cnVlOwogICAgICB9CgogICAgICB2b2lkIGZsdXNoKCkK ICAgICAgewogICAgICAgICBfZmx1c2hlZCA9IHRydWU7CiAgICAgIH0KICAgICAgCiAgICAgIHZv aWQgY2xlYXIoKQogICAgICB7CiAgICAgICAgIF9jYWxsZWQgPSBmYWxzZTsKICAgICAgICAgX2Zs dXNoZWQgPSBmYWxzZTsKICAgICAgfQoKICAgICAgYm9vbCBfY2FsbGVkOwogICAgICBib29sIF9m bHVzaGVkOwogICB9CgogICBhdXRvIG1vY2sgPSBuZXcgQnVmZmVyTW9jaygpOwogICBzaXplX3Qg c2l6ZSA9IDEwMjQgKiAxMDI0OwogICBhdXRvIHdyaXRlciA9IG5ldyBCdWZmZXJlZFdyaXRlciht b2NrLCBzaXplKTsKCiAgIC8vIGNoZWNrIHRoYXQgaW50ZXJuYWwgd3JpdGVyIGlzIG5vdCBjYWxs ZWQKICAgbW9jay5jbGVhcigpOwogICB3cml0ZXIubG9nKExldmVsLndhcm5pbmcsICIxMjM0NTY3 ODkwIik7CiAgIGFzc2VydCghbW9jay5fY2FsbGVkKTsKICAgYXNzZXJ0KCFtb2NrLl9mbHVzaGVk KTsKCiAgIC8vIGNoZWNrIHRoYXQgaW50ZXJuYWwgd3JpdGVyIGlzIGNhbGxlZCBidXQgbm90IGZs dXNoZWQKICAgbW9jay5jbGVhcigpOwogICB3cml0ZXIubG9nKExldmVsLndhcm5pbmcsIG5ldyBj aGFyW3NpemVdKTsKICAgYXNzZXJ0KG1vY2suX2NhbGxlZCk7CiAgIGFzc2VydCghbW9jay5fZmx1 c2hlZCk7CgogICAvLyBpZiB0aGVyZSBpcyBubyBkYXRhIGluIHRoZSBidWZmZXIgdGhlbiBvbmx5 IGZsdXNoIHNob3VsZCBiZSBjYWxsZWQKICAgbW9jay5jbGVhcigpOwogICB3cml0ZXIuZmx1c2go KTsKICAgYXNzZXJ0KCFtb2NrLl9jYWxsZWQpOwogICBhc3NlcnQobW9jay5fZmx1c2hlZCgpKTsK CiAgIC8vIGNoZWNrIHRoYXQgaW50ZXJuYWwgd3JpdGVyIGlzIG5vdCBjYWxsZWQKICAgbW9jay5j bGVhcigpOwogICB3cml0ZXIubG9nKExldmVsLndhcm5pbmcsICIxMjM0NTY3ODkwIik7CiAgIGFz c2VydCghbW9jay5fY2FsbGVkKTsKICAgYXNzZXJ0KCFtb2NrLl9mbHVzaGVkKTsKCiAgIC8vIGRh dGEgaW4gdGhlIGJ1ZmZlciBib3RoIGxvZyBhbmQgZmx1c2ggc2hvdWxkIGdldCBjYWxsZWQgd2hl biBmbHVzaGVkCiAgIG1vY2suY2xlYXIoKTsKICAgd3JpdGVyLmZsdXNoKCk7CiAgIGFzc2VydCht b2NrLl9jYWxsZWQpOwogICBhc3NlcnQobW9jay5fZmx1c2hlZCk7Cn0KCnByaXZhdGUgZmluYWwg Y2xhc3MgQnVmZmVyZWRXcml0ZXIoTG9nV3JpdGVyKQogICBpZihpc0xvZ1dyaXRlcihMb2dXcml0 ZXIpKQp7CiAgIHByaXZhdGUgc3RydWN0IExpbmUKICAgewogICAgICBwcml2YXRlIExldmVsIF9s ZXZlbDsKICAgICAgcHJpdmF0ZSBzdHJpbmcgX21lc3NhZ2U7CiAgIH0KCiAgIHRoaXMoTG9nV3Jp dGVyIHdyaXRlciwgc2l6ZV90IGJ1ZmZlclNpemUgPSAxMDI0ICogMTAyNCkKICAgewogICAgICBf d3JpdGVyID0gd3JpdGVyOwogICAgICBfYnVmZmVyU2l6ZSA9IGJ1ZmZlclNpemU7CiAgIH0KCiAg IHZvaWQgbG9nKExldmVsIGxldmVsLCBzdHJpbmcgbXNnKQogICB7CiAgICAgIC8vIGlmIHRoZXJl IGlzIGVub3VnaCBzcGFjZSB0aGVuIGJ1ZmZlciB0aGUgbWVzc2FnZQogICAgICAvLyBlbHNlIHdy aXRlIHRoZSBidWZmZXIgYW5kIHRoZSBtZXNzYWdlCiAgIH0KCiAgIHZvaWQgZmx1c2goKQogICB7 CiAgICAgIC8vIHdyaXRlIHRoZSBidWZmZXIKICAgfQoKICAgcHJpdmF0ZSBMb2dXcml0ZXIgX3dy aXRlcjsKICAgcHJpdmF0ZSBzaXplX3QgX2J1ZmZlclNpemU7Cn0rLwoKcHJpdmF0ZSBzaGFyZWQg SW50ZXJuYWxMb2dnaW5nIF9pbnRlcm5hbDsK --bcaec547c9956f2d5f04a2b5a8f8--
May 07 2011
parent 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
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 next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--0016e68ef4334f1e7b04a2b6ac46
Content-Type: text/plain; charset=ISO-8859-1

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. --0016e68ef4334f1e7b04a2b6ac46 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Sat, May 7, 2011 at 4:17 PM, Jose Armando Gar= cia <span dir=3D"ltr">&lt;<a href=3D"mailto:jsancio gmail.com">jsancio gmai= l.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"m= argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div class=3D"im">Hey folks,<br> <br> For the past couple of days I took the liberty of partially<br> implementing a logging module for D. I say partially because all the<br> features that I want to implement are not currently implement. You<br> should really look at the implementation more as a proof of concept<br> even thought most of the code will be used in the final<br> implementation.<br> <br> That been said I am really interested in getting some feedback on the<br> API. That includes high-level design (e.g. using a thread to perform<br> logging. On that note I am planning to also have a shared memory<br> implementation), interfaces and the documentation.<br> <br> When making comment be aware that the design goals of the module are:<br> 1) Provide a logging mechanism that is easy to use in the common case.<br> 2) The module should allow for as much configuration as possible at<br> compile time and execution time without breaking design goal 1.<br> 3) It should be possible to extend or replace the backend without<br> breaking the semantic exposed by the API.<br> <br> I am fairly new to the D language so any comment on how I can take<br> advantage of D idiom or D features in the API or implementation would<br> be greatly appreciated.<br> <br> My intent, and hopefully we will get there with your help, is to<br> include this in Phobos for D2.<br> <br> </div>logging.d - <a href=3D"http://ubuntuone.com/p/rfL/" target=3D"_blank"=
http://ubuntuone.com/p/rfL/</a><br>

tp://ubuntuone.com/p/rfM/</a><br> <div class=3D"im"><br> Thanks,<br> -Jose<br></div></blockquote><div><br></div><div><br></div><div>I&#39;ll be = sure to try it out in the next few days. Passing messages to a separate log= ging 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.</div> <div>One thing I&#39;ll miss from Log4J and its siblings is that typing <a = href=3D"http://log.info">log.info</a>(&quot;message&quot;) is a lot more in= tuitive than log(LogLevel.info, &quot;message&quot;). I don&#39;t think tha= t&#39;s a major gripe though.</div> </div> --0016e68ef4334f1e7b04a2b6ac46--
May 07 2011
prev sibling next sibling parent 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=

 good reason that I didn't foresee, I'd much rather just keep things like
 logging simple and stupid.

May 07 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
--0016e6d260a8aaa13704a2bff47a
Content-Type: text/plain; charset=ISO-8859-1

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. --0016e6d260a8aaa13704a2bff47a Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Sat, May 7, 2011 at 11:03 PM, dsimcha <span d= ir=3D"ltr">&lt;<a href=3D"mailto:dsimcha yahoo.com">dsimcha yahoo.com</a>&g= t;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0= .8ex;border-left:1px #ccc solid;padding-left:1ex;"> Ok, there&#39;s clearly been some misunderstanding here. =A0My real point w= as, why do you need this threading at all?</blockquote><div><br></div><div>= It&#39;s definitely overkill for a single threaded application, but for thi= ngs like the application I&#39;m working on, which is multithreaded and alr= eady uses message passing between threads, I think it would fit in quite ni= cely.</div> <div>My question would be whether it&#39;s pluggable enough to allow the si= mple case of a single threaded program that doesn&#39;t need message passin= g to be implemented.</div></div> --0016e6d260a8aaa13704a2bff47a--
May 08 2011
prev sibling next sibling parent 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=

 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=




 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=



 a
 good reason that I didn't foresee, I'd much rather just keep things lik=



 logging simple and stupid.



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=


 why do you need this threading at all?

It's definitely overkill for a single threaded application, but for thing=

 like the application I'm working on, which is multithreaded and already u=

 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=

 of a single threaded program that doesn't need message passing to be
 implemented.

May 08 2011
prev sibling next sibling parent 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
prev sibling next sibling parent 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.

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
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/9/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:
 One possibility is to provide a nice2ugly template that transforms C#
 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 next sibling 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 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 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 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 next sibling parent 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
prev sibling next 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 "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
prev sibling next sibling 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 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=

 nobody wants their work to go to waste, and in particular I think I'd har=

 the community's interests by working on redundant stuff when so many othe=

 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 =

 and because I figured nobody would implement it the way I thought it need=

 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 =

 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 =

 artifact.

 Right now the two APIs are converging and start differing in minor detail=

 which makes it painfully obvious that at the end of the day two people ar=

 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=

 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=

 the log subsystem pick its parameters. Don't use a delegate unless you ca=

 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=

 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=

 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=

 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=

 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 =

 for it outside logging. (That doesn't mean there isn't any, it just means=

 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=

 * Define "after" in addition to "every" and "first", and overload them al=

 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
prev sibling next sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
--bcaec548a40dfe509d04a4596714
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

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=

 nobody wants their work to go to waste, and in particular I think I'd har=

 the community's interests by working on redundant stuff when so many othe=

 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 =

 and because I figured nobody would implement it the way I thought it need=

 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 =

 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 =

 artifact.

 Right now the two APIs are converging and start differing in minor detail=

 which makes it painfully obvious that at the end of the day two people ar=

 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=

 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=

 the log subsystem pick its parameters. Don't use a delegate unless you ca=

 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=

 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=

 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=

 initLogging(args[0 .. 1]).

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

 * The names LOGGING_FATAL_DISABLED etc. are gratuitous departures from gl=

 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 =

 for it outside logging. (That doesn't mean there isn't any, it just means=

 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=


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=

 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

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.

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

class. Didn't see the need to use polymorphism but I could be wrong...
 * Call your proposal std.log :o).

 Thanks,

 Andrei

--bcaec548a40dfe509d04a4596714 Content-Type: application/octet-stream; name="druntime.patch" Content-Disposition: attachment; filename="druntime.patch" Content-Transfer-Encoding: base64 X-Attachment-Id: f_go8u59i10 ZGlmZiAtLWdpdCBhL3NyYy9jb3JlL3RocmVhZC5kIGIvc3JjL2NvcmUvdGhyZWFkLmQKaW5kZXgg Mzg4YzEzOS4uNWI0NDkzZiAxMDA2NDQKLS0tIGEvc3JjL2NvcmUvdGhyZWFkLmQKKysrIGIvc3Jj L2NvcmUvdGhyZWFkLmQKQEAgLTk4MCw2ICs5ODAsMjAgQEAgY2xhc3MgVGhyZWFkCiAgICAgICAg IH0KICAgICB9CiAKKyAgICAvKioKKyAgICAgKiBPcGFxdWUgdHlwZSBmb3IgdGhlIHN5c3RlbS1s ZXZlbCB0aHJlYWQgaWRlbnRpZmllcgorICAgICAqLworICAgIHZlcnNpb24oIFdpbmRvd3MgKSBh bGlhcyB1aW50IFRocmVhZEFkZHI7CisgICAgZWxzZSB2ZXJzaW9uKCBQb3NpeCApIGFsaWFzIHB0 aHJlYWRfdCBUaHJlYWRBZGRyOworCisgICAgLyoqCisgICAgICogU3lzdGVtLWxldmVsIHRocmVh ZCBpZGVudGlmaWVyCisgICAgICovCisgICAgZmluYWwgQHByb3BlcnR5IFRocmVhZEFkZHIgdGhy ZWFkSWQoKQorICAgIHsKKyAgICAgICByZXR1cm4gbV9hZGRyOworICAgIH0KKwogCiAgICAgLy8v Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8v Ly8vLy8vLy8vLy8vLy8vCiAgICAgLy8gVGhyZWFkIFByaW9yaXR5IEFjdGlvbnMKQEAgLTEzOTMs MTIgKzE0MDcsMTAgQEAgcHJpdmF0ZToKICAgICB2ZXJzaW9uKCBXaW5kb3dzICkKICAgICB7CiAg ICAgICAgIGFsaWFzIHVpbnQgVExTS2V5OwotICAgICAgICBhbGlhcyB1aW50IFRocmVhZEFkZHI7 CiAgICAgfQogICAgIGVsc2UgdmVyc2lvbiggUG9zaXggKQogICAgIHsKICAgICAgICAgYWxpYXMg cHRocmVhZF9rZXlfdCBUTFNLZXk7Ci0gICAgICAgIGFsaWFzIHB0aHJlYWRfdCAgICAgVGhyZWFk QWRkcjsKICAgICB9CiAKIAo= --bcaec548a40dfe509d04a4596714--
May 28 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Clever use of __FILE__ and __LINE__ to create unique instantiations of
the every() template. :)
May 28 2011
prev sibling parent 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
prev sibling next sibling parent 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
prev sibling next sibling 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 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 =


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


 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 =


 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 =


 want to.

Thanks! In fact, the command-line arguments are needed for =

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
prev sibling next sibling parent 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
prev sibling next sibling 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 next sibling parent 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
prev sibling next sibling parent 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 documentation says: "If log­ging is ef­fected with­out hav­ing called this func­tion, all pa­ra­me­ters are at their de­fault val­ues and all log­ging 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.

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

Depends on the app. I desire logs for my server to be sent over a socket to a centralized aggregator. But then I've got, um, well, a _lot_ of servers.
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>  



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