digitalmars.D - Implementing std.log
- Robert Clipsham (14/14) Apr 20 2011 Hey folks,
- Andrei Alexandrescu (9/20) Apr 20 2011 Generally, I think a good logging library should:
- Sean Kelly (4/18) Apr 20 2011 It does so using macros and IOStreams though. Or is there a =
- Andrei Alexandrescu (3/19) Apr 20 2011 The interface would of course be adapted to D.
- so (5/22) Apr 20 2011 Probably the reason is that until now there wasn't a way to make printf ...
- Denis Koroskin (19/30) Apr 20 2011 For me, Logger needs to be simple but feature complete. Here is my ideal...
- so (5/11) Apr 20 2011 Fine if you remove the first line, switching the output is something we ...
- Denis Koroskin (11/23) Apr 21 2011 Having different loggers for different parts of programs (e.g. separate ...
- Jens Mueller (7/37) Apr 21 2011 This can be solved by taking the compilation unit into account. I.e.
- Denis Koroskin (4/42) Apr 21 2011 That could work, I guess. Either way, one line of code is that much of a...
- Jacob Carlborg (11/36) Apr 21 2011 "log" could be a default instance of a class or struct (Logger for
- so (4/29) Apr 21 2011 So you want the iostream way, global logger objects, otherwise i don't s...
- Denis Koroskin (4/38) Apr 21 2011 No globals, of course, loggers are part of objects. In most cases,
- so (37/42) Apr 21 2011 class A {
- Andrei Alexandrescu (8/21) Apr 21 2011 [snip]
- Kagamin (2/15) Apr 21 2011 If you parameterize logger with just a class name, that's not enough. lo...
- David Nadlinger (4/5) Apr 20 2011 You might want to have a look at SLF4J and Logback, which were written
- Dmitry Olshansky (6/17) Apr 20 2011 Actually we have a lurking proposal (with implementation, though I
- Zz (5/22) Apr 22 2011 I currently use the logger written by Masahiro Nakagawa and it has handl...
- Sean Cavanaugh (5/16) Apr 24 2011 I just wanted to mention Pantheios as a C++ logging system to take look
- Andrei Alexandrescu (4/23) Apr 24 2011 I think Pantheios is an example of library design gone bad. It is
- Jose Armando Garcia (26/53) May 07 2011 Hey folks,
- Andrei Alexandrescu (19/22) May 08 2011 [snip]
- Jacob Carlborg (8/32) May 09 2011 Isn't the name of the log file a little too verbose? Don't know if I'm
- Andrei Alexandrescu (9/14) May 09 2011 I did what glog does. Going forward, there is a private static string
- Jacob Carlborg (6/20) May 09 2011 Excuse me for asking again but to me it seems that the log functions
- Andrei Alexandrescu (11/31) May 09 2011 No, log files are created and opened only once, and the time in the
- Jacob Carlborg (8/22) May 09 2011 I don't think the positional parameters are odd (C# has them with
- Andrei Alexandrescu (4/26) May 09 2011 I used the Posix positional format syntax, see
- Andrej Mitrovic (9/9) May 09 2011 I'm not a big fan of that format syntax. It's just hard to look at and
- Robert Clipsham (5/14) May 09 2011 That is A LOT nicer to look at. Please can we have this? :<
- Jacob Carlborg (4/17) May 09 2011 I like it as well, the same syntax used by C# and Tango.
- Andrei Alexandrescu (12/25) May 09 2011 I, too, prefer it a great deal to the prinf/scanf format, and it
- Robert Clipsham (9/22) May 09 2011 Compilation switch maybe? Support both by default, compile with
- Andrej Mitrovic (3/6) May 09 2011 That is exactly what my echo function does. It replaces {} syntax with
- Jacob Carlborg (4/31) May 09 2011 Ok, I see.
- Jacob Carlborg (14/38) May 09 2011 I assume the "initLogging" function needs the application command line
- Andrei Alexandrescu (11/22) May 09 2011 Thanks! In fact, the command-line arguments are needed for considerably
- Sean Kelly (12/29) May 09 2011 I
- Jacob Carlborg (4/23) May 09 2011 Ah, you're right.
- Jacob Carlborg (5/30) May 09 2011 Yes, but since it requires you to pass an array I assumed the
- Andrei Alexandrescu (30/39) May 09 2011 I looked over the code, it's quite nice and clean. If you or anyone else...
- Jacob Carlborg (10/52) May 09 2011 Ok.
- Andrei Alexandrescu (9/42) May 09 2011 The static if actually refers to the next point, which implies that
- Jacob Carlborg (11/54) May 10 2011 Are you referring to core.runtime.Runtime.args? That is not completely
- Andrei Alexandrescu (6/66) May 10 2011 I see. I'll defer ultimate decision on adding getProcessPath to Sean and...
- Jacob Carlborg (4/77) May 10 2011 Well, I only brought it up because I didn't know about Runtime.args.
- Jacob Carlborg (4/21) May 11 2011 Sean, Walter, is this worth including?
- Sean Kelly (2/21) May 11 2011 Yes. Not sure where it should live though.
- Andrei Alexandrescu (7/28) May 11 2011 http://d-programming-language.org/phobos/std_process.html
- Jacob Carlborg (5/39) May 12 2011 I'll do this as soon as I can find the time, although it's not on the
- Robert Clipsham (12/36) May 09 2011 The example looks great, exactly what I'd hope for in the way of a
- Robert Clipsham (10/18) May 09 2011 One more question:
- Andrei Alexandrescu (6/23) May 09 2011 I thought I'd leave that to format(), but probably it's worth just
- Andrei Alexandrescu (19/59) May 09 2011 Passing -version=strip_log_error during compilation strips all error,
- Jens Mueller (14/43) May 09 2011 I think every() behaves strangely. Because the counter is per function.
- Andrei Alexandrescu (11/23) May 10 2011 Actually, they behave correctly. The counters for every and everyMs are
- Jens Mueller (9/36) May 11 2011 Oh yes. Now I see. I missed the template arguments. Sorry. Now I also
- dsimcha (4/11) May 11 2011 I noticed this was recently checked into Phobos. What's its status? Is...
- Andrei Alexandrescu (8/20) May 11 2011 Ouch. Pushing to Phobos is a mistake, I meant to only push it to my own
- Andrei Alexandrescu (7/28) May 11 2011 I removed std.log from Phobos. I left in support for positional
- Andrei Alexandrescu (13/13) May 14 2011 On 5/9/11 1:52 AM, Andrei Alexandrescu wrote:
- dsimcha (5/18) May 14 2011 Overall, I like this library a lot. One comment, though, is that the
- Andrei Alexandrescu (3/30) May 14 2011 Logs will be thread-shared. I haven't seen a need for thread-local logs.
- Jonathan M Davis (24/55) May 14 2011 I've dealt with code before where it was critical to know which log mess...
- Andrei Alexandrescu (5/39) May 14 2011 Just like glog, std.log outputs the thread ID for each log line. See the...
- Jonathan M Davis (11/54) May 14 2011 Ah, good to know. I haven't a had chance to look at it yet, and I'd neve...
- Michel Fortin (14/22) May 14 2011 I'd even go further and question whether it makes sense to have info,
- Andrej Mitrovic (1/1) May 14 2011 Your post just went asian on me. http://i.imgur.com/solwD.png
- Jonathan M Davis (8/21) May 14 2011 I'd definitely vote for them all to be in the same file, but I don't gen...
- Andrei Alexandrescu (8/28) May 14 2011 The info log contains log messages for all levels.
- Michel Fortin (9/22) May 14 2011 That's better then, even though it's not very obvious. Perhaps it
- Andrei Alexandrescu (10/33) May 14 2011 http://d-programming-language.org/phobos-prerelease/std_log.html
- Jonathan M Davis (10/41) May 14 2011 If it's based on glog, it makes sense for it to generally stick to what ...
- Jacob Carlborg (9/44) May 15 2011 Why not? It doesn't say anywhere in the documentation, as far as I can
- Andrei Alexandrescu (16/66) May 15 2011 That's beside the point as the documentation could and should be
- Jonathan M Davis (17/88) May 15 2011 I think that it makes good sense to start with an API based on an existi...
- Jacob Carlborg (9/97) May 17 2011 I agree with Jonathan, if glog is good enough we can follow its design
- Andrei Alexandrescu (11/34) May 14 2011 A server app must log to files, no question about that. We'll need to
- Michel Fortin (21/40) May 14 2011 No question about that.
- Andrei Alexandrescu (4/24) May 14 2011 In fact it may as well be the case that logging is for servers first.
- Brad Roberts (3/33) May 14 2011 Depends on the app. I desire logs for my server to be sent over a socke...
- Andrei Alexandrescu (3/36) May 14 2011 We'll need to provide socket streaming support.
- Jens Mueller (16/54) May 15 2011 ch
- Andrei Alexandrescu (8/58) May 15 2011 The way the Google flags library does that is by planting registration
- Robert Clipsham (7/20) May 14 2011 I far prefered log.xyz to logXyz... The latter just looks ugly in my
- Andrei Alexandrescu (10/37) May 14 2011 There are a few problems with log.xyz. For one, std.log.log.info is
- Robert Clipsham (7/44) May 14 2011 In which case, wouldn't xyz alone be better? Then you have std.log.info,...
- Jacob Carlborg (7/45) May 15 2011 The obvious solution would be to have the logging functions returning an...
- Andrei Alexandrescu (6/17) May 15 2011 No need to be ironic. Interfaces are the obvious solution, and what I
- Jacob Carlborg (5/24) May 17 2011 It wasn't my intention to be ironic. I missed "indirection" and just
- Michel Fortin (8/17) May 14 2011 Shouldn't "everyMs" and "afterMs" accept any of core.time's duration
- Jonathan M Davis (13/28) May 14 2011 I'd vote for that. Then again, I'm tempted to argue that we shouldn't ha...
- Andrei Alexandrescu (4/17) May 14 2011 Great idea. Then we can actually overload every() and after().
- Jonathan M Davis (34/51) May 14 2011 A minor note on efficiency. You're currently calling hour, minute, secon...
- Jacob Carlborg (12/25) May 15 2011 Why does the user have to manually initialize the library? Why not use a...
- Robert Clipsham (5/37) May 15 2011 Agreed.
- Lars T. Kyllingstad (3/36) May 22 2011 I agree with this.
- so (8/21) May 22 2011 I overall like the library, thanks for the work!
- Jacob Carlborg (12/25) May 15 2011 How about an API that looks something like this:
- Andrei Alexandrescu (56/88) May 15 2011 Thanks for your work.
- Jacob Carlborg (18/73) May 17 2011 Note that my suggestion was just a simple and incomplete suggestion on
- Andrei Alexandrescu (10/33) May 17 2011 [snip]
- Jacob Carlborg (4/38) May 18 2011 No hard feelings, I also have a tendency to just give negative feedback.
- Jose Armando Garcia (38/84) May 18 2011 std.logging is still alive! After posting my first attempt at a
- Andrei Alexandrescu (92/100) May 18 2011 Clearly there are advantages to competing proposals, but I have mixed
- Jens Mueller (38/170) May 19 2011 Yeah. If two proposals converge to one it makes no sense anymore. But I
- Andrei Alexandrescu (3/11) May 19 2011 It was Jacob. Apologies to both.
- Jose Armando Garcia (32/133) May 24 2011 Just wanted to let everyone know that I am working on having a review
- Johannes Pfau (6/15) May 24 2011 I think the review process is meant to be similar to the boost review
- Jose Armando Garcia (54/155) May 28 2011 The implementation and documentation for std.log is ready for viewing.
- Andrej Mitrovic (2/2) May 28 2011 Clever use of __FILE__ and __LINE__ to create unique instantiations of
- Daniel Gibson (3/5) May 28 2011 does this belong in this thread?
- Andrej Mitrovic (2/6) May 28 2011 I was just commenting the implementation.
- Daniel Gibson (3/10) May 28 2011 Ah ok. I just remembered every from another thread (where using __LINE__...
- Jonathan M Davis (4/18) May 28 2011 I'd suggest starting a new thread on it or it's likely that a lot of peo...
- Jose Armando Garcia (32/119) May 18 2011 This is a review of std.log. Overall, I really like the API exposed by
- Jonas Drewsen (8/19) May 16 2011 I like it!
- Jens Mueller (28/45) May 16 2011 I started to test it out.
- Walter Bright (6/8) May 09 2011 Thanks for doing the hard work of designing and laying out an implementa...
- Jose Armando Garcia (3/13) May 10 2011 Thanks! Will do.
- Jose Armando Garcia (28/55) May 07 2011 Hey folks,
- Andrew Wiley (8/34) May 07 2011 I'll be sure to try it out in the next few days. Passing messages to a
- dsimcha (5/8) May 07 2011 Can you explain why you did this? I admittedly don't know much about
- Jose Armando Garcia (12/21) May 07 2011 "Eat your own dog food". D goes to great extend to discourage memory
- dsimcha (3/25) May 07 2011 Ok, there's clearly been some misunderstanding here. My real point was,...
- Andrew Wiley (7/9) May 08 2011 It's definitely overkill for a single threaded application, but for thin...
- Jonathan M Davis (10/20) May 08 2011 Honestly, I would hope that whatever the logging did with threads would ...
- Jose Armando Garcia (9/40) May 08 2011 I am not sure I follow. Writing to disk is slower than writing to
- dsimcha (4/8) May 08 2011 I thought that might be the reason. Makes sense if you have so much
- Jonathan M Davis (14/23) May 08 2011 They do at least some of the time. Constructing strings to log can be sl...
- Michel Fortin (9/33) May 08 2011 True. But on the other hand, if your program crashes, you lost the most
- Jonathan M Davis (11/43) May 08 2011 Oh, I'm not claiming that using a separate thread is the best way to do
- Jose Armando Garcia (15/25) May 08 2011 Yes. The current implementation doesn't support this because share
- Jose Armando Garcia (14/34) May 08 2011 Good point and I agree that most users don't care and just want it to
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
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
On Apr 20, 2011, at 9:23 AM, Andrei Alexandrescu wrote:=20 Generally, I think a good logging library should: =20 - be small and simple to use =20 - allow defining arbitrary backends =20 - allow switching backends dynamically =20 - offer compile-time control, including zero overhead "all logging =off"=20 - offer run-time control =20 I favor glog, which fulfills all of the above.It does so using macros and IOStreams though. Or is there a = printf-style interface I didn't see?=
Apr 20 2011
On 4/20/11 11:35 AM, Sean Kelly wrote:On Apr 20, 2011, at 9:23 AM, Andrei Alexandrescu wrote:The interface would of course be adapted to D. AndreiGenerally, 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?
Apr 20 2011
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: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.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?
Apr 20 2011
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
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
On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> 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");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 21 2011
Denis Koroskin wrote:On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote: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 JensHaving 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");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 21 2011
On Thu, 21 Apr 2011 16:58:17 +0400, Jens Mueller <jens.k.mueller gmx.de> wrote:Denis Koroskin wrote:That could work, I guess. Either way, one line of code is that much of a difference, I believe.On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote: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 JensHaving 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");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 21 2011
On 2011-04-21 14:37, Denis Koroskin wrote:On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:"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 CarlborgHaving 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");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 21 2011
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:So you want the iostream way, global logger objects, otherwise i don't see how this solves the problem you are suggesting.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");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 21 2011
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: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.On Thu, 21 Apr 2011 01:34:29 +0400, so <so so.com> wrote:So you want the iostream way, global logger objects, otherwise i don't see how this solves the problem you are suggesting.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");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 21 2011
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(...); }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
On 4/21/11 11:53 AM, so wrote:[snip] Again, I'd _much_ rather prefer if someone just implemented this: http://google-glog.googlecode.com/svn/trunk/doc/glog.html It's simple, to the point, and brings the bacon home. In fact I'm putting dibs on this. I'll implement the thing and make a proposal. Andreiclass A { logger log; } class B { A a; logger log; }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
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
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
On 20.04.2011 20:09, Robert Clipsham wrote:Hey folks, I've just finished porting my web framework from D1/Tango to D2/Phobos, and in the transition lost logging functionality. As I'll be writing a logging library anyway, I wondered if there'd be interest in a std.log? If so, is there a current logging library we would like it to be based on, or should we design from scratch? I know there has been discussion about Google's http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another candidate may be http://logging.apache.org/log4j/ . Do we want a comprehensive logging library, or just the basics? (Possibly with some method for extension if needed).Actually we have a lurking proposal (with implementation, though I haven't check it): http://d.puremagic.com/issues/show_bug.cgi?id=5329 -- Dmitry Olshansky
Apr 20 2011
I currently use the logger written by Masahiro Nakagawa and it has handled what I need. You can get it from: http://www.bitbucket.org/repeatedly/scrap/src/tip/logger.d Zz Robert Clipsham Wrote:Hey folks, I've just finished porting my web framework from D1/Tango to D2/Phobos, and in the transition lost logging functionality. As I'll be writing a logging library anyway, I wondered if there'd be interest in a std.log? If so, is there a current logging library we would like it to be based on, or should we design from scratch? I know there has been discussion about Google's http://google-glog.googlecode.com/svn/trunk/doc/glog.html and another candidate may be http://logging.apache.org/log4j/ . Do we want a comprehensive logging library, or just the basics? (Possibly with some method for extension if needed). -- Robert http://octarineparrot.com/
Apr 22 2011
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
On 04/24/2011 02:23 PM, Sean Cavanaugh wrote:On 4/20/2011 11:09 AM, Robert Clipsham wrote:I think Pantheios is an example of library design gone bad. It is fascinatingly overengineered. AndreiHey 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
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:I think Pantheios is an example of library design gone bad. It is fascinatingly overengineered. AndreiHey 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.
May 07 2011
On 5/7/11 3:43 PM, Jose Armando Garcia wrote:Hey folks, For the past couple of days I took the liberty of partially implementing a logging module for D.[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
May 08 2011
On 2011-05-09 08:52, Andrei Alexandrescu wrote:On 5/7/11 3:43 PM, Jose Armando Garcia 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. -- /Jacob CarlborgHey folks, For the past couple of days I took the liberty of partially implementing a logging module for D.[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
May 09 2011
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
On 2011-05-09 17:49, Andrei Alexandrescu wrote:On 5/9/11 10:37 AM, Jacob Carlborg wrote: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 CarlborgIsn'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
On 5/9/11 12:10 PM, Jacob Carlborg wrote:On 2011-05-09 17:49, Andrei Alexandrescu wrote: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. AndreiOn 5/9/11 10:37 AM, Jacob Carlborg wrote: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?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
On 2011-05-09 17:49, Andrei Alexandrescu wrote:On 5/9/11 10:37 AM, Jacob Carlborg wrote: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 CarlborgIsn'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
On 5/9/11 12:14 PM, Jacob Carlborg wrote:On 2011-05-09 17:49, Andrei Alexandrescu wrote:I used the Posix positional format syntax, see http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html. AndreiOn 5/9/11 10:37 AM, Jacob Carlborg wrote: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.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
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
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
On 2011-05-09 20:34, Robert Clipsham wrote:On 09/05/2011 19:18, Andrej Mitrovic wrote:-- /Jacob CarlborgI'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? :<
May 09 2011
On 5/9/11 1:34 PM, Robert Clipsham wrote:On 09/05/2011 19:18, Andrej Mitrovic wrote:I, too, prefer it a great deal to the prinf/scanf format, and it wouldn't be difficult to implement, but at this point we need to worry about compatibility issues and such (TDPL already uses the % syntax as does existing D code). I don't see a simple migration path. format strings into % format strings, e.g. nice2ugly!"{1}:{2}" yields the string constant "%1$s:%2$s". By and large this doesn't seem to be a very worrisome issue as formatting strings are a minority in most applications and are seldom maintained. You pay attention, get them right, and then just use them. AndreiI'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? :<
May 09 2011
On 09/05/2011 20:47, Andrei Alexandrescu wrote:On 5/9/11 1:34 PM, Robert Clipsham wrote: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/That is A LOT nicer to look at. Please can we have this? :<I, too, prefer it a great deal to the prinf/scanf format, and it wouldn't be difficult to implement, but at this point we need to worry about compatibility issues and such (TDPL already uses the % syntax as does existing D code). I don't see a simple migration path. format strings into % format strings, e.g. nice2ugly!"{1}:{2}" yields the string constant "%1$s:%2$s". By and large this doesn't seem to be a very worrisome issue as formatting strings are a minority in most applications and are seldom maintained. You pay attention, get them right, and then just use them. Andrei
May 09 2011
On 5/9/11, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:format strings into % format strings, e.g. nice2ugly!"{1}:{2}" yields the string constant "%1$s:%2$s".That is exactly what my echo function does. It replaces {} syntax with %$s syntax behind the scenes, and then forwards that to writef.
May 09 2011
On 2011-05-09 19:34, Andrei Alexandrescu wrote:On 5/9/11 12:14 PM, Jacob Carlborg wrote:Ok, I see. -- /Jacob CarlborgOn 2011-05-09 17:49, Andrei Alexandrescu wrote:I used the Posix positional format syntax, see http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html. AndreiOn 5/9/11 10:37 AM, Jacob Carlborg wrote: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.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
On 2011-05-09 08:52, Andrei Alexandrescu wrote:On 5/7/11 3:43 PM, Jose Armando Garcia 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. -- /Jacob CarlborgHey folks, For the past couple of days I took the liberty of partially implementing a logging module for D.[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
May 09 2011
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
On May 9, 2011, at 10:45 AM, Andrei Alexandrescu wrote:On 5/9/11 12:24 PM, Jacob Carlborg wrote:lineI assume the "initLogging" function needs the application command =Ibecause 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. =thehave 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 =youBoost 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 =considerably more than just the application name. std.log is = configurable via application's command line (e.g. --logtostderr = --log_dir=3D/tmp/ etc., see documentation) and extracts these flags = using getopt. The rest of the flags are left alone for the application = to process. For what it's worth, the command-line args are available via = core.runtime as well.=want to.=20 Thanks! In fact, the command-line arguments are needed for =
May 09 2011
On 2011-05-09 20:03, Sean Kelly wrote:On May 9, 2011, at 10:45 AM, Andrei Alexandrescu wrote:Ah, you're right. -- /Jacob CarlborgOn 5/9/11 12:24 PM, Jacob Carlborg wrote:For what it's worth, the command-line args are available via core.runtime as well.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.
May 09 2011
On 2011-05-09 19:45, Andrei Alexandrescu wrote:On 5/9/11 12:24 PM, Jacob Carlborg wrote:Yes, but since it requires you to pass an array I assumed the application name was the minimum requirement.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-- /Jacob Carlborg
May 09 2011
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
On 2011-05-09 19:58, Andrei Alexandrescu wrote:On 5/9/11 12:24 PM, Jacob Carlborg wrote:Not sure I understand this.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).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! AndreiOk, 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
On 5/9/11 1:48 PM, Jacob Carlborg wrote:On 2011-05-09 19:58, Andrei Alexandrescu wrote: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.On 5/9/11 12:24 PM, Jacob Carlborg wrote:Not sure I understand this.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)); } }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
On 2011-05-09 21:18, Andrei Alexandrescu wrote:On 5/9/11 1:48 PM, 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. -- /Jacob CarlborgOn 2011-05-09 19:58, Andrei Alexandrescu wrote: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.On 5/9/11 12:24 PM, Jacob Carlborg wrote:Not sure I understand this.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)); } }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 10 2011
On 5/10/11 3:22 AM, Jacob Carlborg wrote:On 2011-05-09 21:18, Andrei Alexandrescu wrote: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, AndreiOn 5/9/11 1:48 PM, 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.On 2011-05-09 19:58, Andrei Alexandrescu wrote: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.On 5/9/11 12:24 PM, Jacob Carlborg wrote:Not sure I understand this.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)); } }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 10 2011
On 2011-05-10 16:41, Andrei Alexandrescu wrote:On 5/10/11 3:22 AM, Jacob Carlborg wrote:Well, I only brought it up because I didn't know about Runtime.args. -- /Jacob CarlborgOn 2011-05-09 21:18, Andrei Alexandrescu wrote: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, AndreiOn 5/9/11 1:48 PM, 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.On 2011-05-09 19:58, Andrei Alexandrescu wrote: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.On 5/9/11 12:24 PM, Jacob Carlborg wrote:Not sure I understand this.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)); } }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 10 2011
On 2011-05-10 16:41, Andrei Alexandrescu wrote:On 5/10/11 3:22 AM, Jacob Carlborg wrote:Sean, Walter, is this worth including? -- /Jacob CarlborgAre 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 11 2011
On May 11, 2011, at 11:38 AM, Jacob Carlborg wrote:On 2011-05-10 16:41, Andrei Alexandrescu wrote:Yes. Not sure where it should live though.On 5/10/11 3:22 AM, Jacob Carlborg wrote:Sean, Walter, is this worth including?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.
May 11 2011
On 5/11/11 5:09 PM, Sean Kelly wrote:On May 11, 2011, at 11:38 AM, Jacob Carlborg wrote: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! AndreiOn 2011-05-10 16:41, Andrei Alexandrescu wrote:Yes. Not sure where it should live though.On 5/10/11 3:22 AM, Jacob Carlborg wrote:Sean, Walter, is this worth including?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.
May 11 2011
On 2011-05-12 05:38, Andrei Alexandrescu wrote:On 5/11/11 5:09 PM, Sean Kelly wrote:I'll do this as soon as I can find the time, although it's not on the top of my priority list. -- /Jacob CarlborgOn May 11, 2011, at 11:38 AM, Jacob Carlborg wrote: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! AndreiOn 2011-05-10 16:41, Andrei Alexandrescu wrote:Yes. Not sure where it should live though.On 5/10/11 3:22 AM, Jacob Carlborg wrote:Sean, Walter, is this worth including?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.
May 12 2011
On 09/05/2011 07:52, Andrei Alexandrescu wrote:On 5/7/11 3:43 PM, Jose Armando Garcia 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. -- Robert http://octarineparrot.com/Hey folks, For the past couple of days I took the liberty of partially implementing a logging module for D.[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei
May 09 2011
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
On 5/9/11 1:33 PM, Robert Clipsham wrote:On 09/05/2011 19:30, Robert Clipsham wrote: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. AndreiThe 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); ----
May 09 2011
On 5/9/11 1:30 PM, Robert Clipsham wrote:On 09/05/2011 07:52, Andrei Alexandrescu wrote: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.On 5/7/11 3:43 PM, Jose Armando Garcia 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?)Hey folks, For the past couple of days I took the liberty of partially implementing a logging module for D.[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter. Andrei* 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
Andrei Alexandrescu wrote:On 5/7/11 3:43 PM, Jose Armando Garcia 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. 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. JensHey folks, For the past couple of days I took the liberty of partially implementing a logging module for D.[snip] Nice work. Also thanks for contacting me offline. As I mentioned I'd already decided I'll take a stab at implementing a logging module inspired in design from glog. I was tired of the endless discussions on what a logging API should look like. This ironically is leading now to an embarrassment of riches - we now have two proposals on the table. I subjectively prefer mine for the simple reason that it includes exactly what I wanted from a logging subsystem with a light syntax. The documentation is at http://d-programming-language.org/phobos-prerelease/std_log.html. The source code is at http://erdani.com/log.d, with informative title only; to compile the code you'd need some changes in std.format as well (I extended the positional parameter syntax to allow ranges of positions). Todos include slight refactoring to avoid bloat in generated code per call, OS portability (I only tested on OSX), and getting threading right by fixing the shared-related compiler bugs. Looking forward to more discussion of the matter.
May 09 2011
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
Andrei Alexandrescu wrote:On 5/9/11 3:12 PM, Jens Mueller wrote: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.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.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.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.Thanks. I'll try it out. JensI'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.
May 11 2011
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
On 05/11/2011 08:46 AM, dsimcha wrote:On 5/9/2011 2:52 AM, Andrei Alexandrescu wrote: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, AndreiAs 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
On 05/11/2011 09:15 AM, Andrei Alexandrescu wrote:On 05/11/2011 08:46 AM, dsimcha wrote: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. AndreiOn 5/9/2011 2:52 AM, Andrei Alexandrescu wrote: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, AndreiAs 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
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
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, AndreiOverall, 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
On 05/14/2011 01:29 PM, dsimcha wrote:On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:Logs will be thread-shared. I haven't seen a need for thread-local logs. AndreiOn 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, AndreiOverall, 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
On 2011-05-14 12:36, Andrei Alexandrescu wrote:On 05/14/2011 01:29 PM, dsimcha wrote: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 DavisOn 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:Logs will be thread-shared. I haven't seen a need for thread-local logs.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, AndreiOverall, 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
On 05/14/2011 04:31 PM, Jonathan M Davis wrote:On 2011-05-14 12:36, Andrei Alexandrescu wrote: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 AndreiOn 05/14/2011 01:29 PM, dsimcha wrote: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.On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:Logs will be thread-shared. I haven't seen a need for thread-local logs.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, AndreiOverall, 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
On 2011-05-14 14:50, Andrei Alexandrescu wrote:On 05/14/2011 04:31 PM, Jonathan M Davis wrote: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 DavisOn 2011-05-14 12:36, Andrei Alexandrescu wrote: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 fixOn 05/14/2011 01:29 PM, dsimcha wrote: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.On 5/14/2011 1:04 PM, Andrei Alexandrescu wrote:Logs will be thread-shared. I haven't seen a need for thread-local logs.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, AndreiOverall, 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
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'sYour post just went asian on me. http://i.imgur.com/solwD.pngMay 14 2011On 2011-05-14 14:56, Michel Fortin wrote:On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> said: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 DavisSo, 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.May 14 2011On 05/14/2011 05:17 PM, Jonathan M Davis wrote:On 2011-05-14 14:56, Michel Fortin wrote: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. AndreiOn 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com> said: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.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.May 14 2011On 2011-05-14 18:33:06 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:On 05/14/2011 05:17 PM, Jonathan M Davis wrote: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/On 2011-05-14 14:56, Michel Fortin wrote:The info log contains log messages for all levels.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.May 14 2011On 05/14/2011 06:36 PM, Michel Fortin wrote:On 2011-05-14 18:33:06 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said: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. AndreiOn 05/14/2011 05:17 PM, Jonathan M Davis wrote: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.On 2011-05-14 14:56, Michel Fortin wrote:The info log contains log messages for all levels.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.May 14 2011On 2011-05-14 15:33, Andrei Alexandrescu wrote:On 05/14/2011 05:17 PM, Jonathan M Davis wrote:said:On 2011-05-14 14:56, Michel Fortin wrote:On 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com>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 DavisThe 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.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.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.May 14 2011On 2011-05-15 00:33, Andrei Alexandrescu wrote:On 05/14/2011 05:17 PM, Jonathan M Davis wrote: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 CarlborgOn 2011-05-14 14:56, Michel Fortin wrote: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. AndreiOn 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com> said: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.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.May 15 2011On 05/15/2011 10:26 AM, Jacob Carlborg wrote:On 2011-05-15 00:33, Andrei Alexandrescu wrote: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.On 05/14/2011 05:17 PM, Jonathan M Davis wrote:Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog.On 2011-05-14 14:56, Michel Fortin wrote: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. AndreiOn 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com> said: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.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 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. AndreiMay 15 2011On 2011-05-15 16:01, Andrei Alexandrescu wrote:On 05/15/2011 10:26 AM, Jacob Carlborg wrote: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 DavisOn 2011-05-15 00:33, Andrei Alexandrescu wrote: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.On 05/14/2011 05:17 PM, Jonathan M Davis wrote:Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog.On 2011-05-14 14:56, Michel Fortin wrote: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. AndreiOn 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com> said: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.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 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.May 15 2011On 2011-05-16 01:27, Jonathan M Davis wrote:On 2011-05-15 16:01, Andrei Alexandrescu wrote: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 CarlborgOn 05/15/2011 10:26 AM, Jacob Carlborg wrote: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 DavisOn 2011-05-15 00:33, Andrei Alexandrescu wrote: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.On 05/14/2011 05:17 PM, Jonathan M Davis wrote:Why not? It doesn't say anywhere in the documentation, as far as I can see, that it's based on glog.On 2011-05-14 14:56, Michel Fortin wrote: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. AndreiOn 2011-05-14 17:31:30 -0400, Jonathan M Davis<jmdavisProg gmx.com> said: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.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 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.May 17 2011On 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'sOn 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'sOn 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'sOn 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'sOn 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'sAndrei Alexandrescu wrote:On 05/14/2011 04:56 PM, Michel Fortin wrote:d:On 2011-05-14 17:31:30 -0400, Jonathan M Davis <jmdavisProg gmx.com> sai=chSo, 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=alledcould 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=ues and allthis func=ADtion, all pa=ADra=ADme=ADters are at their de=ADfault val=AD=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). Jenslog=ADging is done only to stderr." So basically, I'll get what I want if I never call initLogging, but then I can't control verbosity and other settings using --v and other flags passed as arguments.=20 A server app must log to files, no question about that. We'll need to add rotation etc. in the future. But I do plan to offer ways to manually override defaults, e.g.: =20 void main(string[] args) { logtostderr =3D true; // override default initLogging(args); ... }May 15 2011On 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'sOn 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, AndreiI 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 2011On 05/14/2011 02:50 PM, Robert Clipsham wrote:On 14/05/2011 18:04, Andrei Alexandrescu wrote: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.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, AndreiI 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?I want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name). AndreiMay 14 2011On 14/05/2011 21:37, Andrei Alexandrescu wrote:On 05/14/2011 02:50 PM, Robert Clipsham wrote: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.On 14/05/2011 18:04, Andrei Alexandrescu wrote: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.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, AndreiI far prefered log.xyz to logXyz... The latter just looks ugly in my opinion.Fair enough. I keep asking as it's essential functionality for me. -- Robert http://octarineparrot.com/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).May 14 2011On 2011-05-14 22:37, Andrei Alexandrescu wrote:On 05/14/2011 02:50 PM, Robert Clipsham wrote: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 CarlborgOn 14/05/2011 18:04, Andrei Alexandrescu wrote: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.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, AndreiI 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?I want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name). AndreiMay 15 2011On 05/15/2011 10:22 AM, Jacob Carlborg wrote:On 2011-05-14 22:37, Andrei Alexandrescu wrote: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. AndreiI want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name). AndreiThe 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.May 15 2011On 2011-05-16 01:04, Andrei Alexandrescu wrote:On 05/15/2011 10:22 AM, Jacob Carlborg wrote:It wasn't my intention to be ironic. I missed "indirection" and just read something about "inside FileLogger". -- /Jacob CarlborgOn 2011-05-14 22:37, Andrei Alexandrescu wrote: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. AndreiI want to nail usability before extension. Extensibility can be provided via an indirection inside FileLogger (which should indeed receive a more appropriate name). AndreiThe 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.May 17 2011On 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 2011On 2011-05-14 16:35, Michel Fortin wrote:On 2011-05-14 13:04:54 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said: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 DavisDocumentation: 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?May 14 2011On 5/14/11 6:35 PM, Michel Fortin wrote:On 2011-05-14 13:04:54 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> said:Great idea. Then we can actually overload every() and after(). Thanks, AndreiDocumentation: 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?May 14 2011On 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 DavisMay 14 2011On 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, AndreiWhy 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 CarlborgMay 15 2011On 15/05/2011 16:15, Jacob Carlborg wrote:On 2011-05-14 19:04, Andrei Alexandrescu wrote:Agreed. -- Robert http://octarineparrot.com/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, AndreiWhy 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.May 15 2011On Sun, 15 May 2011 17:15:38 +0200, Jacob Carlborg wrote:On 2011-05-14 19:04, Andrei Alexandrescu wrote:I agree with this. -LarsOn 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, AndreiWhy 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.May 22 2011On 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: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.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. -LarsMay 22 2011On 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, AndreiHow 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 CarlborgMay 15 2011On 05/15/2011 02:54 PM, Jacob Carlborg wrote:On 2011-05-14 19:04, 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. 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. AndreiOn 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, AndreiHow 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).May 15 2011On 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. AndreiI 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 CarlborgMay 17 2011On 5/17/11 4:02 AM, Jacob Carlborg wrote:On 2011-05-16 02:05, Andrei Alexandrescu wrote:[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, AndreiThanks 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.May 17 2011On 2011-05-17 22:15, Andrei Alexandrescu wrote:On 5/17/11 4:02 AM, Jacob Carlborg wrote:No hard feelings, I also have a tendency to just give negative feedback. -- /Jacob CarlborgOn 2011-05-16 02:05, Andrei Alexandrescu wrote:[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, AndreiThanks 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.May 18 2011std.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:No hard feelings, I also have a tendency to just give negative feedback. -- /Jacob CarlborgOn 2011-05-16 02:05, Andrei Alexandrescu wrote:[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, AndreiThanks 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.May 18 2011On 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, AndreiMay 18 2011Andrei 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: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.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.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. JensMay 19 2011On 5/19/11 2:56 AM, Jens Mueller wrote:Andrei Alexandrescu wrote:It was Jacob. Apologies to both. Andrei* 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.May 19 2011Just 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:lyI 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=mthe community's interests by working on redundant stuff when so many othe=rthings are in need of attention. The reason I started std.log was out of desperation that everybody wanted to talk about it instead of working on =it,and because I figured nobody would implement it the way I thought it need=sto be done anyway. That's why I wrote on Apr 21st:itAgain, 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 =oneartifact. Right now the two APIs are converging and start differing in minor detail=s,which makes it painfully obvious that at the end of the day two people ar=eworking 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=ityis 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=tthe log subsystem pick its parameters. Don't use a delegate unless you ca=n'tdo 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=ldwant 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=ldallow 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=llinitLogging(args[0 .. 1]). * The obvious action to do with a log is to write to it. I don't want to write: log!info.write(stuff); I want to write: logInfo(stuff); or, fine, log!info(stuff); * The names LOGGING_FATAL_DISABLED etc. are gratuitous departures from gl=og.Do what glog does adapted to D's naming convention, hence strip_log_xxx. * I don't want to write log!info(args.length > 1).write("Arguments: ", args[1 .. $]); Putting the condition there makes no sense without the manual. I want to write logInfo.when(args.length > 1)("Arguments: ", args[1 .. $]); or log!info.when(args.length > 1)("Arguments: ", args[1 .. $]); which omits the obvious "write" but adds the non-obvious "when". * Factoring out every, first, etc. is an interesting idea but I found no =usefor it outside logging. (That doesn't mean there isn't any, it just means=weshould think of it because cool things may happen.) That shouldn't harm except when combined with the point above we're forced to: logInfo.when(every(1000))("text"); which is self-explanatory but rather verbose. In all honesty log!info(every(9)).write("Every nine"); isn't that easy on the eyes eithe=r.* Define "after" in addition to "every" and "first", and overload them al=lfor 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, AndreiMay 24 2011Jose 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, -JoseI 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 PfauMay 24 2011The 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:lyI 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=mthe community's interests by working on redundant stuff when so many othe=rthings are in need of attention. The reason I started std.log was out of desperation that everybody wanted to talk about it instead of working on =it,and because I figured nobody would implement it the way I thought it need=sto be done anyway. That's why I wrote on Apr 21st:itAgain, 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 =oneartifact. Right now the two APIs are converging and start differing in minor detail=s,which makes it painfully obvious that at the end of the day two people ar=eworking 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=ityis 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=tthe log subsystem pick its parameters. Don't use a delegate unless you ca=n'tdo without. If client code wants to do configuration work, give them functions, don't ask them for a callback. The callback complicates things for no reason.Done.* The name initializeLogging is a gratuitous departure from glog. Use initLogging.Done.* Keep the glog flags as they are. In all likelihood any user of glog wou=ldwant to define such flags, so we may as well spare them the work.Done.* Pick the logging directory like glog does.Done.* Add programmatic setting of flag names and values before calling initLogging. I think that's a good idea that doesn't depart from glog's design (google cmdline parser uses global names a la FLAGS_xxx). That wou=ldallow 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=llinitLogging(args[0 .. 1]).Done. Given how std.log's command line parsing currently works the user can change an option's default but that easily changeable if we really want this.* The obvious action to do with a log is to write to it. I don't want to write: log!info.write(stuff); I want to write: logInfo(stuff); or, fine, log!info(stuff);Done.* The names LOGGING_FATAL_DISABLED etc. are gratuitous departures from gl=og.Do what glog does adapted to D's naming convention, hence strip_log_xxx.Done.* I don't want to write log!info(args.length > 1).write("Arguments: ", args[1 .. $]); Putting the condition there makes no sense without the manual. I want to write logInfo.when(args.length > 1)("Arguments: ", args[1 .. $]); or log!info.when(args.length > 1)("Arguments: ", args[1 .. $]); which omits the obvious "write" but adds the non-obvious "when".Done.* Factoring out every, first, etc. is an interesting idea but I found no =usefor it outside logging. (That doesn't mean there isn't any, it just means=weshould think of it because cool things may happen.) That shouldn't harm except when combined with the point above we're forced to: logInfo.when(every(1000))("text"); which is self-explanatory but rather verbose. In all honesty log!info(every(9)).write("Every nine"); isn't that easy on the eyes eithe=r.I went with factoring out every, first, etc because I found it to be a cleaner design and easier to test. We can discuss this further if we want to make it an integral part of the library.* Define "after" in addition to "every" and "first", and overload them al=lfor 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 logDone. When implementing this I noticed that total!"hnsecs" performed some unnecessary computations. I should use your code (to use dur!"hnsecs") instead. I'll see if that code path is smarter.* I peeked at the implementation and you allocate one new string for each logged message. You must keep a buffer in thread-local store and reuse it with each call.Done.* The way I see a nice implementation would be (inspired from Jens' work) via a class that defines the client-level methods as final, and has 2-3 extension methods that do the work. That way there's no need for awkward extra names (Logged/Logger, ouch) - one class encapsulates them all.I fixed the Logged/Logger problem in the design but I still didn't use class. Didn't see the need to use polymorphism but I could be wrong...* Call your proposal std.log :o).Done.Thanks, AndreiMay 28 2011Clever use of __FILE__ and __LINE__ to create unique instantiations of the every() template. :)May 28 2011Am 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 2011On 5/28/11, Daniel Gibson <metalcaedes gmail.com> wrote:Am 28.05.2011 20:08, schrieb Andrej Mitrovic:I was just commenting the implementation.Clever use of __FILE__ and __LINE__ to create unique instantiations of the every() template. :)does this belong in this thread?May 28 2011Am 28.05.2011 20:19, schrieb Andrej Mitrovic:On 5/28/11, Daniel Gibson<metalcaedes gmail.com> wrote:Ah ok. I just remembered every from another thread (where using __LINE__ and __FILE__ was discussed) :)Am 28.05.2011 20:08, schrieb Andrej Mitrovic:I was just commenting the implementation.Clever use of __FILE__ and __LINE__ to create unique instantiations of the every() template. :)does this belong in this thread?May 28 2011On 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, -JoseI'd suggest starting a new thread on it or it's likely that a lot of people will miss this. - Jonathan M DavisMay 28 2011This 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:No hard feelings, I also have a tendency to just give negative feedback. -- /Jacob CarlborgOn 2011-05-16 02:05, Andrei Alexandrescu wrote:[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, AndreiThanks 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.May 18 2011On 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. /JonasMay 16 2011Andrei 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. JensMay 16 2011On 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 2011Thanks! 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 2011Hey 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:I think Pantheios is an example of library design gone bad. It is fascinatingly overengineered. AndreiHey 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.May 07 2011On 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, -JoseI'll be sure to try it out in the next few days. Passing messages to a separate logging thread seems like it might be a overkill, but it could work. I do like that you can get the file and line included with messages. One thing I'll miss from Log4J and its siblings is that typing log.info("message") is a lot more intuitive than log(LogLevel.info, "message"). I don't think that's a major gripe though.May 07 2011On 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"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:'s aI'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 2011Ok, 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 2011On Sat, May 7, 2011 at 11:03 PM, dsimcha <dsimcha yahoo.com> wrote:Ok, there's clearly been some misunderstanding here. My real point was, why do you need this threading at all?It's definitely overkill for a single threaded application, but for things like the application I'm working on, which is multithreaded and already uses message passing between threads, I think it would fit in quite nicely. My question would be whether it's pluggable enough to allow the simple case of a single threaded program that doesn't need message passing to be implemented.May 08 2011On Sat, May 7, 2011 at 11:03 PM, dsimcha <dsimcha yahoo.com> wrote: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 DavisOk, there's clearly been some misunderstanding here. My real point was, why do you need this threading at all?It's definitely overkill for a single threaded application, but for things like the application I'm working on, which is multithreaded and already uses message passing between threads, I think it would fit in quite nicely. My question would be whether it's pluggable enough to allow the simple case of a single threaded program that doesn't need message passing to be implemented.May 08 2011I 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=, whydo you need this threading at all? On 5/7/2011 9:01 PM, Jose Armando Garcia wrote:d"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=re'swork.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=ea good reason that I didn't foresee, I'd much rather just keep things lik=logging simple and stupid.May 08 2011On 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 2011On 5/8/2011 11:45 AM, Jose Armando Garcia wrote: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 DavisI 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 2011On 2011-05-08 18:24:12 -0400, Jonathan M Davis <jmdavisProg gmx.com> said: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/On 5/8/2011 11:45 AM, Jose Armando Garcia wrote: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.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 2011On 2011-05-08 15:45, Michel Fortin wrote:On 2011-05-08 18:24:12 -0400, Jonathan M Davis <jmdavisProg gmx.com> said: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 DavisTrue. 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.On 5/8/2011 11:45 AM, Jose Armando Garcia wrote: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.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 2011Yes. 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:s,Ok, there's clearly been some misunderstanding here. =A0My real point wa=swhy 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=sesmessage 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=seof a single threaded program that doesn't need message passing to be implemented.May 08 2011Good 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:was,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 =gswhy do you need this threading at all?It's definitely overkill for a single threaded application, but for thin=nglike 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=eto 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=hthread the log message came from. How it's thread safe should be invisibl=e andirrelevant to anyone using the logger. Why should I care whether it's usi=ngmessage passing, shared variables, or whatever internally? Ideally, it wouldn't need to worry about threading at all, but I'm not sure how likel=ythat is. I believe that writeln should be thread-safe, but I'm not sure t=hatfile stuff would be, and presumably the logger needs to be able to do bot=h ofthose. - Jonathan M DavisMay 08 2011