www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - std.log available for viewing

reply Jose Armando Garcia <jsancio gmail.com> writes:
The implementation and documentation for std.log is ready for viewing.
You can take a look at the doc at
http://jsancio.github.com/phobos/phobos/std_log.html. The source code
is at https://github.com/jsancio/phobos/blob/master/std/log.d.

I had to make some changes to druntime to get the thread id. The
module will work without the changes but you wont to see thread ids in
your log messages. I will look into sending a pull request to
druntime, in the meantime you can apply the attached patch to your
druntime if you want to see thread ids in the log.

Let me know if you have any comments or suggestions! Thanks,
-Jose
May 28 2011
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-29 01:40, 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. The
 module will work without the changes but you wont to see thread ids in
 your log messages. I will look into sending a pull request to
 druntime, in the meantime you can apply the attached patch to your
 druntime if you want to see thread ids in the log.

 Let me know if you have any comments or suggestions! Thanks,
 -Jose
Why is everyone that contribute with a std.log implementation keep insisting that it should be configured via command line options? This is not how a library should be configured, it should be configured via regular methods like the rest of Phobos. If an application wants to set logging options via the command line then that's up to the application to implement. I don't like the abbreviations, "vlog" and "dfatal". I first thought you had an error in the documentation when I saw "fatal" and "dfatal". I would suggest "verbose" and "debugFatal", it's clear what they mean and it's consistent with how the other logging levels are named. There's always the option to alias a method for the users. -- /Jacob Carlborg
May 29 2011
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/29/11 5:07 AM, Jacob Carlborg wrote:
 Why is everyone that contribute with a std.log implementation keep
 insisting that it should be configured via command line options? This is
 not how a library should be configured, it should be configured via
 regular methods like the rest of Phobos. If an application wants to set
 logging options via the command line then that's up to the application
 to implement.
I think that's because command-line configuration is very commonly required for logging. (Programmatic configuration should be allowed as well.) Though logging is useful for a variety of applications, it is vital to headless servers. Having a unified convention for command-line configurability is a boon for deployment tools.
 I don't like the abbreviations, "vlog" and "dfatal". I first thought you
 had an error in the documentation when I saw "fatal" and "dfatal". I
 would suggest "verbose" and "debugFatal", it's clear what they mean and
 it's consistent with how the other logging levels are named. There's
 always the option to alias a method for the users.
I instantly recognized "vlog" as "verbose log" and "dlog" as "debug log". We arguably don't need the latter as "debug log" is quite light, and I don't see "vlog" a tenuous term to learn and use. A lot of terms could go any number of ways though. Andrei
May 29 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-29 17:06, Andrei Alexandrescu wrote:
 On 5/29/11 5:07 AM, Jacob Carlborg wrote:
 Why is everyone that contribute with a std.log implementation keep
 insisting that it should be configured via command line options? This is
 not how a library should be configured, it should be configured via
 regular methods like the rest of Phobos. If an application wants to set
 logging options via the command line then that's up to the application
 to implement.
I think that's because command-line configuration is very commonly required for logging. (Programmatic configuration should be allowed as well.) Though logging is useful for a variety of applications, it is vital to headless servers. Having a unified convention for command-line configurability is a boon for deployment tools.
 I don't like the abbreviations, "vlog" and "dfatal". I first thought you
 had an error in the documentation when I saw "fatal" and "dfatal". I
 would suggest "verbose" and "debugFatal", it's clear what they mean and
 it's consistent with how the other logging levels are named. There's
 always the option to alias a method for the users.
I instantly recognized "vlog" as "verbose log" and "dlog" as "debug log". We arguably don't need the latter as "debug log" is quite light, and I don't see "vlog" a tenuous term to learn and use. A lot of terms could go any number of ways though. Andrei
I also recognized "vlog" as "verbose log" but the first time I saw "fatal" and "dfatal" I actually though there was a mistake. We have this great language construct, alias, in D, why not take advantage of it? Name the functions clear and consistent without any unnecessary abbreviations and let the user of the library create alias if he/she wants to. Why shouldn't "error" be named "elog" and "info" be named "ilog"? To me it seems that "vlog" is just a random pick for using a abbreviated name. Sometimes you are very consistent but other times you just want to go with the shortest. Why can't we have it consistent? -- /Jacob Carlborg
May 29 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/29/2011 01:32 PM, Jacob Carlborg wrote:
 Sometimes you are very consistent but other times you just want to go
 with the shortest. Why can't we have it consistent?
Again, consistency is a relation, not a value, i.e. consistent with _what_ is key. In this case I'm being consistent with glog's choice of names. Andrei
May 29 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-29 20:34, Andrei Alexandrescu wrote:
 On 05/29/2011 01:32 PM, Jacob Carlborg wrote:
 Sometimes you are very consistent but other times you just want to go
 with the shortest. Why can't we have it consistent?
Again, consistency is a relation, not a value, i.e. consistent with _what_ is key. In this case I'm being consistent with glog's choice of names. Andrei
Why are you so fixed with glog, yes I know you think it's a great library, could you please let it go and try to think out of the box that is glog. Can we have it consistent within our own logging API and for one second forget that the API is original based on glog? -- /Jacob Carlborg
May 29 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/29/2011 01:42 PM, Jacob Carlborg wrote:
 On 2011-05-29 20:34, Andrei Alexandrescu wrote:
 On 05/29/2011 01:32 PM, Jacob Carlborg wrote:
 Sometimes you are very consistent but other times you just want to go
 with the shortest. Why can't we have it consistent?
Again, consistency is a relation, not a value, i.e. consistent with _what_ is key. In this case I'm being consistent with glog's choice of names. Andrei
Why are you so fixed with glog, yes I know you think it's a great library, could you please let it go and try to think out of the box that is glog.
This is not "thinking", it's a simple name choice.
 Can we have it consistent within our own logging API and for one second
 forget that the API is original based on glog?
That would be circular logic. I'm sure you are referring to consistency with the general naming convention in Phobos, which I agree would also be desirable. The delicate thing is satisfying everybody. Andrei
May 29 2011
next sibling parent Daniel Gibson <metalcaedes gmail.com> writes:
Am 29.05.2011 23:07, schrieb Andrei Alexandrescu:
 On 05/29/2011 01:42 PM, Jacob Carlborg wrote:
 On 2011-05-29 20:34, Andrei Alexandrescu wrote:
 On 05/29/2011 01:32 PM, Jacob Carlborg wrote:
 Sometimes you are very consistent but other times you just want to go
 with the shortest. Why can't we have it consistent?
Again, consistency is a relation, not a value, i.e. consistent with _what_ is key. In this case I'm being consistent with glog's choice of names. Andrei
Why are you so fixed with glog, yes I know you think it's a great library, could you please let it go and try to think out of the box that is glog.
This is not "thinking", it's a simple name choice.
 Can we have it consistent within our own logging API and for one second
 forget that the API is original based on glog?
That would be circular logic. I'm sure you are referring to consistency with the general naming convention in Phobos, which I agree would also be desirable. The delicate thing is satisfying everybody.
IMHO consistency with Phobos' naming conventions is more important than consistency with the naming conventions of the lib that the code was inspired by. People who have ever used glog will want to use std.log - and they will expect names to be consistent within Phobos and they won't care about historical reasons.
 
 Andrei
Cheers, - Daniel
May 29 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-05-29 23:07, Andrei Alexandrescu wrote:
 On 05/29/2011 01:42 PM, Jacob Carlborg wrote:
 On 2011-05-29 20:34, Andrei Alexandrescu wrote:
 On 05/29/2011 01:32 PM, Jacob Carlborg wrote:
 Sometimes you are very consistent but other times you just want to go
 with the shortest. Why can't we have it consistent?
Again, consistency is a relation, not a value, i.e. consistent with _what_ is key. In this case I'm being consistent with glog's choice of names. Andrei
Why are you so fixed with glog, yes I know you think it's a great library, could you please let it go and try to think out of the box that is glog.
This is not "thinking", it's a simple name choice.
 Can we have it consistent within our own logging API and for one second
 forget that the API is original based on glog?
That would be circular logic. I'm sure you are referring to consistency with the general naming convention in Phobos, which I agree would also be desirable. The delicate thing is satisfying everybody. Andrei
Yes, it would be more consistent with the rest of Phobos. But if we just take a look at the logging library and for one second forget that the API is originally from glog then "vlog" is not consistent with how the other functions are named, "info" and "error" for example. -- /Jacob Carlborg
May 30 2011
prev sibling next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
Configuring through the command line is optional for example the
following command line:

$ program --minloglevel=warning --v=3 --logdir=/tmp

Translate to the following in code:

---
import std.log;

void main(string[] args)
{
   FilterConfig filterConfig;
   filterConfig.minSeverity = Level.warning;
   filterCofnig.verboseConfig.maxVerboseLevel = 3;

   LoggerConfig loggerConfig;
   loggerConfig.logDirectory = "/tmp";

   initializeLogging!SharedLogger(loggerConfig, filterConfig);

   //...
}
---

I.e. all the command line options are also available programmatically.
The reverse is not the case. All programmatic options are not
available at the command line.

Fine point about 'dfatal' and 'vlog'. I was trying to keep the
interface as close to glog as possible where it is warranted but I
have not problem changing it to 'debugFatal' and 'verbose'.

Thanks,
-Jose

On Sun, May 29, 2011 at 7:07 AM, Jacob Carlborg <doob me.com> wrote:
 On 2011-05-29 01:40, 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. The
 module will work without the changes but you wont to see thread ids in
 your log messages. I will look into sending a pull request to
 druntime, in the meantime you can apply the attached patch to your
 druntime if you want to see thread ids in the log.

 Let me know if you have any comments or suggestions! Thanks,
 -Jose
Why is everyone that contribute with a std.log implementation keep insisting that it should be configured via command line options? This is not how a library should be configured, it should be configured via regular methods like the rest of Phobos. If an application wants to set logging options via the command line then that's up to the application to implement. I don't like the abbreviations, "vlog" and "dfatal". I first thought you had an error in the documentation when I saw "fatal" and "dfatal". I would suggest "verbose" and "debugFatal", it's clear what they mean and it's consistent with how the other logging levels are named. There's always the option to alias a method for the users. -- /Jacob Carlborg
May 29 2011
parent reply Jacob Carlborg <doob me.com> writes:
On 2011-05-29 17:10, Jose Armando Garcia wrote:
 Configuring through the command line is optional for example the
 following command line:

 $ program --minloglevel=warning --v=3 --logdir=/tmp

 Translate to the following in code:

 ---
 import std.log;

 void main(string[] args)
 {
     FilterConfig filterConfig;
     filterConfig.minSeverity = Level.warning;
     filterCofnig.verboseConfig.maxVerboseLevel = 3;

     LoggerConfig loggerConfig;
     loggerConfig.logDirectory = "/tmp";

     initializeLogging!SharedLogger(loggerConfig, filterConfig);

     //...
 }
 ---

 I.e. all the command line options are also available programmatically.
 The reverse is not the case. All programmatic options are not
 available at the command line.

 Fine point about 'dfatal' and 'vlog'. I was trying to keep the
 interface as close to glog as possible where it is warranted but I
 have not problem changing it to 'debugFatal' and 'verbose'.

 Thanks,
 -Jose
I guess that that is acceptable. BTW, what happens if you start logging without passing any command line arguments or initializing the library? Does it have a default behavior making it usable? -- /Jacob Carlborg
May 29 2011
parent reply Jose Armando Garcia <jsancio gmail.com> writes:
By default the module will read the command line arguments looking for
known option. For any option that is missing the default will be used.
The default for each option is described in FilterConfig,
VerboseConfig and LoggerConfig. I.e. the module works without any
explicit initialization by the user. Look at 'share static this()'.

On Sun, May 29, 2011 at 3:22 PM, Jacob Carlborg <doob me.com> wrote:
 On 2011-05-29 17:10, Jose Armando Garcia wrote:
 Configuring through the command line is optional for example the
 following command line:

 $ program --minloglevel=3Dwarning --v=3D3 --logdir=3D/tmp

 Translate to the following in code:

 ---
 import std.log;

 void main(string[] args)
 {
 =A0 =A0FilterConfig filterConfig;
 =A0 =A0filterConfig.minSeverity =3D Level.warning;
 =A0 =A0filterCofnig.verboseConfig.maxVerboseLevel =3D 3;

 =A0 =A0LoggerConfig loggerConfig;
 =A0 =A0loggerConfig.logDirectory =3D "/tmp";

 =A0 =A0initializeLogging!SharedLogger(loggerConfig, filterConfig);

 =A0 =A0//...
 }
 ---

 I.e. all the command line options are also available programmatically.
 The reverse is not the case. All programmatic options are not
 available at the command line.

 Fine point about 'dfatal' and 'vlog'. I was trying to keep the
 interface as close to glog as possible where it is warranted but I
 have not problem changing it to 'debugFatal' and 'verbose'.

 Thanks,
 -Jose
I guess that that is acceptable. BTW, what happens if you start logging without passing any command line arguments or initializing the library? D=
oes
 it have a default behavior making it usable?

 --
 /Jacob Carlborg
May 29 2011
parent Jacob Carlborg <doob me.com> writes:
On 2011-05-30 01:59, Jose Armando Garcia wrote:
 By default the module will read the command line arguments looking for
 known option. For any option that is missing the default will be used.
 The default for each option is described in FilterConfig,
 VerboseConfig and LoggerConfig. I.e. the module works without any
 explicit initialization by the user. Look at 'share static this()'.
Sounds reasonable. -- /Jacob Carlborg
May 30 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/29/2011 3:07 AM, Jacob Carlborg wrote:
 Why is everyone that contribute with a std.log implementation keep insisting
 that it should be configured via command line options?
What rolls down stairs alone or in pairs, and over your neighbor's dog? What's great for a snack, And fits on your back? It's log, log, log It's log, it's log, It's big, it's heavy, it's wood. It's log, it's log, it's better than bad, it's good. Everyone wants a log You're gonna love it, log Come on and get your log Everyone needs a log log log log LOG FROM BLAMMO (-- Ren & Stimpy)
May 29 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 5/29/11, Walter Bright <newshound2 digitalmars.com> wrote:
 On 5/29/2011 3:07 AM, Jacob Carlborg wrote:
 Why is everyone that contribute with a std.log implementation keep
 insisting
 that it should be configured via command line options?
What rolls down stairs alone or in pairs, and over your neighbor's dog? What's great for a snack, And fits on your back? It's log, log, log It's log, it's log, It's big, it's heavy, it's wood. It's log, it's log, it's better than bad, it's good. Everyone wants a log You're gonna love it, log Come on and get your log Everyone needs a log log log log LOG FROM BLAMMO (-- Ren & Stimpy)
I expect this to be incorporated as the de-facto default error message for fatal errors. It shall be displayed in a dialog box, even on headless servers!
May 29 2011
prev sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Sun, May 29, 2011 at 3:57 PM, Walter Bright
<newshound2 digitalmars.com> wrote:
 On 5/29/2011 3:07 AM, Jacob Carlborg wrote:
 Why is everyone that contribute with a std.log implementation keep
 insisting
 that it should be configured via command line options?
What rolls down stairs alone or in pairs, and over your neighbor's dog? What's great for a snack, And fits on your back? It's log, log, log It's log, it's log, It's big, it's heavy, it's wood. It's log, it's log, it's better than bad, it's good. Everyone wants a log You're gonna love it, log Come on and get your log Everyone needs a log log log log LOG FROM BLAMMO (-- Ren & Stimpy)
Walter, what do you think about adding __MODULE__ to the language? It will work similar to __FILE__ and __LINE__ but instead get replaced by the name of the module. This would be really useful for std.log's verbosity filtering feature. I can send a pull request once I am familiar with dmd's code. Thanks, -Jose
May 30 2011
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On May 31, 11 00:59, Jose Armando Garcia wrote:
[snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
May 30 2011
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
 On May 31, 11 00:59, Jose Armando Garcia wrote:
 [snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
While this is already quite useful, stuff like this wont work: import std.algorithm; void main(){ int f(int x){return x*x-2;} auto m = map!"f(a)+1"([1,6,8]); } What you'd actually want to pass implicitly is a local __SCOPE__, not a global __MODULE__ scope. Timon
May 30 2011
parent KennyTM~ <kennytm gmail.com> writes:
On May 31, 11 03:56, Timon Gehr wrote:
 On May 31, 11 00:59, Jose Armando Garcia wrote:
 [snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
While this is already quite useful, stuff like this wont work: import std.algorithm; void main(){ int f(int x){return x*x-2;} auto m = map!"f(a)+1"([1,6,8]); } What you'd actually want to pass implicitly is a local __SCOPE__, not a global __MODULE__ scope. Timon
__MODULE__ requires minimal change because a module symbol is well-supported. __SCOPE__ needs much more work. As a short-term solution, __MODULE__ is more practical to implement first than __SCOPE__.
May 30 2011
prev sibling parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 30/05/2011 18:41, KennyTM~ wrote:
 On May 31, 11 00:59, Jose Armando Garcia wrote:
 [snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
Why do we need __MODULE__ at all for that, a new key does not seems necessary. Instead of "__MODULE__.stringof[7..$]" there is ".stringof[7..$]" which works already. As for accessing the module scope itself, perhaps we could use ".this" as a syntax. -- Bruno Medeiros - Software Engineer
Jun 02 2011
next sibling parent reply KennyTM~ <kennytm gmail.com> writes:
On Jun 2, 11 22:47, Bruno Medeiros wrote:
 On 30/05/2011 18:41, KennyTM~ wrote:
 On May 31, 11 00:59, Jose Armando Garcia wrote:
 [snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
Why do we need __MODULE__ at all for that, a new key does not seems necessary. Instead of "__MODULE__.stringof[7..$]" there is ".stringof[7..$]" which works already. As for accessing the module scope itself, perhaps we could use ".this" as a syntax.
__MODULE__ is evaluated at instantiation site, like __FILE__ and __LINE__, while .stringof is evaluated at definition site.
Jun 02 2011
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
On 02/06/2011 16:28, KennyTM~ wrote:
 On Jun 2, 11 22:47, Bruno Medeiros wrote:
 On 30/05/2011 18:41, KennyTM~ wrote:
 On May 31, 11 00:59, Jose Armando Garcia wrote:
 [snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
Why do we need __MODULE__ at all for that, a new key does not seems necessary. Instead of "__MODULE__.stringof[7..$]" there is ".stringof[7..$]" which works already. As for accessing the module scope itself, perhaps we could use ".this" as a syntax.
__MODULE__ is evaluated at instantiation site, like __FILE__ and __LINE__, while .stringof is evaluated at definition site.
Ah, I see what you mean, when they are used as default arguments in functions and templates, right? Didn't recall that was the case. -- Bruno Medeiros - Software Engineer
Jun 02 2011
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2011-06-02 16:47, Bruno Medeiros wrote:
 On 30/05/2011 18:41, KennyTM~ wrote:
 On May 31, 11 00:59, Jose Armando Garcia wrote:
 [snip]
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.

 I can send a pull request once I am familiar with dmd's code.

 Thanks,
 -Jose
I'd recommend making __MODULE__ return the actual module object instead of the module name, in case anybody wants to implement it. The latter can be easily got by __MODULE__.stringof[7..$] or parsing std.traits.mangledName!__MODULE__ if you need the fully-qualified name, but the reverse is not true. Moreover, making __MODULE__ a true module object allows a global scope be passed around implicitly, e.g. currently you need to write int f(int x) { return x*x-2; } void main() { auto m = map!((y){ return f(y)+1; })([1,6,8]); // ^^^^^^^^^^^^^^^^^^^^^ ugly but with __MODULE__ it is possible to reduce the syntactic noise: auto m = map!"f(a)+1"([1,6,8]); by declaring std.functional.unaryFun as template unaryFun(alias f, ....., alias mod=__MODULE__) { ... with (mod) { mixin(f); } ...
Why do we need __MODULE__ at all for that, a new key does not seems necessary. Instead of "__MODULE__.stringof[7..$]" there is ".stringof[7..$]" which works already. As for accessing the module scope itself, perhaps we could use ".this" as a syntax.
.stringof doesn't return the full module name, just the last part. -- /Jacob Carlborg
Jun 02 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.
I don't know. I know I am leery of just adding more and more stuff like this.
May 30 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/30/2011 01:02 PM, Walter Bright wrote:
 On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.
I don't know. I know I am leery of just adding more and more stuff like this.
Gnu's and subsequently C++0x's experience with __FUNCTION__ and __PRETTY_FUNCTION__ has shown that the effects are beneficial. Andrei
May 30 2011
parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 30/05/2011 20:08, Andrei Alexandrescu wrote:
 On 05/30/2011 01:02 PM, Walter Bright wrote:
 On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.
I don't know. I know I am leery of just adding more and more stuff like this.
Gnu's and subsequently C++0x's experience with __FUNCTION__ and __PRETTY_FUNCTION__ has shown that the effects are beneficial. Andrei
module/package of a given symbol - I figure adding a trait is better than adding more ugly __FOOBAR__ nonsense (not that __traits() is the nicest syntax of course ;)). -- Robert http://octarineparrot.com/
May 30 2011
parent KennyTM~ <kennytm gmail.com> writes:
On May 31, 11 03:32, Robert Clipsham wrote:
 On 30/05/2011 20:08, Andrei Alexandrescu wrote:
 On 05/30/2011 01:02 PM, Walter Bright wrote:
 On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:
 Walter, what do you think about adding __MODULE__ to the language? It
 will work similar to __FILE__ and __LINE__ but instead get replaced by
 the name of the module. This would be really useful for std.log's
 verbosity filtering feature.
I don't know. I know I am leery of just adding more and more stuff like this.
Gnu's and subsequently C++0x's experience with __FUNCTION__ and __PRETTY_FUNCTION__ has shown that the effects are beneficial. Andrei
module/package of a given symbol - I figure adding a trait is better than adding more ugly __FOOBAR__ nonsense (not that __traits() is the nicest syntax of course ;)).
The advantage of __NONSENSE__ is that, by convention, the token will be evaluated at instantiation site instead of definition site in a parameter default: template T(alias modName=__MODULE__) { ... how would __traits(moduleOf, ...) deal with this?
May 30 2011
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/28/11 6:40 PM, 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. The
 module will work without the changes but you wont to see thread ids in
 your log messages. I will look into sending a pull request to
 druntime, in the meantime you can apply the attached patch to your
 druntime if you want to see thread ids in the log.

 Let me know if you have any comments or suggestions! Thanks,
 -Jose
1. The fatal log should never be stripped. This is because execution of code after using fatal depends on compile-time flags, which is unacceptable. Logging to fatal should terminate the application regardless of circumstances. Otherwise people would need to write things like: fatal("blah"); assert(0, "Execution cannot continue even though logging is stripped"); This is needless and bug-prone. Fatal is fatal. 2. A critical log that (always) throws might encourage disciplined use of exceptions - and with good messages. BTW the log message should be present in the exception object too! 3. Why doesn't vlog take the __LINE__ too? 4. initLogging and initializeLogging are highly confusing names. Overload them to share the same name, or rename one. 5. Time should be not expressed as long. 6. The riches of XxxConfig types form a sudden swell difficult to justify. What is the justification of FilterConfig, VerboseConfig, and LoggerConfig? They don't even make sense as nouns or noun phrases. Anyhow, a simple approach to design would be: if you need to configure some already-created object you'd do so by calling methods of that object, and if you need to configure an object just before creating it, some factory pattern might be of use. Probably configuration after construction is the election approach for this case. 7. The design pushes formatting down to the dynamic interface. That might be the right thing but prevents the front end from configuring formatting, thus complicating matters for the user. The implementer is also aggravated because they need to implement formatting code themselves. (As far as I can tell, formatting is not formally offered by the design.) This latter issue could be solved by inserting a lower-level interface that only transports strings, and a stock implementation of a formatting object; but that complicates the design. Thanks, Andrei
May 29 2011
next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
Thanks. Comments below.

On Sun, May 29, 2011 at 12:44 PM, Andrei Alexandrescu
<SeeWebsiteForEmail erdani.org> wrote:
 On 5/28/11 6:40 PM, 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. The
 module will work without the changes but you wont to see thread ids in
 your log messages. I will look into sending a pull request to
 druntime, in the meantime you can apply the attached patch to your
 druntime if you want to see thread ids in the log.

 Let me know if you have any comments or suggestions! Thanks,
 -Jose
1. The fatal log should never be stripped. This is because execution of code after using fatal depends on compile-time flags, which is unacceptable. Logging to fatal should terminate the application regardless of circumstances. Otherwise people would need to write things like: fatal("blah"); assert(0, "Execution cannot continue even though logging is stripped"); This is needless and bug-prone. Fatal is fatal.
Makes sense - will change.
 2. A critical log that (always) throws might encourage disciplined use of
 exceptions - and with good messages. BTW the log message should be present
 in the exception object too!
Makes sense - will change.
 3. Why doesn't vlog take the __LINE__ too?
vlog simply filters based on the verbose level and the file by comparing it to the --vmodule and --v flags. For this reason it only need the level and the file name. Message formatting is done in another method.
 4. initLogging and initializeLogging are highly confusing names. Overload
 them to share the same name, or rename one.
Yeah. I don't like this either but if I remember correctly D/dmd doesn't let me overload a function with a template. I'll look into this again. Maybe I can figure out a way to make initLogging a template and hence rename initializeLogging.
 5. Time should be not expressed as long.
Are you referring to LogMessage.time? Do you see an issue with internally (things not expose to the client/user) being expressed as long?
 6. The riches of XxxConfig types form a sudden swell difficult to justify.
 What is the justification of FilterConfig, VerboseConfig, and LoggerConfig?
 They don't even make sense as nouns or noun phrases. Anyhow, a simple
 approach to design would be: if you need to configure some already-created
 object you'd do so by calling methods of that object, and if you need to
 configure an object just before creating it, some factory pattern might be
 of use. Probably configuration after construction is the election approach
 for this case.
I can probably merge FilterConfig and VerboseConfig into one configuration object. I want to keep that separate from LoggerConfig because the things in LoggerConfig are specific to a logger/writer that writes to disk hence only useful to a file writer. The configuration of a logger/writer that records log message to a database may/will look different. Now, to answer why do they even exist at all is that originally I wanted to only allow configuration at creation time. Now I am thinking of allowing configuration even after message have been logged. If that is the case then I can probably remove FilterConfig and VerboseConfig. I'll look into this and get back to you with a concrete answer...
 7. The design pushes formatting down to the dynamic interface. That might be
 the right thing but prevents the front end from configuring formatting, thus
 complicating matters for the user. The implementer is also aggravated
 because they need to implement formatting code themselves. (As far as I can
 tell, formatting is not formally offered by the design.) This latter issue
 could be solved by inserting a lower-level interface that only transports
 strings, and a stock implementation of a formatting object; but that
 complicates the design.
I definitively don't want to do formatting in the front end to allow the recording of structured/semi-structured log messages. I now of at least one large datacenter that stores semi-structured log message on a distributed database. I'll look into presenting this formatting issue in a nice way to the writer of the backend.
 Thanks,

 Andrei
May 29 2011
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/29/2011 12:25 PM, Jose Armando Garcia wrote:
 Thanks. Comments below.
[snip] All good points. Thanks! Andrei
May 29 2011
prev sibling next sibling parent reply Brad Roberts <braddr puremagic.com> writes:
On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of code
after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
application regardless of circumstances. Otherwise
 people would need to write things like:
 
 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");
 
 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. After a couple years, I came to greatly regret it. Fatalness down in libraries became overused, particularly in layers that were libraries. In some ways it was abuse of fatal for things that shouldn't have been, but it's mere existence encouraged it's use. I really don't think it's the log libraries job to implement app termination behavior. My 2 cents, Brad
May 29 2011
next sibling parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 29.05.2011 22:57, schrieb Brad Roberts:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of code
after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. After a couple years, I came to greatly regret it. Fatalness down in libraries became overused, particularly in layers that were libraries. In some ways it was abuse of fatal for things that shouldn't have been, but it's mere existence encouraged it's use. I really don't think it's the log libraries job to implement app termination behavior. My 2 cents, Brad
Also imagine the following scenario: You detect a fatal error and want to log it, while all the useful information you want to log is at hand. However afterwards you'd like to shut down the application gracefully to leave your data as consistent as possible or whatever, so you don't want the application to terminate immediately after fatal() but you want to do error handling yourself and terminate afterwards (and what you do for error handling/shutting downmay be dependent on the error, so just using scope(error) may not be the easiest choice). Cheers, - Daniel
May 29 2011
parent reply Jose Armando Garcia <jsancio gmail.com> writes:
Then use critical with all the exception handling techniques that D
provide, try, scope, etc. Maybe critical should allow the throwing of
user define exceptions with a meaningful default. What do people
think?

On Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com> wrot=
e:
 Am 29.05.2011 22:57, schrieb Brad Roberts:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of=
code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the app=
lication regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. =A0After=
a couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers that=
were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence encou=
raged it's use.
 I really don't think it's the log libraries job to implement app termina=
tion behavior.
 My 2 cents,
 Brad
Also imagine the following scenario: You detect a fatal error and want to log it, while all the useful information you want to log is at hand. However afterwards you'd like to shut down the application gracefully to leave your data as consistent as possible or whatever, so you don't want the application to terminate immediately after fatal() but you want to do error handling yourself and terminate afterwards (and what you do for error handling/shutting downmay be dependent on the error, so just using scope(error) may not be the easiest choice). Cheers, - Daniel
May 29 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 30.05.2011 02:11, schrieb Jose Armando Garcia:
 Then use critical with all the exception handling techniques that D
 provide, try, scope, etc. Maybe critical should allow the throwing of
 user define exceptions with a meaningful default. What do people
 think?
 
I don't have much experience with logging frameworks, but is there really a *need* for a fatal log-function that terminates the program? I'd expect fatal() to produce a line like "<timestamp> FATAL: <yourmessage>" in the log (and I'd expect it to be logged when only fatal messages are activated) - but I wouldn't expect it to terminate the program. I'd just like to log the fatal error (yes, it is fatal, not just critical or something) and terminate the program myself. BTW: You may have noticed that people in this newsgroup usually write *below* the cited text they're referring to - could you do the same, for the sake of consistency and readability? Thanks :-) Cheers, - Daniel
 On Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com> wrote:
 Am 29.05.2011 22:57, schrieb Brad Roberts:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of code
after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. After a couple years, I came to greatly regret it. Fatalness down in libraries became overused, particularly in layers that were libraries. In some ways it was abuse of fatal for things that shouldn't have been, but it's mere existence encouraged it's use. I really don't think it's the log libraries job to implement app termination behavior. My 2 cents, Brad
Also imagine the following scenario: You detect a fatal error and want to log it, while all the useful information you want to log is at hand. However afterwards you'd like to shut down the application gracefully to leave your data as consistent as possible or whatever, so you don't want the application to terminate immediately after fatal() but you want to do error handling yourself and terminate afterwards (and what you do for error handling/shutting downmay be dependent on the error, so just using scope(error) may not be the easiest choice). Cheers, - Daniel
May 29 2011
parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Sun, May 29, 2011 at 9:37 PM, Daniel Gibson <metalcaedes gmail.com> wrot=
e:
 Am 30.05.2011 02:11, schrieb Jose Armando Garcia:
 Then use critical with all the exception handling techniques that D
 provide, try, scope, etc. Maybe critical should allow the throwing of
 user define exceptions with a meaningful default. What do people
 think?
I don't have much experience with logging frameworks, but is there really a *need* for a fatal log-function that terminates the program? I'd expect fatal() to produce a line like "<timestamp> FATAL: <yourmessage>" in the log (and I'd expect it to be logged when only fatal messages are activated) - but I wouldn't expect it to terminate the program. I'd just like to log the fatal error (yes, it is fatal, not just critical or something) and terminate the program myself.
It is just a matter of semantic. We have, if you want, arbitrarily defined fatal to halt the program, critical to throw an exception, and error to just log. But we should think of them all as an error/bug in your program. Now if in a particular point of your application you want it to halt on such error then use fatal, if you want it to throw then use critical, if you want it to just log then use error. The power is in your hand. Fair enough?
 BTW: You may have noticed that people in this newsgroup usually write
 *below* the cited text they're referring to - could you do the same, for
 the sake of consistency and readability? =A0Thanks :-)
Thanks!
 Cheers,
 - Daniel


 On Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com> w=
rote:
 Am 29.05.2011 22:57, schrieb Brad Roberts:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution =
of code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the a=
pplication regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped"=
);
 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. =A0Aft=
er a couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers th=
at were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence enc=
ouraged it's use.
 I really don't think it's the log libraries job to implement app termi=
nation behavior.
 My 2 cents,
 Brad
Also imagine the following scenario: You detect a fatal error and want to log it, while all the useful information you want to log is at hand. However afterwards you'd like to shut down the application gracefully t=
o
 leave your data as consistent as possible or whatever, so you don't wan=
t
 the application to terminate immediately after fatal() but you want to
 do error handling yourself and terminate afterwards (and what you do fo=
r
 error handling/shutting downmay be dependent on the error, so just usin=
g
 scope(error) may not be the easiest choice).

 Cheers,
 - Daniel
May 29 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 30.05.2011 03:07, schrieb Jose Armando Garcia:
 On Sun, May 29, 2011 at 9:37 PM, Daniel Gibson <metalcaedes gmail.com> wrote:
 Am 30.05.2011 02:11, schrieb Jose Armando Garcia:
 Then use critical with all the exception handling techniques that D
 provide, try, scope, etc. Maybe critical should allow the throwing of
 user define exceptions with a meaningful default. What do people
 think?
I don't have much experience with logging frameworks, but is there really a *need* for a fatal log-function that terminates the program? I'd expect fatal() to produce a line like "<timestamp> FATAL: <yourmessage>" in the log (and I'd expect it to be logged when only fatal messages are activated) - but I wouldn't expect it to terminate the program. I'd just like to log the fatal error (yes, it is fatal, not just critical or something) and terminate the program myself.
It is just a matter of semantic. We have, if you want, arbitrarily defined fatal to halt the program, critical to throw an exception, and error to just log. But we should think of them all as an error/bug in your program. Now if in a particular point of your application you want it to halt on such error then use fatal, if you want it to throw then use critical, if you want it to just log then use error. The power is in your hand. Fair enough?
Sounds ok, but for me it still "feels" strange that the logging library terminates my program or throws exception. And error() (probably?) will be logged differently than fatal(), even though both log an error and fatal() has the additional feature to terminate your program via assert(false); if I'm not mistaken. [OT:] What is assert(false); supposed to do, anyway? I think I've read it's supposed to terminates the program immediately without any cleanups (which is unfortunate for a logging library - at least destructors and scope guards should be executed so e.g. database connections are cleanly closed). I just tried it (with dmd 2.053 on linux) and it seems that normally an AssertError is thrown on assert(false) (or assert(0)), but when compiled with dmd -release I get a segfault.. Furthermore I couldn't find any documentation on the assert(0) special case on the homepage (apart from posts in the NG). Cheers, - Daniel
 BTW: You may have noticed that people in this newsgroup usually write
 *below* the cited text they're referring to - could you do the same, for
 the sake of consistency and readability?  Thanks :-)
Thanks!
 Cheers,
 - Daniel


 On Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com> wrote:
 Am 29.05.2011 22:57, schrieb Brad Roberts:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of code
after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. After a couple years, I came to greatly regret it. Fatalness down in libraries became overused, particularly in layers that were libraries. In some ways it was abuse of fatal for things that shouldn't have been, but it's mere existence encouraged it's use. I really don't think it's the log libraries job to implement app termination behavior. My 2 cents, Brad
Also imagine the following scenario: You detect a fatal error and want to log it, while all the useful information you want to log is at hand. However afterwards you'd like to shut down the application gracefully to leave your data as consistent as possible or whatever, so you don't want the application to terminate immediately after fatal() but you want to do error handling yourself and terminate afterwards (and what you do for error handling/shutting downmay be dependent on the error, so just using scope(error) may not be the easiest choice). Cheers, - Daniel
May 29 2011
next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Sun, May 29, 2011 at 10:19 PM, Daniel Gibson <metalcaedes gmail.com> wro=
te:
 Am 30.05.2011 03:07, schrieb Jose Armando Garcia:
 On Sun, May 29, 2011 at 9:37 PM, Daniel Gibson <metalcaedes gmail.com> w=
rote:
 Am 30.05.2011 02:11, schrieb Jose Armando Garcia:
 Then use critical with all the exception handling techniques that D
 provide, try, scope, etc. Maybe critical should allow the throwing of
 user define exceptions with a meaningful default. What do people
 think?
I don't have much experience with logging frameworks, but is there really a *need* for a fatal log-function that terminates the program? I'd expect fatal() to produce a line like "<timestamp> FATAL: <yourmessage>" in the log (and I'd expect it to be logged when only fatal messages are activated) - but I wouldn't expect it to terminate the program. I'd just like to log the fatal error (yes, it is fatal, no=
t
 just critical or something) and terminate the program myself.
It is just a matter of semantic. We have, if you want, arbitrarily defined fatal to halt the program, critical to throw an exception, and error to just log. But we should think of them all as an error/bug in your program. Now if in a particular point of your application you want it to halt on such error then use fatal, if you want it to throw then use critical, if you want it to just log then use error. The power is in your hand. Fair enough?
Sounds ok, but for me it still "feels" strange that the logging library terminates my program or throws exception. And error() (probably?) will be logged differently than fatal(), even though both log an error and fatal() has the additional feature to terminate your program via assert(false); if I'm not mistaken. [OT:] What is assert(false); supposed to do, anyway? I think I've read it's supposed to terminates the program immediately without any cleanups (which is unfortunate for a logging library - at least destructors and scope guards should be executed so e.g. database connections are cleanly closed). I just tried it (with dmd 2.053 on linux) and it seems that normally an AssertError is thrown on assert(false) (or assert(0)), but when compiled with dmd -release I get a segfault.. Furthermore I couldn't find any documentation on the assert(0) special case on the homepage (apart from posts in the NG).
http://d-programming-language.org/expression.html#AssertExpression
 Cheers,
 - Daniel

 BTW: You may have noticed that people in this newsgroup usually write
 *below* the cited text they're referring to - could you do the same, fo=
r
 the sake of consistency and readability? =A0Thanks :-)
Thanks!
 Cheers,
 - Daniel


 On Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com>=
wrote:
 Am 29.05.2011 22:57, schrieb Brad Roberts:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because executio=
n of code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the=
application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is strippe=
d");
 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. =A0A=
fter a couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers =
that were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence e=
ncouraged it's use.
 I really don't think it's the log libraries job to implement app ter=
mination behavior.
 My 2 cents,
 Brad
Also imagine the following scenario: You detect a fatal error and wan=
t
 to log it, while all the useful information you want to log is at han=
d.
 However afterwards you'd like to shut down the application gracefully=
to
 leave your data as consistent as possible or whatever, so you don't w=
ant
 the application to terminate immediately after fatal() but you want t=
o
 do error handling yourself and terminate afterwards (and what you do =
for
 error handling/shutting downmay be dependent on the error, so just us=
ing
 scope(error) may not be the easiest choice).

 Cheers,
 - Daniel
May 29 2011
parent reply Daniel Gibson <metalcaedes gmail.com> writes:
Am 30.05.2011 03:40, schrieb Jose Armando Garcia:
 On Sun, May 29, 2011 at 10:19 PM, Daniel Gibson <metalcaedes gmail.com> wrote:
 [OT:] What is assert(false); supposed to do, anyway?
 I think I've read it's supposed to terminates the program immediately
 without any cleanups (which is unfortunate for a logging library - at
 least destructors and scope guards should be executed so e.g. database
 connections are cleanly closed).
 I just tried it (with dmd 2.053 on linux) and it seems that normally an
 AssertError is thrown on assert(false) (or assert(0)), but when compiled
 with dmd -release I get a segfault..
 Furthermore I couldn't find any documentation on the assert(0) special
 case on the homepage (apart from posts in the NG).
http://d-programming-language.org/expression.html#AssertExpression
Thanks. Strange that the site-search on digitalmars.com/d/ didn't find this when searching for "assert(0)".
May 29 2011
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-29 18:43, Daniel Gibson wrote:
 Am 30.05.2011 03:40, schrieb Jose Armando Garcia:
 On Sun, May 29, 2011 at 10:19 PM, Daniel Gibson <metalcaedes gmail.com> 
wrote:
 [OT:] What is assert(false); supposed to do, anyway?
 I think I've read it's supposed to terminates the program immediately
 without any cleanups (which is unfortunate for a logging library - at
 least destructors and scope guards should be executed so e.g. database
 connections are cleanly closed).
 I just tried it (with dmd 2.053 on linux) and it seems that normally an
 AssertError is thrown on assert(false) (or assert(0)), but when compiled
 with dmd -release I get a segfault..
 Furthermore I couldn't find any documentation on the assert(0) special
 case on the homepage (apart from posts in the NG).
http://d-programming-language.org/expression.html#AssertExpression
Thanks. Strange that the site-search on digitalmars.com/d/ didn't find this when searching for "assert(0)".
I don't think that the site search includes _anything_ in the documentation. I have no idea why. But from what I can tell, the search skips the documentation entirely. It's quite annoying really. - Jonathan M Davis
May 29 2011
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-29 18:19, Daniel Gibson wrote:
 Am 30.05.2011 03:07, schrieb Jose Armando Garcia:
 On Sun, May 29, 2011 at 9:37 PM, Daniel Gibson <metalcaedes gmail.com> 
wrote:
 Am 30.05.2011 02:11, schrieb Jose Armando Garcia:
 Then use critical with all the exception handling techniques that D
 provide, try, scope, etc. Maybe critical should allow the throwing of
 user define exceptions with a meaningful default. What do people
 think?
I don't have much experience with logging frameworks, but is there really a *need* for a fatal log-function that terminates the program? I'd expect fatal() to produce a line like "<timestamp> FATAL: <yourmessage>" in the log (and I'd expect it to be logged when only fatal messages are activated) - but I wouldn't expect it to terminate the program. I'd just like to log the fatal error (yes, it is fatal, not just critical or something) and terminate the program myself.
It is just a matter of semantic. We have, if you want, arbitrarily defined fatal to halt the program, critical to throw an exception, and error to just log. But we should think of them all as an error/bug in your program. Now if in a particular point of your application you want it to halt on such error then use fatal, if you want it to throw then use critical, if you want it to just log then use error. The power is in your hand. Fair enough?
Sounds ok, but for me it still "feels" strange that the logging library terminates my program or throws exception. And error() (probably?) will be logged differently than fatal(), even though both log an error and fatal() has the additional feature to terminate your program via assert(false); if I'm not mistaken. [OT:] What is assert(false); supposed to do, anyway? I think I've read it's supposed to terminates the program immediately without any cleanups (which is unfortunate for a logging library - at least destructors and scope guards should be executed so e.g. database connections are cleanly closed). I just tried it (with dmd 2.053 on linux) and it seems that normally an AssertError is thrown on assert(false) (or assert(0)), but when compiled with dmd -release I get a segfault.. Furthermore I couldn't find any documentation on the assert(0) special case on the homepage (apart from posts in the NG).
assert(0) is normal without -release, but once you compile with -release, it becomes the HLT instruction. So, it kills your program when you hit in. The idea is that it should _never_ happen - even in release mode - and that if it does, you _want_ your program to be killed. For instance, dmd typically inserts assert(0) at the end of functions that are supposed to return a value so that it catches any cases where you reach the end of a function without returning a value (though it probably doesn't bother if the last line in the function is a return statement). If the program were to continue at that point, it would be in a fatal state, so assert(0) kills the program. Now, obviously, that's a case where the compiler does it, but there are plenty of other cases where you might find it useful in your own code (such as an else branch or a default case statement which should never be reached). I don't know where it is in the online documentation, if it's there at all. It is in TDPL though. - Jonathan M Davis
May 29 2011
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 29 May 2011 16:57:52 -0400, Brad Roberts <braddr puremagic.com>  
wrote:

 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of  
 code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the  
 application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
Fatal can be with context. Let's say you have one thread that hits a fatal error, and another thread which is finishing out a DB transaction. Since logging the fatal error will kill the whole application, I now would have to write some sync function that all threads have to periodically call to make sure I don't kill some perfectly valid process that's unrelated to the fatal error. This seems like way more work to me than assert(0).
 At one time I used a log framework that included this behavior.  After a  
 couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers that  
 were libraries.  In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence  
 encouraged it's use.

 I really don't think it's the log libraries job to implement app  
 termination behavior.
Would it be possible to provide a "non-action" logger implementation? It seems that the logger instantiation is customizable on the call to initializeLogging. I'd say that should be the default as well (if you want certain actions, you can select the more proactive one). Also, one thing I liked about log4net is that I could redirect certain log levels to different loggers. That is, when I logged a fatal error, it went both to the log file and to the event log of the server. Other levels simply went to the log file. Is it possible to do stuff like that? I admit I haven't fully read the docs, I just briefly read them. -Steve
May 31 2011
parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, May 31, 2011 at 11:28 AM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Sun, 29 May 2011 16:57:52 -0400, Brad Roberts <braddr puremagic.com>
 wrote:

 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of
 code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
 application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
Fatal can be with context. =A0Let's say you have one thread that hits a f=
atal
 error, and another thread which is finishing out a DB transaction. =A0Sin=
ce
 logging the fatal error will kill the whole application, I now would have=
to
 write some sync function that all threads have to periodically call to ma=
ke
 sure I don't kill some perfectly valid process that's unrelated to the fa=
tal
 error. =A0This seems like way more work to me than assert(0).
For some applications fatal makes sense for others critical is better and for others error is better. Use the one that fits your application or library. Having said that you can replace the assert(false) by using a fatal handler the only requirement on this handler is that it doesn't return or throw; otherwise std.log will assert(false).
 At one time I used a log framework that included this behavior. =A0After=
a
 couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers that
 were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence
 encouraged it's use.

 I really don't think it's the log libraries job to implement app
 termination behavior.
Would it be possible to provide a "non-action" logger implementation? =A0=
It
 seems that the logger instantiation is customizable on the call to
 initializeLogging. =A0I'd say that should be the default as well (if you =
want
 certain actions, you can select the more proactive one).
This is not possible. Can you please motivate you requirement? The intent is that some of the semantic of fatal, critical, error, warning, info and verbose is set by the frontend to std.log and it doesn't change when the user changes the backend. I want to give the user some kind of guarantee on how the library behaves.
 Also, one thing I liked about log4net is that I could redirect certain lo=
g
 levels to different loggers. =A0That is, when I logged a fatal error, it =
went
 both to the log file and to the event log of the server. =A0Other levels
 simply went to the log file. =A0Is it possible to do stuff like that? =A0=
I admit
 I haven't fully read the docs, I just briefly read them.
Yes, we can do that in a future version with a configuration option that logs to syslog in posix and event log in windows.
 -Steve
May 31 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 31 May 2011 12:28:12 -0400, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Tue, May 31, 2011 at 11:28 AM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Sun, 29 May 2011 16:57:52 -0400, Brad Roberts <braddr puremagic.com>
 wrote:

 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution  
 of
 code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
 application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is  
 stripped");

 This is needless and bug-prone. Fatal is fatal.
Fatal can be with context. Let's say you have one thread that hits a fatal error, and another thread which is finishing out a DB transaction. Since logging the fatal error will kill the whole application, I now would have to write some sync function that all threads have to periodically call to make sure I don't kill some perfectly valid process that's unrelated to the fatal error. This seems like way more work to me than assert(0).
For some applications fatal makes sense for others critical is better and for others error is better. Use the one that fits your application or library. Having said that you can replace the assert(false) by using a fatal handler the only requirement on this handler is that it doesn't return or throw; otherwise std.log will assert(false).
Again, this sounds way too complicated for what it's giving you (avoiding having to forcibly kill your application if that's what you desire). If I had to choose from your options, I'd use neither critical nor fatal. I'd probably just stick with the higher levels, and start putting my own levels in as strings to avoid what I'd consider to be "buggy" behavior... From my own experience, I almost never *never* use a forced kill. A graceful shutdown works much better. Remember that a 'fatal' error is not so much a "this program can't continue because it's not sane," but a "this program cannot continue because something is misconfigured, etc." This does not warrant raw destruction. A better option is to make the default "handler" assert(0), and let you override that when you set a new one. This should not be too difficult (only need assert(0) in one place). Flexibility in this regard is way more valuable than consistency between applications. I don't see the reasoning for the hard requirements. Is it simply because it's this way in glog?
 At one time I used a log framework that included this behavior.  After  
 a
 couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers  
 that
 were libraries.  In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence
 encouraged it's use.

 I really don't think it's the log libraries job to implement app
 termination behavior.
Would it be possible to provide a "non-action" logger implementation? It seems that the logger instantiation is customizable on the call to initializeLogging. I'd say that should be the default as well (if you want certain actions, you can select the more proactive one).
This is not possible. Can you please motivate you requirement? The intent is that some of the semantic of fatal, critical, error, warning, info and verbose is set by the frontend to std.log and it doesn't change when the user changes the backend. I want to give the user some kind of guarantee on how the library behaves.
Sure, the requirement is that the logger never ever alters my program's behavior without my permission. I'm using the logger to log data, not to create code paths. If I want a function that logs a message and then halts the application, I can write one of those (you can even include it as part of std.log!). It's like having fopen halt your application if it can't open a file. Essentially I think it is an egregious mistake to tie whole-application functionality to logging. I don't care of the convenience, a logger is for logging, nothing else. For sure, if std.log implements mandatory halting, my belief is another competitor log library will certainly get the lion's share of users, even if it's third party. -Steve
May 31 2011
next sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer
<schveiguy yahoo.com> wrote:
 On Tue, 31 May 2011 12:28:12 -0400, Jose Armando Garcia <jsancio gmail.co=
m>
 wrote:

 On Tue, May 31, 2011 at 11:28 AM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Sun, 29 May 2011 16:57:52 -0400, Brad Roberts <braddr puremagic.com>
 wrote:

 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution =
of
 code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
 application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped"=
);
 This is needless and bug-prone. Fatal is fatal.
Fatal can be with context. =A0Let's say you have one thread that hits a fatal error, and another thread which is finishing out a DB transaction. =A0S=
ince
 logging the fatal error will kill the whole application, I now would ha=
ve
 to
 write some sync function that all threads have to periodically call to
 make
 sure I don't kill some perfectly valid process that's unrelated to the
 fatal
 error. =A0This seems like way more work to me than assert(0).
For some applications fatal makes sense for others critical is better and for others error is better. Use the one that fits your application or library. Having said that you can replace the assert(false) by using a fatal handler the only requirement on this handler is that it doesn't return or throw; otherwise std.log will assert(false).
Again, this sounds way too complicated for what it's giving you (avoiding having to forcibly kill your application if that's what you desire). =A0I=
f I
 had to choose from your options, I'd use neither critical nor fatal. =A0I=
'd
 probably just stick with the higher levels, and start putting my own leve=
ls
 in as strings to avoid what I'd consider to be "buggy" behavior...

 From my own experience, I almost never *never* use a forced kill. =A0A
 graceful shutdown works much better. =A0Remember that a 'fatal' error is =
not
 so much a "this program can't continue because it's not sane," but a "thi=
s
 program cannot continue because something is misconfigured, etc." =A0This=
does
 not warrant raw destruction.
That is probably because most programmers write web application in which independent request/processing are all handle by the same process. So by definition since requests are independent it is unfair for one request to affect another request (by asserting) because they share the same process. Not everyone writes application using that model. If your programming model is such (or architecture if you prefer that word ;), then yes using fatal("") is not wise but maybe critical("") and error("") is. Let say instead you are writing a multi-process embedded system for the mars-rover and your subsystem deals with propulsion then maybe you do want to fatal("") or assert(false) instead of driving down a cliff even though the camera sub-system wants to take a picture of a pretty rock.
 A better option is to make the default "handler" assert(0), and let you
 override that when you set a new one. =A0This should not be too difficult
 (only need assert(0) in one place).

 Flexibility in this regard is way more valuable than consistency between
 applications. =A0I don't see the reasoning for the hard requirements. =A0=
Is it
 simply because it's this way in glog?
This is a matter of who makes the decision and has the domain knowledge. I say that the decision if something should assert or throw or just logs is up to the module coder. The coder that wrote fatal("") for example. Not the person that configures the logger/writer which in many systems knows nothing about the intricacies of the application or modules.
 At one time I used a log framework that included this behavior. =A0Aft=
er a
 couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers th=
at
 were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence
 encouraged it's use.

 I really don't think it's the log libraries job to implement app
 termination behavior.
Would it be possible to provide a "non-action" logger implementation? =
=A0It
 seems that the logger instantiation is customizable on the call to
 initializeLogging. =A0I'd say that should be the default as well (if yo=
u
 want
 certain actions, you can select the more proactive one).
This is not possible. Can you please motivate you requirement? The intent is that some of the semantic of fatal, critical, error, warning, info and verbose is set by the frontend to std.log and it doesn't change when the user changes the backend. I want to give the user some kind of guarantee on how the library behaves.
Sure, the requirement is that the logger never ever alters my program's behavior without my permission. =A0I'm using the logger to log data, not =
to
 create code paths. =A0If I want a function that logs a message and then h=
alts
 the application, I can write one of those (you can even include it as par=
t
 of std.log!). =A0It's like having fopen halt your application if it can't=
open
 a file.
As a exercise, try to write such a function that gives you the same flexibility of std.log. E.g. willLog, when(), compile time disabling, etc. and I think you will end up with something similar to std.log!
 Essentially I think it is an egregious mistake to tie whole-application
 functionality to logging. =A0I don't care of the convenience, a logger is=
for
 logging, nothing else. =A0For sure, if std.log implements mandatory halti=
ng,
 my belief is another competitor log library will certainly get the lion's
 share of users, even if it's third party.
I would like to be flexible and meet your requirements but what is the problem of not using fatal if you don't want to assert and not using critical if you don't want to throw and instead use error if you just want to log?
 -Steve
May 31 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 31 May 2011 14:10:20 -0400, Jose Armando Garcia  
<jsancio gmail.com> wrote:

 On Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 Again, this sounds way too complicated for what it's giving you  
 (avoiding
 having to forcibly kill your application if that's what you desire).  
  If I
 had to choose from your options, I'd use neither critical nor fatal.  
  I'd
 probably just stick with the higher levels, and start putting my own  
 levels
 in as strings to avoid what I'd consider to be "buggy" behavior...

 From my own experience, I almost never *never* use a forced kill.  A
 graceful shutdown works much better.  Remember that a 'fatal' error is  
 not
 so much a "this program can't continue because it's not sane," but a  
 "this
 program cannot continue because something is misconfigured, etc."  This  
 does
 not warrant raw destruction.
That is probably because most programmers write web application in which independent request/processing are all handle by the same process. So by definition since requests are independent it is unfair for one request to affect another request (by asserting) because they share the same process. Not everyone writes application using that model. If your programming model is such (or architecture if you prefer that word ;), then yes using fatal("") is not wise but maybe critical("") and error("") is.
If critical throws, then it is also of no use. I want to control when exceptions are thrown, I don't want exceptions or program halting to be the tax for using the logging facility. I can see this pattern emerging: try { logCritical("critical error encountered!"); } catch(Exception e){} // stupid std.log...
 Let say instead you are writing a multi-process embedded system for
 the mars-rover and your subsystem deals with propulsion then maybe you
 do want to fatal("") or assert(false) instead of driving down a cliff
 even though the camera sub-system wants to take a picture of a pretty
 rock.
Then I do assert(0) instead? Why the fuck do I bother logging? Assert as soon as possible to avoid falling off a cliff!
 A better option is to make the default "handler" assert(0), and let you
 override that when you set a new one.  This should not be too difficult
 (only need assert(0) in one place).

 Flexibility in this regard is way more valuable than consistency between
 applications.  I don't see the reasoning for the hard requirements.  Is  
 it
 simply because it's this way in glog?
This is a matter of who makes the decision and has the domain knowledge. I say that the decision if something should assert or throw or just logs is up to the module coder. The coder that wrote fatal("") for example. Not the person that configures the logger/writer which in many systems knows nothing about the intricacies of the application or modules.
Again, one has the ability to do fatal(""); assert(0); or myFunctionThatLogsThenAsserts("");
 Sure, the requirement is that the logger never ever alters my program's
 behavior without my permission.  I'm using the logger to log data, not  
 to
 create code paths.  If I want a function that logs a message and then  
 halts
 the application, I can write one of those (you can even include it as  
 part
 of std.log!).  It's like having fopen halt your application if it can't  
 open
 a file.
As a exercise, try to write such a function that gives you the same flexibility of std.log. E.g. willLog, when(), compile time disabling, etc. and I think you will end up with something similar to std.log!
I'm not complaining about anything but the assert(0) and throwing an exception on fatal and critical error respectively. The other facilities I haven't examined, but sound reasonable to me.
 Essentially I think it is an egregious mistake to tie whole-application
 functionality to logging.  I don't care of the convenience, a logger is  
 for
 logging, nothing else.  For sure, if std.log implements mandatory  
 halting,
 my belief is another competitor log library will certainly get the  
 lion's
 share of users, even if it's third party.
I would like to be flexible and meet your requirements but what is the problem of not using fatal if you don't want to assert and not using critical if you don't want to throw and instead use error if you just want to log?
Because some shmuck will use fatal or critical in a library function, not understanding what a grave mistake it is, and then I have to go pester it can kill your program, then I think why is it there? You are conflating logging a fatal condition with destroying the program. The two functions are separate, and I would argue that a log level should not be reserved for cases where you want to assert(0) or throw an exception. You can create an additional function that ties these together so easily, I can't understand why we are having this debate. -Steve
May 31 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 5/31/11 1:32 PM, Steven Schveighoffer wrote:
 On Tue, 31 May 2011 14:10:20 -0400, Jose Armando Garcia
 <jsancio gmail.com> wrote:

 On Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 Again, this sounds way too complicated for what it's giving you
 (avoiding
 having to forcibly kill your application if that's what you desire).
 If I
 had to choose from your options, I'd use neither critical nor fatal. I'd
 probably just stick with the higher levels, and start putting my own
 levels
 in as strings to avoid what I'd consider to be "buggy" behavior...

 From my own experience, I almost never *never* use a forced kill. A
 graceful shutdown works much better. Remember that a 'fatal' error is
 not
 so much a "this program can't continue because it's not sane," but a
 "this
 program cannot continue because something is misconfigured, etc."
 This does
 not warrant raw destruction.
That is probably because most programmers write web application in which independent request/processing are all handle by the same process. So by definition since requests are independent it is unfair for one request to affect another request (by asserting) because they share the same process. Not everyone writes application using that model. If your programming model is such (or architecture if you prefer that word ;), then yes using fatal("") is not wise but maybe critical("") and error("") is.
If critical throws, then it is also of no use. I want to control when exceptions are thrown, I don't want exceptions or program halting to be the tax for using the logging facility. I can see this pattern emerging: try { logCritical("critical error encountered!"); } catch(Exception e){} // stupid std.log...
I don't understand this. You are at the same time using logCritical, which has as its MAIN distinction from logError the fact that it throws, to then complain about that very distinction and manually arrange things to be identical. Why not use logError? There are two logs that behave almost the same: logInfo and logError. I think that should be enough choice. Then we have two logs that add value: logCritical and logFatal. What is wrong about that? Andrei
May 31 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 31 May 2011 14:48:57 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail erdani.org> wrote:

 On 5/31/11 1:32 PM, Steven Schveighoffer wrote:
 On Tue, 31 May 2011 14:10:20 -0400, Jose Armando Garcia
 <jsancio gmail.com> wrote:

 On Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 Again, this sounds way too complicated for what it's giving you
 (avoiding
 having to forcibly kill your application if that's what you desire).
 If I
 had to choose from your options, I'd use neither critical nor fatal.  
 I'd
 probably just stick with the higher levels, and start putting my own
 levels
 in as strings to avoid what I'd consider to be "buggy" behavior...

 From my own experience, I almost never *never* use a forced kill. A
 graceful shutdown works much better. Remember that a 'fatal' error is
 not
 so much a "this program can't continue because it's not sane," but a
 "this
 program cannot continue because something is misconfigured, etc."
 This does
 not warrant raw destruction.
That is probably because most programmers write web application in which independent request/processing are all handle by the same process. So by definition since requests are independent it is unfair for one request to affect another request (by asserting) because they share the same process. Not everyone writes application using that model. If your programming model is such (or architecture if you prefer that word ;), then yes using fatal("") is not wise but maybe critical("") and error("") is.
If critical throws, then it is also of no use. I want to control when exceptions are thrown, I don't want exceptions or program halting to be the tax for using the logging facility. I can see this pattern emerging: try { logCritical("critical error encountered!"); } catch(Exception e){} // stupid std.log...
I don't understand this. You are at the same time using logCritical, which has as its MAIN distinction from logError the fact that it throws, to then complain about that very distinction and manually arrange things to be identical.
I'm operating under the assumption that logCritical and logFatal are at a different log level (i.e. the primary function of a logging facility is to have different degrees of importance, which you can turn on or off depending on the level set). Is that not the case? So I can't have a situation where logError does nothing, but logCritical logs a message? If that is not the case, I have no problem with the functionality. I will re-examine the API more closely. I just did a quick skim after reading Brad's message. -Steve
May 31 2011
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 31 May 2011 15:09:07 -0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 On Tue, 31 May 2011 14:48:57 -0400, Andrei Alexandrescu  
 <SeeWebsiteForEmail erdani.org> wrote:
 I'm operating under the assumption that logCritical and logFatal are at  
 a different log level (i.e. the primary function of a logging facility  
 is to have different degrees of importance, which you can turn on or off  
 depending on the level set).  Is that not the case?  So I can't have a  
 situation where logError does nothing, but logCritical logs a message?
Rereading the docs, it seems that fatal is actually a separate level, so I still assert this is not a good design. I should be able to access all levels without having the program abort or throw an exception. I also note that critical is nowhere to be seen in the docs. Am I missing something? If we change fatal and critical to be the same level as error (and enabled/disabled with error), I think it would be more sensible than what you have proposed. It could be argued that it's not enough levels. Typically, I've only needed 4 levels with logging: fatal errors -- print a message then exit the application (gracefully!). You cannot disable this level. non-fatal errors -- print a message but the program continues. info -- print a message for information so the flow of execution can be followed (i.e. xyz logged in, xyz executed this program, etc.) debug -- print all details, down to printouts of internal structures/protocols. I've never had much use for a warning level. It helps with the debug level to allow selectively turning on levels in certain areas. For example, I had an application which was a tftp server as well as a server for another protocol. When I was writing the TFTP portion, I needed to see the exact packets sent over the wire, but for TFTP only. It was easy to do with log4net, I could just configure that class' logger to be at the debug level (without recompilation). But I wouldn't consider such a feature a requirement for a logging library. I think we should try and focus on the most common and useful aspects of logging for the built-in logger. Seems similar to unittest -- good enough for most cases, and simple enough that it's used everywhere. -Steve
May 31 2011
parent Mike Wey <mike-wey example.com> writes:
On 05/31/2011 09:29 PM, Steven Schveighoffer wrote:
 On Tue, 31 May 2011 15:09:07 -0400, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:

 On Tue, 31 May 2011 14:48:57 -0400, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 I'm operating under the assumption that logCritical and logFatal are
 at a different log level (i.e. the primary function of a logging
 facility is to have different degrees of importance, which you can
 turn on or off depending on the level set). Is that not the case? So I
 can't have a situation where logError does nothing, but logCritical
 logs a message?
Rereading the docs, it seems that fatal is actually a separate level, so I still assert this is not a good design. I should be able to access all levels without having the program abort or throw an exception. I also note that critical is nowhere to be seen in the docs. Am I missing something? If we change fatal and critical to be the same level as error (and enabled/disabled with error), I think it would be more sensible than what you have proposed. It could be argued that it's not enough levels. Typically, I've only needed 4 levels with logging: fatal errors -- print a message then exit the application (gracefully!). You cannot disable this level. non-fatal errors -- print a message but the program continues. info -- print a message for information so the flow of execution can be followed (i.e. xyz logged in, xyz executed this program, etc.) debug -- print all details, down to printouts of internal structures/protocols. I've never had much use for a warning level. -Steve
I agree with Steven that terminating the app when logging a fatal message is a horrible design choice. You would almost always want to stop gracefully, witch you can't with the current fatal log. A logging library should log messages, is shouldn't control the flow of the application. -- Mike Wey
May 31 2011
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
On Tue, May 31, 2011 at 3:10 PM, Jose Armando Garcia <jsancio gmail.com> wr=
ote:
 On Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Tue, 31 May 2011 12:28:12 -0400, Jose Armando Garcia <jsancio gmail.c=
om>
 wrote:

 On Tue, May 31, 2011 at 11:28 AM, Steven Schveighoffer
 <schveiguy yahoo.com> wrote:
 On Sun, 29 May 2011 16:57:52 -0400, Brad Roberts <braddr puremagic.com=
 wrote:

 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution=
of
 code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the
 application regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped=
");
 This is needless and bug-prone. Fatal is fatal.
Fatal can be with context. =A0Let's say you have one thread that hits =
a
 fatal
 error, and another thread which is finishing out a DB transaction. =A0=
Since
 logging the fatal error will kill the whole application, I now would h=
ave
 to
 write some sync function that all threads have to periodically call to
 make
 sure I don't kill some perfectly valid process that's unrelated to the
 fatal
 error. =A0This seems like way more work to me than assert(0).
For some applications fatal makes sense for others critical is better and for others error is better. Use the one that fits your application or library. Having said that you can replace the assert(false) by using a fatal handler the only requirement on this handler is that it doesn't return or throw; otherwise std.log will assert(false).
Again, this sounds way too complicated for what it's giving you (avoidin=
g
 having to forcibly kill your application if that's what you desire). =A0=
If I
 had to choose from your options, I'd use neither critical nor fatal. =A0=
I'd
 probably just stick with the higher levels, and start putting my own lev=
els
 in as strings to avoid what I'd consider to be "buggy" behavior...

 From my own experience, I almost never *never* use a forced kill. =A0A
 graceful shutdown works much better. =A0Remember that a 'fatal' error is=
not
 so much a "this program can't continue because it's not sane," but a "th=
is
 program cannot continue because something is misconfigured, etc." =A0Thi=
s does
 not warrant raw destruction.
That is probably because most programmers write web application in which independent request/processing are all handle by the same process. So by definition since requests are independent it is unfair for one request to affect another request (by asserting) because they share the same process. =A0Not everyone writes application using that model. If your programming model is such (or architecture if you prefer that word ;), then yes using fatal("") is not wise but maybe critical("") and error("") is. Let say instead you are writing a multi-process embedded system for the mars-rover and your subsystem deals with propulsion then maybe you do want to fatal("") or assert(false) instead of driving down a cliff even though the camera sub-system wants to take a picture of a pretty rock.
 A better option is to make the default "handler" assert(0), and let you
 override that when you set a new one. =A0This should not be too difficul=
t
 (only need assert(0) in one place).

 Flexibility in this regard is way more valuable than consistency between
 applications. =A0I don't see the reasoning for the hard requirements. =
=A0Is it
 simply because it's this way in glog?
This is a matter of who makes the decision and has the domain knowledge. I say that the decision if something should assert or throw or just logs is up to the module coder. The coder that wrote fatal("") for example. Not the person that configures the logger/writer which in many systems knows nothing about the intricacies of the application or modules.
 At one time I used a log framework that included this behavior. =A0Af=
ter a
 couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers t=
hat
 were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence
 encouraged it's use.

 I really don't think it's the log libraries job to implement app
 termination behavior.
Would it be possible to provide a "non-action" logger implementation? =
=A0It
 seems that the logger instantiation is customizable on the call to
 initializeLogging. =A0I'd say that should be the default as well (if y=
ou
 want
 certain actions, you can select the more proactive one).
This is not possible. Can you please motivate you requirement? The intent is that some of the semantic of fatal, critical, error, warning, info and verbose is set by the frontend to std.log and it doesn't change when the user changes the backend. I want to give the user some kind of guarantee on how the library behaves.
Sure, the requirement is that the logger never ever alters my program's behavior without my permission. =A0I'm using the logger to log data, not=
to
 create code paths. =A0If I want a function that logs a message and then =
halts
 the application, I can write one of those (you can even include it as pa=
rt
 of std.log!). =A0It's like having fopen halt your application if it can'=
t open
 a file.
As a exercise, try to write such a function that gives you the same flexibility of std.log. E.g. willLog, when(), compile time disabling, etc. and I think you will end up with something similar to std.log!
 Essentially I think it is an egregious mistake to tie whole-application
 functionality to logging. =A0I don't care of the convenience, a logger i=
s for
 logging, nothing else. =A0For sure, if std.log implements mandatory halt=
ing,
 my belief is another competitor log library will certainly get the lion'=
s
 share of users, even if it's third party.
I would like to be flexible and meet your requirements but what is the problem of not using fatal if you don't want to assert and not using critical if you don't want to throw and instead use error if you just want to log?
 -Steve
Btw, I think a similar argument can be made for assert and enforce for example. If you want to always throw use enforce(). If you want to always halt use assert(false). If you want to only throw in debug use assert(cond). Similarly the coder that wrote the module knows which is correct for its module not the person that compiles or runs the code.
May 31 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-05-29 10:25, Jose Armando Garcia wrote:
 Thanks. Comments below.
 
 On Sun, May 29, 2011 at 12:44 PM, Andrei Alexandrescu
 <SeeWebsiteForEmail erdani.org> wrote:
 4. initLogging and initializeLogging are highly confusing names. Overload
 them to share the same name, or rename one.
Yeah. I don't like this either but if I remember correctly D/dmd doesn't let me overload a function with a template. I'll look into this again. Maybe I can figure out a way to make initLogging a template and hence rename initializeLogging.
Generally, the fix to that is to templatize the function which isn't templatized. That could mean templatizing its argument and then using template constrains to enforce that it's exactly the same type that it was before rather than increasing the number of types that it can take, but it does fix the overloading problem. Still, dmd really should be fixed to get rid of this issue. - Jonathan M Davis
May 29 2011
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
That is a valid point. I think if we add critical and put a suggestion
in the doc that fatal should only be used in extreme cases because it
cannot be disabled. Then that should solve the problem. Going from
fatal to critical to error is only a regular expression away.

On Sun, May 29, 2011 at 5:57 PM, Brad Roberts <braddr puremagic.com> wrote:
 On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:
 1. The fatal log should never be stripped. This is because execution of =
code after using fatal depends on compile-time
 flags, which is unacceptable. Logging to fatal should terminate the appl=
ication regardless of circumstances. Otherwise
 people would need to write things like:

 fatal("blah");
 assert(0, "Execution cannot continue even though logging is stripped");

 This is needless and bug-prone. Fatal is fatal.
At one time I used a log framework that included this behavior. =A0After =
a couple years, I came to greatly regret it.
 Fatalness down in libraries became overused, particularly in layers that =
were libraries. =A0In some ways it was abuse of
 fatal for things that shouldn't have been, but it's mere existence encour=
aged it's use.
 I really don't think it's the log libraries job to implement app terminat=
ion behavior.
 My 2 cents,
 Brad
May 29 2011
prev sibling parent reply "Masahiro Nakagawa" <repeatedly gmail.com> writes:
On Sun, 29 May 2011 08:40:16 +0900, Jose Armando Garcia  
<jsancio gmail.com> 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. The
 module will work without the changes but you wont to see thread ids in
 your log messages. I will look into sending a pull request to
 druntime, in the meantime you can apply the attached patch to your
 druntime if you want to see thread ids in the log.

 Let me know if you have any comments or suggestions! Thanks,
- every, first, after These are useful? I can't image the use cases. I think 'when(cond)' is enough. - fatal, error and other global variables 'logger.error("hoge")' seems to be better than 'error("hoge")'. error("hoge") is not clear in complicated context. In addition, I think defining general name variables on global scope is bad. Masahiro
May 29 2011
next sibling parent David Nadlinger <see klickverbot.at> writes:
On 5/29/11 11:43 PM, Masahiro Nakagawa wrote:
 - every, first, after
 These are useful? I can't image the use cases.
 I think 'when(cond)' is enough.
These can be quite useful when logging from a function that is called really frequently, where logging all calls would just flood the logs, but you want to output some stats occasionally. David
May 29 2011
prev sibling parent Jose Armando Garcia <jsancio gmail.com> writes:
Comments below.

Thanks!

2011/5/29 Masahiro Nakagawa <repeatedly gmail.com>:
 On Sun, 29 May 2011 08:40:16 +0900, Jose Armando Garcia <jsancio gmail.com>
 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. The
 module will work without the changes but you wont to see thread ids in
 your log messages. I will look into sending a pull request to
 druntime, in the meantime you can apply the attached patch to your
 druntime if you want to see thread ids in the log.

 Let me know if you have any comments or suggestions! Thanks,
- every, first, after These are useful? I can't image the use cases. I think 'when(cond)' is enough.
Let's say you have a loop or a function that gets executed many times but you only want to see the message every number of times or just the first time. I had to do this many times myself. Why not just provide a standard way of doing this?
 - fatal, error and other global variables
 'logger.error("hoge")' seems to be better than 'error("hoge")'.
 error("hoge") is not clear in complicated context. In addition,
 I think defining general name variables on global scope is bad.
Those symbols are declared in the std.log namespace or module not in the global namespace. You can use: static import std.log; //... std.log.error("hoge"); or import log = std.log; // ... log.error("hoge"); Take a look at module imports at: http://d-programming-language.org/module.html#ImportDeclaration
 Masahiro
May 29 2011