digitalmars.D - std.log available for viewing
- Jose Armando Garcia (11/11) May 28 2011 The implementation and documentation for std.log is ready for viewing.
- Jacob Carlborg (14/25) May 29 2011 Why is everyone that contribute with a std.log implementation keep
- Andrei Alexandrescu (12/23) May 29 2011 I think that's because command-line configuration is very commonly
- Jacob Carlborg (13/36) May 29 2011 I also recognized "vlog" as "verbose log" but the first time I saw
- Andrei Alexandrescu (5/7) May 29 2011 Again, consistency is a relation, not a value, i.e. consistent with
- Jacob Carlborg (8/15) May 29 2011 Why are you so fixed with glog, yes I know you think it's a great
- Andrei Alexandrescu (6/21) May 29 2011 That would be circular logic. I'm sure you are referring to consistency
- Daniel Gibson (9/36) May 29 2011 IMHO consistency with Phobos' naming conventions is more important than
- Jacob Carlborg (7/29) May 30 2011 Yes, it would be more consistent with the rest of Phobos. But if we just...
- Jose Armando Garcia (26/53) May 29 2011 Configuring through the command line is optional for example the
- Jacob Carlborg (6/31) May 29 2011 I guess that that is acceptable. BTW, what happens if you start logging
- Jose Armando Garcia (7/49) May 29 2011 By default the module will read the command line arguments looking for
- Jacob Carlborg (4/9) May 30 2011 Sounds reasonable.
- Walter Bright (17/19) May 29 2011 What rolls down stairs
- Andrej Mitrovic (4/24) May 29 2011 I expect this to be incorporated as the de-facto default error message
- Jose Armando Garcia (9/30) May 30 2011 Walter, what do you think about adding __MODULE__ to the language? It
- KennyTM~ (22/29) May 30 2011 I'd recommend making __MODULE__ return the actual module object instead
- Timon Gehr (9/41) May 30 2011 While this is already quite useful, stuff like this wont work:
- KennyTM~ (4/52) May 30 2011 __MODULE__ requires minimal change because a module symbol is
- Bruno Medeiros (7/39) Jun 02 2011 Why do we need __MODULE__ at all for that, a new key does not seems
- KennyTM~ (3/47) Jun 02 2011 __MODULE__ is evaluated at instantiation site, like __FILE__ and
- Bruno Medeiros (5/54) Jun 02 2011 Ah, I see what you mean, when they are used as default arguments in
- Jacob Carlborg (4/48) Jun 02 2011 .stringof doesn't return the full module name, just the last part.
- Walter Bright (2/6) May 30 2011 I don't know. I know I am leery of just adding more and more stuff like ...
- Andrei Alexandrescu (4/11) May 30 2011 Gnu's and subsequently C++0x's experience with __FUNCTION__ and
- Robert Clipsham (8/20) May 30 2011 Pull request #75 adds __traits(moduleOf) which allows you to get the
- KennyTM~ (7/27) May 30 2011 The advantage of __NONSENSE__ is that, by convention, the token will be
- Andrei Alexandrescu (34/45) May 29 2011 1. The fatal log should never be stripped. This is because execution of
- Jose Armando Garcia (32/79) May 29 2011 Thanks. Comments below.
- Andrei Alexandrescu (4/5) May 29 2011 [snip]
- Brad Roberts (7/15) May 29 2011 At one time I used a log framework that included this behavior. After a...
- Daniel Gibson (11/29) May 29 2011 Also imagine the following scenario: You detect a fatal error and want
- Jose Armando Garcia (12/41) May 29 2011 Then use critical with all the exception handling techniques that D
- Daniel Gibson (13/51) May 29 2011 I don't have much experience with logging frameworks, but is there
- Jose Armando Garcia (22/73) May 29 2011 It is just a matter of semantic. We have, if you want, arbitrarily
- Daniel Gibson (18/87) May 29 2011 Sounds ok, but for me it still "feels" strange that the logging library
- Jose Armando Garcia (21/108) May 29 2011 rote:
- Daniel Gibson (3/17) May 29 2011 Thanks. Strange that the site-search on digitalmars.com/d/ didn't find
- Jonathan M Davis (6/23) May 29 2011 I don't think that the site search includes _anything_ in the documentat...
- Jonathan M Davis (17/57) May 29 2011 assert(0) is normal without -release, but once you compile with -release...
- Steven Schveighoffer (19/38) May 31 2011 Fatal can be with context. Let's say you have one thread that hits a
- Jose Armando Garcia (25/64) May 31 2011 atal
- Steven Schveighoffer (30/91) May 31 2011 Again, this sounds way too complicated for what it's giving you (avoidin...
- Jose Armando Garcia (50/136) May 31 2011 m>
- Steven Schveighoffer (28/104) May 31 2011 If critical throws, then it is also of no use. I want to control when
- Andrei Alexandrescu (10/50) May 31 2011 I don't understand this. You are at the same time using logCritical,
- Steven Schveighoffer (11/62) May 31 2011 I'm operating under the assumption that logCritical and logFatal are at ...
- Steven Schveighoffer (30/37) May 31 2011 Rereading the docs, it seems that fatal is actually a separate level, so...
- Mike Wey (8/36) May 31 2011 I agree with Steven that terminating the app when logging a fatal
- Jose Armando Garcia (33/157) May 31 2011 om>
- Jonathan M Davis (8/19) May 29 2011 Generally, the fix to that is to templatize the function which isn't
- Jose Armando Garcia (11/26) May 29 2011 That is a valid point. I think if we add critical and put a suggestion
- Masahiro Nakagawa (10/20) May 29 2011 - every, first, after
- David Nadlinger (5/8) May 29 2011 These can be quite useful when logging from a function that is called
- Jose Armando Garcia (18/40) May 29 2011 Comments below.
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
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, -JoseWhy 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
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
On 2011-05-29 17:06, Andrei Alexandrescu wrote:On 5/29/11 5:07 AM, Jacob Carlborg wrote: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 CarlborgWhy 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
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
On 2011-05-29 20:34, Andrei Alexandrescu wrote:On 05/29/2011 01:32 PM, Jacob Carlborg wrote: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 CarlborgSometimes 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
On 05/29/2011 01:42 PM, Jacob Carlborg wrote:On 2011-05-29 20:34, Andrei Alexandrescu wrote:This is not "thinking", it's a simple name choice.On 05/29/2011 01:32 PM, Jacob Carlborg wrote: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.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. AndreiCan 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
Am 29.05.2011 23:07, schrieb Andrei Alexandrescu:On 05/29/2011 01:42 PM, Jacob Carlborg wrote: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.On 2011-05-29 20:34, Andrei Alexandrescu wrote:This is not "thinking", it's a simple name choice.On 05/29/2011 01:32 PM, Jacob Carlborg wrote: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.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. AndreiCan 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.AndreiCheers, - Daniel
May 29 2011
On 2011-05-29 23:07, Andrei Alexandrescu wrote:On 05/29/2011 01:42 PM, Jacob Carlborg wrote: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 CarlborgOn 2011-05-29 20:34, Andrei Alexandrescu wrote:This is not "thinking", it's a simple name choice.On 05/29/2011 01:32 PM, Jacob Carlborg wrote: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.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. AndreiCan 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 30 2011
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, -JoseWhy 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
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, -JoseI 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
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:oesConfiguring 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, -JoseI guess that that is acceptable. BTW, what happens if you start logging without passing any command line arguments or initializing the library? D=it have a default behavior making it usable? -- /Jacob Carlborg
May 29 2011
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
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
On 5/29/11, Walter Bright <newshound2 digitalmars.com> wrote:On 5/29/2011 3:07 AM, Jacob Carlborg wrote: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!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
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: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, -JoseWhy 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 30 2011
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, -JoseI'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
On May 31, 11 00:59, Jose Armando Garcia wrote: [snip]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. TimonWalter, 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, -JoseI'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
On May 31, 11 03:56, Timon Gehr wrote:__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__.On May 31, 11 00:59, Jose Armando Garcia wrote: [snip]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. TimonWalter, 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, -JoseI'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
On 30/05/2011 18:41, KennyTM~ wrote:On May 31, 11 00:59, Jose Armando Garcia wrote: [snip]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 EngineerWalter, 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, -JoseI'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); } ...
Jun 02 2011
On Jun 2, 11 22:47, Bruno Medeiros wrote:On 30/05/2011 18:41, KennyTM~ wrote:__MODULE__ is evaluated at instantiation site, like __FILE__ and __LINE__, while .stringof is evaluated at definition site.On May 31, 11 00:59, Jose Armando Garcia wrote: [snip]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.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, -JoseI'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); } ...
Jun 02 2011
On 02/06/2011 16:28, KennyTM~ wrote:On Jun 2, 11 22:47, Bruno Medeiros wrote: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 EngineerOn 30/05/2011 18:41, KennyTM~ wrote:__MODULE__ is evaluated at instantiation site, like __FILE__ and __LINE__, while .stringof is evaluated at definition site.On May 31, 11 00:59, Jose Armando Garcia wrote: [snip]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.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, -JoseI'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); } ...
Jun 02 2011
On 2011-06-02 16:47, Bruno Medeiros wrote:On 30/05/2011 18:41, KennyTM~ wrote:.stringof doesn't return the full module name, just the last part. -- /Jacob CarlborgOn May 31, 11 00:59, Jose Armando Garcia wrote: [snip]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.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, -JoseI'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); } ...
Jun 02 2011
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
On 05/30/2011 01:02 PM, Walter Bright wrote:On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:Gnu's and subsequently C++0x's experience with __FUNCTION__ and __PRETTY_FUNCTION__ has shown that the effects are beneficial. AndreiWalter, 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
On 30/05/2011 20:08, Andrei Alexandrescu wrote:On 05/30/2011 01:02 PM, Walter Bright wrote: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/On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:Gnu's and subsequently C++0x's experience with __FUNCTION__ and __PRETTY_FUNCTION__ has shown that the effects are beneficial. AndreiWalter, 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
On May 31, 11 03:32, Robert Clipsham wrote:On 30/05/2011 20:08, Andrei Alexandrescu wrote: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?On 05/30/2011 01:02 PM, Walter Bright wrote: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 ;)).On 5/30/2011 9:59 AM, Jose Armando Garcia wrote:Gnu's and subsequently C++0x's experience with __FUNCTION__ and __PRETTY_FUNCTION__ has shown that the effects are beneficial. AndreiWalter, 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
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, -Jose1. 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
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:Makes sense - will change.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, -Jose1. 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!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
On 05/29/2011 12:25 PM, Jose Armando Garcia wrote:Thanks. Comments below.[snip] All good points. Thanks! Andrei
May 29 2011
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
Am 29.05.2011 22:57, schrieb Brad Roberts:On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote: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, - Daniel1. 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
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:code after using fatal depends on compile-timeOn 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:1. The fatal log should never be stripped. This is because execution of=lication regardless of circumstances. Otherwiseflags, which is unacceptable. Logging to fatal should terminate the app=a couple years, I came to greatly regret it.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=were libraries. =A0In some ways it was abuse ofFatalness down in libraries became overused, particularly in layers that=raged it's use.fatal for things that shouldn't have been, but it's mere existence encou=tion behavior.I really don't think it's the log libraries job to implement app termina=My 2 cents, BradAlso 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
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, - DanielOn 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: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, - Daniel1. 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
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: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?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? =A0Thanks :-)Thanks!Cheers, - Danielrote:On Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com> w=of code after using fatal depends on compile-timeAm 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 =pplication regardless of circumstances. Otherwiseflags, which is unacceptable. Logging to fatal should terminate the a=);people would need to write things like: fatal("blah"); assert(0, "Execution cannot continue even though logging is stripped"=er a couple years, I came to greatly regret it.This is needless and bug-prone. Fatal is fatal.At one time I used a log framework that included this behavior. =A0Aft=at were libraries. =A0In some ways it was abuse ofFatalness down in libraries became overused, particularly in layers th=ouraged it's use.fatal for things that shouldn't have been, but it's mere existence enc=nation behavior.I really don't think it's the log libraries job to implement app termi=oMy 2 cents, BradAlso 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=tleave your data as consistent as possible or whatever, so you don't wan=rthe application to terminate immediately after fatal() but you want to do error handling yourself and terminate afterwards (and what you do fo=gerror handling/shutting downmay be dependent on the error, so just usin=scope(error) may not be the easiest choice). Cheers, - Daniel
May 29 2011
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: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, - DanielAm 30.05.2011 02:11, schrieb Jose Armando Garcia: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?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 :-)Thanks!Cheers, - DanielOn 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: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, - Daniel1. 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
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:rote:On Sun, May 29, 2011 at 9:37 PM, Daniel Gibson <metalcaedes gmail.com> w=tAm 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=http://d-programming-language.org/expression.html#AssertExpressionSounds 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).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?Cheers, - DanielrBTW: 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=wrote:the sake of consistency and readability? =A0Thanks :-)Thanks!Cheers, - DanielOn Sun, May 29, 2011 at 6:20 PM, Daniel Gibson <metalcaedes gmail.com>=n of code after using fatal depends on compile-timeAm 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=application regardless of circumstances. Otherwiseflags, which is unacceptable. Logging to fatal should terminate the=d");people would need to write things like: fatal("blah"); assert(0, "Execution cannot continue even though logging is strippe=fter a couple years, I came to greatly regret it.This is needless and bug-prone. Fatal is fatal.At one time I used a log framework that included this behavior. =A0A=that were libraries. =A0In some ways it was abuse ofFatalness down in libraries became overused, particularly in layers =ncouraged it's use.fatal for things that shouldn't have been, but it's mere existence e=mination behavior.I really don't think it's the log libraries job to implement app ter=tMy 2 cents, BradAlso imagine the following scenario: You detect a fatal error and wan=d.to log it, while all the useful information you want to log is at han=toHowever afterwards you'd like to shut down the application gracefully=antleave your data as consistent as possible or whatever, so you don't w=othe application to terminate immediately after fatal() but you want t=fordo error handling yourself and terminate afterwards (and what you do =ingerror handling/shutting downmay be dependent on the error, so just us=scope(error) may not be the easiest choice). Cheers, - Daniel
May 29 2011
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:Thanks. Strange that the site-search on digitalmars.com/d/ didn't find this when searching for "assert(0)".[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
May 29 2011
On 2011-05-29 18:43, Daniel Gibson wrote:Am 30.05.2011 03:40, schrieb Jose Armando Garcia:wrote:On Sun, May 29, 2011 at 10:19 PM, Daniel Gibson <metalcaedes gmail.com>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 DavisThanks. Strange that the site-search on digitalmars.com/d/ didn't find this when searching for "assert(0)".[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
May 29 2011
On 2011-05-29 18:19, Daniel Gibson wrote:Am 30.05.2011 03:07, schrieb Jose Armando Garcia:wrote:On Sun, May 29, 2011 at 9:37 PM, Daniel Gibson <metalcaedes gmail.com>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 DavisSounds 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).Am 30.05.2011 02:11, schrieb Jose Armando Garcia: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?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.
May 29 2011
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: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).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.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
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:atalOn 5/29/2011 8:44 AM, Andrei Alexandrescu wrote:Fatal can be with context. =A0Let's say you have one thread that hits a f=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.error, and another thread which is finishing out a DB transaction. =A0Sin=celogging the fatal error will kill the whole application, I now would have=towrite some sync function that all threads have to periodically call to ma=kesure I don't kill some perfectly valid process that's unrelated to the fa=talerror. =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).aAt one time I used a log framework that included this behavior. =A0After=Itcouple 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=seems that the logger instantiation is customizable on the call to initializeLogging. =A0I'd say that should be the default as well (if you =wantcertain 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=glevels to different loggers. =A0That is, when I logged a fatal error, it =wentboth 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 admitI 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
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: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?On Sun, 29 May 2011 16:57:52 -0400, Brad Roberts <braddr puremagic.com> wrote: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).On 5/29/2011 8:44 AM, Andrei Alexandrescu wrote: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).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.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. -SteveThis 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.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).
May 31 2011
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:ofOn 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 =);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"=inceFatal 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=This is needless and bug-prone. Fatal is fatal.velogging the fatal error will kill the whole application, I now would ha=f IAgain, 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=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).had to choose from your options, I'd use neither critical nor fatal. =A0I='dprobably just stick with the higher levels, and start putting my own leve=lsin 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 =notso much a "this program can't continue because it's not sane," but a "thi=sprogram cannot continue because something is misconfigured, etc." =A0This=doesnot 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 itsimply 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.er aAt one time I used a log framework that included this behavior. =A0Aft=atcouple years, I came to greatly regret it. Fatalness down in libraries became overused, particularly in layers th==A0Itwere 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? =useems that the logger instantiation is customizable on the call to initializeLogging. =A0I'd say that should be the default as well (if yo=toSure, 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 =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.create code paths. =A0If I want a function that logs a message and then h=altsthe application, I can write one of those (you can even include it as par=tof std.log!). =A0It's like having fopen halt your application if it can't=opena 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=forlogging, 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
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: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...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.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!Again, one has the ability to do fatal(""); assert(0); or myFunctionThatLogsThenAsserts("");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.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.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!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. -SteveEssentially 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?
May 31 2011
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: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? AndreiOn Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote: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...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.
May 31 2011
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: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. -SteveOn Tue, 31 May 2011 14:10:20 -0400, Jose Armando Garcia <jsancio gmail.com> wrote: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.On Tue, May 31, 2011 at 2:34 PM, Steven Schveighoffer <schveiguy yahoo.com> wrote: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...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.
May 31 2011
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
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: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 WeyOn 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
May 31 2011
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:om>On Tue, 31 May 2011 12:28:12 -0400, Jose Armando Garcia <jsancio gmail.c=ofwrote: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=");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=aFatal can be with context. =A0Let's say you have one thread that hits =This is needless and bug-prone. Fatal is fatal.Sincefatal error, and another thread which is finishing out a DB transaction. =A0=avelogging the fatal error will kill the whole application, I now would h=gAgain, this sounds way too complicated for what it's giving you (avoidin=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).If Ihaving to forcibly kill your application if that's what you desire). =A0=I'dhad to choose from your options, I'd use neither critical nor fatal. =A0=elsprobably just stick with the higher levels, and start putting my own lev=notin 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=isso much a "this program can't continue because it's not sane," but a "th=s doesprogram cannot continue because something is misconfigured, etc." =A0Thi=tnot 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==A0Is it(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. =ter asimply 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=hatcouple years, I came to greatly regret it. Fatalness down in libraries became overused, particularly in layers t==A0Itwere 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? =ouseems that the logger instantiation is customizable on the call to initializeLogging. =A0I'd say that should be the default as well (if y=toSure, 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=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.haltscreate code paths. =A0If I want a function that logs a message and then =rtthe application, I can write one of those (you can even include it as pa=t openof std.log!). =A0It's like having fopen halt your application if it can'=s fora 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=ing,logging, nothing else. =A0For sure, if std.log implements mandatory halt=smy belief is another competitor log library will certainly get the lion'=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.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
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: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 Davis4. 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.
May 29 2011
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:code after using fatal depends on compile-time1. The fatal log should never be stripped. This is because execution of =ication regardless of circumstances. Otherwiseflags, which is unacceptable. Logging to fatal should terminate the appl=a couple years, I came to greatly regret it.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 =Fatalness down in libraries became overused, particularly in layers that =were libraries. =A0In some ways it was abuse offatal 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
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
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
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: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?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.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#ImportDeclarationMasahiro
May 29 2011