digitalmars.D - Feedback/Suggestions for std.log
- Gary (86/86) May 18 2011 1. Background
- Jose Armando Garcia (44/115) May 28 2011 Hi Gary.
1. Background Hi all, first time posting. This message is in response to Andrei's first call for feedback on the proposed std.log interface. I'm piping up on the log topic because of recent experience using a logging library ("log4cxx") on a project at work. I'll attempt to identify our teams' requirements of the logging library, and transition into suggestions for D's "std.log", and why D is a powerful language in which to implement a versatile log. I also, in these suggestions, dare make the assumption that the goals of std.log include accommodating audiences and users similar to my humble team members and myself. If this assumption is incorrect or the scope of the suggestions is too large for std.log, by all means pull me back down to Earth. 2. Requirements (for our team's logging functionality), and features which accommodate them - Must be scalable with respect to project size -- Feature: Allow custom log destinations specified at compile or run-time, and log level options specified at logger instantiation (compile time) or at run-time. -- Feature: Allow loggers to exist in a hierarchy, in which properties of parent loggers are shared with children. --- Our team of 18 developers must make judgments about what to log and when. Depending on the diagnostic activity, it is necessary to enable/disable logging in specific domains of the application. The ability to shut off logging in certain parts of the program at run time is paramount to success in debugging certain issues, from our experiences. --- The hierarchy helps in being able to shut off a large branch of loggers by specifying the level for just one ancestor. Also the hierarchy format (at least in our case) maps well to the organization of objects across our domains. - Must be performant - Log calls and interaction must be concise, readable code -- Feature: Minimal setup code, minimal code at log call site --- Our team has felt the pain of supporting and troubleshooting our products at customer sites, with irate customers present. Each illuminative log statement is worth it's weight in gold, but we're also cognizant of maintainability of software, and code with verbose comments becomes difficult to read. --- I opine: the current interface for std.log currently achieves good readability! Awesome! -- Feature: Allow code/logic to be run inside the conditional block of a log call. --- An example of our need for this is the need to print specific data from each member of a list of objects. Rather than incur log call overhead on each iteration over a list (much less not being able to compile away that logic), the most efficient solution seems to be allowing logic in the log conditional block. --- Of course, somebody somewhere will misuse this and put "business" logic in there, and compile out a small but necessary tidbit which made their program function. --- From my very rough understanding after reading the Lazy Evaluation article on "d-programming-language.org", this can be possible with the current std.log interface: Sample pseudo-code: logInfo({ auto msg = "Video modes found: "; foreach( mode, videoModes ) { msg ~= to!string( mode.width ) ~ "x" ~ to!string( mode.height ) ~ ";"; } return msg }); --- log4cxx simply allows a query to the logger at run-time to find out the current log level. I can provide success stories (well, success in finding and debugging issues) from having a few of these features in our logging library, but that could be boring so I'll hold back (available on request). 3. Suggestions Well, the suggestions for std.log are basically the features described above :-) . It'd be an injustice to express a desire to recreate log4cxx/log4j in D, but certain features which log4cxx provides greatly enhance development on large teams. I haven't thought through it, but I get the feeling D might accommodate creating the logger hierarchy at compile time, or rather avoid string (logger name) computations at run-time (log4cxx does all the string manipulation at run-time). I hopefully have made a case for including these features. I believe they'd be helpful to larger teams and teams supporting somewhat complex commercial products. I'm aware that it's very easy to ask for things when I'm not the one working to help provide them. Since I'd like to see this and other growth in the D language, I'll offer my help however I can. Thanks, Gary
May 18 2011
Hi Gary. You should take a look at the proposed logging module for phobos at http://jsancio.github.com/phobos/phobos/std_log.html and https://github.com/jsancio/phobos/blob/master/std/log.d. Please comment. I have some comments below. Thanks for your input.- Must be scalable with respect to project size -- Feature: Allow custom log destinations specified at compile or run-tim=e,and log level options specified at logger instantiation (compile time) or=atrun-time.This is not actually a requirement but more of an implementation suggest. What are you trying to achieve? With std.log you can enable and disable verbose logging in a module at run time with --vmodule. You can also disable logging at a specific severity for the entire process at compile time and run time.-- Feature: Allow loggers to exist in a hierarchy, in which properties of parent loggers are shared with children.Again, this is a implementation detail and not a requirement. What do you plan to do with a hierarchy? Look at vlog, it is much more flexible than a tree of loggers.--- Our team of 18 developers must make judgments about what to log and when. Depending on the diagnostic activity, it is necessary to enable/disable logging in specific domains of the application. The abilit=yto shut off logging in certain parts of the program at run time is paramo=untto success in debugging certain issues, from our experiences.You can use verbose logging and the command line flag --vmodule.--- The hierarchy helps in being able to shut off a large branch of logge=rsby specifying the level for just one ancestor. Also the hierarchy format =(atleast in our case) maps well to the organization of objects across our domains. From my experience you never really know how to organize your loggersat dev time. You realize you want to turn something only at debug time which in many cases it is too late (E.g. you already shipped a binary to QA or customer). std.log gives you the ability to enable and disable logging based on glob match on the source file.- Must be performant - Log calls and interaction must be concise, readable code -- Feature: Minimal setup code, minimal code at log call site --- Our team has felt the pain of supporting and troubleshooting our products at customer sites, with irate customers present. Each illuminati=velog statement is worth it's weight in gold, but we're also cognizant of maintainability of software, and code with verbose comments becomes difficult to read. --- I opine: the current interface for std.log currently achieves good readability! Awesome! -- Feature: Allow code/logic to be run inside the conditional block of a =logcall. --- An example of our need for this is the need to print specific data fr=omeach member of a list of objects. Rather than incur log call overhead on each iteration over a list (much less not being able to compile away that logic), the most efficient solution seems to be allowing logic in the log conditional block. --- Of course, somebody somewhere will misuse this and put "business" log=icin there, and compile out a small but necessary tidbit which made their program function. --- From my very rough understanding after reading the Lazy Evaluation article on "d-programming-language.org", this can be possible with the current std.log interface: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Sample pseudo-code: =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0logInfo({ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0auto msg =3D "Video modes found: "; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0foreach( mode, videoModes ) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0{ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0msg ~=3D to!string( mode.width ) ~ "x" ~ t=o!string( mode.height) ~ ";"; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0} =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return msg =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0});Yes! but your example has a small bug...--- log4cxx simply allows a query to the logger at run-time to find out t=hecurrent log level.This currently not exposed but it is trivial to add support for it...I can provide success stories (well, success in finding and debugging issues) from having a few of these features in our logging library, but t=hatcould be boring so I'll hold back (available on request). 3. Suggestions Well, the suggestions for std.log are basically the features described ab=ove:-) . It'd be an injustice to express a desire to recreate log4cxx/log4j =inD, but certain features which log4cxx provides greatly enhance developmen=ton large teams. I haven't thought through it, but I get the feeling D might accommodate creating the logger hierarchy at compile time, or rather avoid string (logger name) computations at run-time (log4cxx does all the string manipulation at run-time).We can talk about how to improve performance at a later point but it should be possible to cache the results of vmodule filtering.I hopefully have made a case for including these features. I believe they='dbe helpful to larger teams and teams supporting somewhat complex commerci=alproducts. I'm aware that it's very easy to ask for things when I'm not the one work=ingto help provide them. Since I'd like to see this and other growth in the =Dlanguage, I'll offer my help however I can. Thanks, Gary
May 28 2011
Hi Jose, Thanks for your response! I imagine you're quite busy so I appreciate you spending the time to respond. On 11-05-28 05:29 PM, Jose Armando Garcia wrote:Hi Gary. You should take a look at the proposed logging module for phobos at http://jsancio.github.com/phobos/phobos/std_log.html and https://github.com/jsancio/phobos/blob/master/std/log.d. Please comment.I read the proposed interface and am impressed! Comments: * The write method signature uses the source file and line for the message: "write(string file = __FILE__, int line = __LINE__, T...) ..." I saw in an earlier newsgroup message you asked Walter if it was appropriate to include the __MODULE__ name. I'd go further and suggest even optional inclusion of the function name! From our team's experience, any extra information while debugging or viewing logs means we troubleshoot issues that much quicker. If that info can be automatically included, we get a free boost in productivity! * Love the moduleFilter thing. Hopefully I'm referring to it correctly. Comments below. * I want to say this is in the C++ Coding Standards book: I think it's recommended to use nouns in names of classes. Perhaps it's consistent to use "VerbosityConfig" as opposed to "VerboseConfig"? * Abstracting out the "LogFilter" from the Logger strikes me as a good design decision. Responses to your responses:You must forgive my horrible attempt to organize these points. What I meant to convey was the high level requirements and possible features which achieve them as sub-bullets, and examples as sub-bullets of those. Happily, I see std.log achieves the fine grained control of filtering log messages based on severity and verbosity level. Awesome. The prior point is a suggestion for multiple log message destinations. I see the "SharedLogger" in the current proposal sends messages to different files based on severity. Do I perceive correctly that the "abstract interface Logger" can be extended by users of std.log? This is an excellent idea! It's also an effective way to manage feature requests. Can users choose to log to their own sub-types of loggers somehow? This can be an effective way to allow folks to point their log messages at whichever different files they'd like, or to some email destination, all while keeping the std.log interface relatively simple.- Must be scalable with respect to project size -- Feature: Allow custom log destinations specified at compile or run-time, and log level options specified at logger instantiation (compile time) or at run-time.This is not actually a requirement but more of an implementation suggest. What are you trying to achieve? With std.log you can enable and disable verbose logging in a module at run time with --vmodule. You can also disable logging at a specific severity for the entire process at compile time and run time.I believe the "moduleFilter" allows the core of functionality I was shooting for. Apologies for not just stating that.-- Feature: Allow loggers to exist in a hierarchy, in which properties of parent loggers are shared with children.Again, this is a implementation detail and not a requirement. What do you plan to do with a hierarchy? Look at vlog, it is much more flexible than a tree of loggers.I see, agreed! It seems the verbose level has similar behavior to the severity level. If this is true, could someone define their own spectrum of levels out of an enumeration set, if they find the 5 regular levels are too coarse grained?--- Our team of 18 developers must make judgments about what to log and when. Depending on the diagnostic activity, it is necessary to enable/disable logging in specific domains of the application. The ability to shut off logging in certain parts of the program at run time is paramount to success in debugging certain issues, from our experiences.You can use verbose logging and the command line flag --vmodule.I believe I see this "glob" ability in the "moduleFilter" part of the VerboseConfig! Bravo! I was going to point out: the power of the hierarchy was in the efficient configuration of which parts of the program log and which do not. It appears the moduleFilter achieves this, though with more expressiveness! Organization of loggers is definitely a brain exercise, I think partly because there's an implicit desire not to make a log message appear too alien if a customer must view it for any reason. I've settled on roughly matching the logger organization to component organization.--- The hierarchy helps in being able to shut off a large branch of loggers by specifying the level for just one ancestor. Also the hierarchy format (at least in our case) maps well to the organization of objects across our domains. From my experience you never really know how to organize your loggersat dev time. You realize you want to turn something only at debug time which in many cases it is too late (E.g. you already shipped a binary to QA or customer). std.log gives you the ability to enable and disable logging based on glob match on the source file.Ha! I've been trying to achieve this "lazy implicit conversion of function literal to string" thing in my D "mini-test" suite. Haven't ironed it out just yet.-- Feature: Allow code/logic to be run inside the conditional block of a log call. --- An example of our need for this is the need to print specific data from each member of a list of objects. Rather than incur log call overhead on each iteration over a list (much less not being able to compile away that logic), the most efficient solution seems to be allowing logic in the log conditional block. --- Of course, somebody somewhere will misuse this and put "business" logic in there, and compile out a small but necessary tidbit which made their program function. --- From my very rough understanding after reading the Lazy Evaluation article on "d-programming-language.org", this can be possible with the current std.log interface: Sample pseudo-code: logInfo({ auto msg = "Video modes found: "; foreach( mode, videoModes ) { msg ~= to!string( mode.width ) ~ "x" ~ to!string( mode.height ) ~ ";"; } return msg });Yes! but your example has a small bug...To start this point, I call upon the "Contract Programming" chapter of TDPL. Andrei notes that it is dangerous to place modifying code in code which should only be observing. As it pertains to this case, I'd hope revealing the log level, or rather if the log filter will log, won't encourage putting "business logic" in a block meant only for logging. To that end, all the same dangers exist for the method I described above. Hmmm, it may win if it can be stripped at compile time... I admit my ignorance regarding that stripping technique.--- log4cxx simply allows a query to the logger at run-time to find out the current log level.This currently not exposed but it is trivial to add support for it...Right on!I can provide success stories (well, success in finding and debugging issues) from having a few of these features in our logging library, but that could be boring so I'll hold back (available on request). 3. Suggestions Well, the suggestions for std.log are basically the features described above :-) . It'd be an injustice to express a desire to recreate log4cxx/log4j in D, but certain features which log4cxx provides greatly enhance development on large teams. I haven't thought through it, but I get the feeling D might accommodate creating the logger hierarchy at compile time, or rather avoid string (logger name) computations at run-time (log4cxx does all the string manipulation at run-time).We can talk about how to improve performance at a later point but it should be possible to cache the results of vmodule filtering.
May 31 2011
Hi Jose, Thanks for your response! I imagine you're quite busy so I appreciate you spending the time to respond. On 11-05-28 05:29 PM, Jose Armando Garcia wrote:Hi Gary. You should take a look at the proposed logging module for phobos at http://jsancio.github.com/phobos/phobos/std_log.html and https://github.com/jsancio/phobos/blob/master/std/log.d. Please comment.I read the proposed interface and am impressed! Comments: * The write method signature uses the source file and line for the message: "write(string file = __FILE__, int line = __LINE__, T...) ..." I saw in an earlier newsgroup message you asked Walter if it was appropriate to include the __MODULE__ name. I'd go further and suggest even optional inclusion of the function name! From our team's experience, any extra information while debugging or viewing logs means we troubleshoot issues that much quicker. If that info can be automatically included, we get a free boost in productivity! * Love the moduleFilter thing. Hopefully I'm referring to it correctly. Comments below. * I want to say this is in the C++ Coding Standards book: I think it's recommended to use nouns in names of classes. Perhaps it's consistent to use "VerbosityConfig" as opposed to "VerboseConfig"? * Abstracting out the "LogFilter" from the Logger strikes me as a good design decision. Responses to your responses:You must forgive my horrible attempt to organize these points. What I meant to convey was the high level requirements and possible features which achieve them as sub-bullets, and examples as sub-bullets of those. Happily, I see std.log achieves the fine grained control of filtering log messages based on severity and verbosity level. Awesome. The prior point is a suggestion for multiple log message destinations. I see the "SharedLogger" in the current proposal sends messages to different files based on severity. Do I perceive correctly that the "abstract interface Logger" can be extended by users of std.log? This is an excellent idea! It's also an effective way to manage feature requests. Can users choose to log to their own sub-types of loggers somehow? This can be an effective way to allow folks to point their log messages at whichever different files they'd like, or to some email destination, all while keeping the std.log interface relatively simple.- Must be scalable with respect to project size -- Feature: Allow custom log destinations specified at compile or run-time, and log level options specified at logger instantiation (compile time) or at run-time.This is not actually a requirement but more of an implementation suggest. What are you trying to achieve? With std.log you can enable and disable verbose logging in a module at run time with --vmodule. You can also disable logging at a specific severity for the entire process at compile time and run time.I believe the "moduleFilter" allows the core of functionality I was shooting for. Apologies for not just stating that.-- Feature: Allow loggers to exist in a hierarchy, in which properties of parent loggers are shared with children.Again, this is a implementation detail and not a requirement. What do you plan to do with a hierarchy? Look at vlog, it is much more flexible than a tree of loggers.I see, agreed! It seems the verbose level has similar behavior to the severity level. If this is true, could someone define their own spectrum of levels out of an enumeration set, if they find the 5 regular levels are too coarse grained?--- Our team of 18 developers must make judgments about what to log and when. Depending on the diagnostic activity, it is necessary to enable/disable logging in specific domains of the application. The ability to shut off logging in certain parts of the program at run time is paramount to success in debugging certain issues, from our experiences.You can use verbose logging and the command line flag --vmodule.I believe I see this "glob" ability in the "moduleFilter" part of the VerboseConfig! Bravo! I was going to point out: the power of the hierarchy was in the efficient configuration of which parts of the program log and which do not. It appears the moduleFilter achieves this, though with more expressiveness! Organization of loggers is definitely a brain exercise, I think partly because there's an implicit desire not to make a log message appear too alien if a customer must view it for any reason. I've settled on roughly matching the logger organization to component organization.--- The hierarchy helps in being able to shut off a large branch of loggers by specifying the level for just one ancestor. Also the hierarchy format (at least in our case) maps well to the organization of objects across our domains. From my experience you never really know how to organize your loggersat dev time. You realize you want to turn something only at debug time which in many cases it is too late (E.g. you already shipped a binary to QA or customer). std.log gives you the ability to enable and disable logging based on glob match on the source file.Ha! I've been trying to achieve this "lazy implicit conversion of function literal to string" thing in my D "mini-test" suite. Haven't ironed it out just yet.-- Feature: Allow code/logic to be run inside the conditional block of a log call. --- An example of our need for this is the need to print specific data from each member of a list of objects. Rather than incur log call overhead on each iteration over a list (much less not being able to compile away that logic), the most efficient solution seems to be allowing logic in the log conditional block. --- Of course, somebody somewhere will misuse this and put "business" logic in there, and compile out a small but necessary tidbit which made their program function. --- From my very rough understanding after reading the Lazy Evaluation article on "d-programming-language.org", this can be possible with the current std.log interface: Sample pseudo-code: logInfo({ auto msg = "Video modes found: "; foreach( mode, videoModes ) { msg ~= to!string( mode.width ) ~ "x" ~ to!string( mode.height ) ~ ";"; } return msg });Yes! but your example has a small bug...To start this point, I call upon the "Contract Programming" chapter of TDPL. Andrei notes that it is dangerous to place modifying code in code which should only be observing. As it pertains to this case, I'd hope revealing the log level, or rather if the log filter will log, won't encourage putting "business logic" in a block meant only for logging. To that end, all the same dangers exist for the method I described above. Hmmm, it may win if it can be stripped at compile time... I admit my ignorance regarding that stripping technique.--- log4cxx simply allows a query to the logger at run-time to find out the current log level.This currently not exposed but it is trivial to add support for it...Right on!I can provide success stories (well, success in finding and debugging issues) from having a few of these features in our logging library, but that could be boring so I'll hold back (available on request). 3. Suggestions Well, the suggestions for std.log are basically the features described above :-) . It'd be an injustice to express a desire to recreate log4cxx/log4j in D, but certain features which log4cxx provides greatly enhance development on large teams. I haven't thought through it, but I get the feeling D might accommodate creating the logger hierarchy at compile time, or rather avoid string (logger name) computations at run-time (log4cxx does all the string manipulation at run-time).We can talk about how to improve performance at a later point but it should be possible to cache the results of vmodule filtering.
May 31 2011