logging v1.4 - some comments

Excuse the break in threading - gmane has lost/missed a lot of boost traffic. Hi John, I've only had a quick look at the latest version: The m_destroyed hack needs to go - this should only be relevant for static (not scoped) logs and the real issue is that you need to do thread-safe singletons - ie. you need to use posix call_once or equivalent to contstruct the thing. Destruction is a bit tricky - not doing it seems a reasonable option, though stopping leak detectors from compaining would be nice. The scoped log stuff doesn't seem to have been updated to support levels yet - in fact I'm not sure if it currently works? I think (fancy that - given the way it was in analog ;-)) that the named appenders need to be managed - currently, you can create multiple appenders with the same name, then when you delete by name you delete all appenders with that name. I don't see the utility of that model, which when combined with the wildcard matching is really fairly hard to use. For example, suppose I have an appender that logs to some sort of display for "real time" tracing. First off, I say: manipulate_logs("error.*").add_appender(displaywrite, "display") Then I notice an error about some component foo and decide to look at more detail about foo: manipulate_logs("*.foo").add_appender(displaywrite, "display") Now I get anything logged to "error.foo" written to "display" twice. I then say: manipulate_logs("error.*").del_appender("display") Because I want to concentrate on "foo" only. Now I find I don't get errors from foo displayed, only other less critical messaages. Then, foo goes out of scope (it's a scoped log), only to come back into scope again. When it does, and it generates an error, I'm (not really) suprised to see it sent to "display".... As the purpose of named appenders is to facilitate runtime modification of the appender set, surely the ability to make these modifications using *only* the name is reasonable. The fact that add requires a function while del only needs a name only highlights this. Regardless of what the rules for combining appenders/modifiers/enabledness are, they need to be consistent and to work across scoped logs going in/out of scope. I think what is needed is a set of connections (logs connect to appenders/modifiers) ordered by the log name which may include wildcards. Log name (segments) containing wildcards should be ordered before exact names so the more specific rules override the less specific ones. Note the above was from reading the docs + code - I haven't tried running it yet, and maybe I'm misunderstanding something. Regards Darryl.

Darryl Green <darryl.green@aanet.com.au> writes:
Excuse the break in threading - gmane has lost/missed a lot of boost traffic.
Seriously? Can you point to a single message in the archive at lists.boost.org that hasn't been registered at GMane? If so, we need to do something about it ASAP! -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Darryl Green <darryl.green@aanet.com.au> writes:
Excuse the break in threading - gmane has lost/missed a lot of boost traffic.
Seriously? Can you point to a single message in the archive at lists.boost.org that hasn't been registered at GMane? If so, we need to do something about it ASAP!
I think Darryl is right, there have been some messages lost during the recent Gmane hickups. But I can't prove it as the boost mail archive seems to have stopped at 2005-08-01 23:21:13. Markus

Darryl Green <darryl.green <at> aanet.com.au> writes:
I think what is needed is a set of connections (logs connect to appenders/modifiers) ordered by the log name which may include wildcards. Log name (segments) containing wildcards should be ordered before exact names so the more specific rules override the less specific ones.
I'm putting together an alternate manager to implement something like the above. The semantics will be that you specify logging rules like: // create/register (but don't connect to any logs) an appender log_appender("display") = write_to_cout; log_appender("bazfile") = write_to_file("baz.log"); manipulate_logs("foo.bar.*") .connect_appender("display"); manipulate_logs("foo.bar.baz") .disconnect_appender("display") .connect_appender("bazfile") // one can delete the actual appender // which will disconnect it first! log_appender("display").erase(); The connecting/disconnecting of appenders maintains a (per appender) set of rules for matching logs. The size of the rule set is bounded (assuming the set of log names is) by removing redundant rules whenever a modification to the rule set is made. The rules are applied in the order they are specified. Clearly this means changing manipulate_logs, and changing the manager concept/interface. I'm finding it hard to see how a really "alternate" manager could be written given the rather restrictive set of required interfaces. I think manipulate_logs() should simply provide access to completely manager defined functionality. I also find the manipulation of logs by specifying the pattern to match a number of logs, then applying a number of appenders to them to be less than appealing, I think the "inverse" interface should also be provided ie. appender("display") .connect("foo.bar.*") .disconnect("foo.bar.baz"); appender("bazfile") .connect("foo.bar.baz"); Would have the same result as the manipulate_logs lines above. I'll include this too. Darryl Green.

Darryl Green wrote:
Darryl Green <darryl.green <at> aanet.com.au> writes:
I think what is needed is a set of connections (logs connect to appenders/modifiers) ordered by the log name which may include wildcards. Log name (segments) containing wildcards should be ordered before exact names so the more specific rules override the less specific ones.
I'm putting together an alternate manager to implement something like the above.
The semantics will be that you specify logging rules like:
// create/register (but don't connect to any logs) an appender log_appender("display") = write_to_cout; log_appender("bazfile") = write_to_file("baz.log");
manipulate_logs("foo.bar.*") .connect_appender("display");
manipulate_logs("foo.bar.baz") .disconnect_appender("display") .connect_appender("bazfile")
// one can delete the actual appender // which will disconnect it first! log_appender("display").erase();
The connecting/disconnecting of appenders maintains a (per appender) set of rules for matching logs. The size of the rule set is bounded (assuming the set of log names is) by removing redundant rules whenever a modification to the rule set is made. The rules are applied in the order they are specified.
This does indeed look easier. I want to update the log manager to allow for this, but I don't think I'll have the time to do it, before the formal review (30 Sept).
Clearly this means changing manipulate_logs, and changing the manager concept/interface. I'm finding it hard to see how a really "alternate" manager could be written given the rather restrictive set of required interfaces. I think manipulate_logs() should simply provide access to completely manager defined functionality.
I also find the manipulation of logs by specifying the pattern to match a number of logs, then applying a number of appenders to them to be less than appealing, I think the "inverse" interface should also be provided ie.
appender("display") .connect("foo.bar.*") .disconnect("foo.bar.baz"); appender("bazfile") .connect("foo.bar.baz");
Would have the same result as the manipulate_logs lines above.
Yup, this makes sense as well. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -v1.6.3 (Resource Splitter) -- http://www.torjo.com/cb/ - Click, Build, Run!

Darryl Green wrote:
Excuse the break in threading - gmane has lost/missed a lot of boost traffic.
Hi John, I've only had a quick look at the latest version:
The m_destroyed hack needs to go - this should only be relevant for static (not scoped) logs and the real issue is that you need to do thread-safe singletons - ie. you need to use posix call_once or equivalent to contstruct the thing. Destruction is a bit tricky - not doing it seems a reasonable option, though stopping leak detectors from compaining would be nice.
I don't think construction is tricky. I think knowing whether I'm still constructed - that's the problem. And for scoped logs, you can simply ignore it.
The scoped log stuff doesn't seem to have been updated to support levels yet - in fact I'm not sure if it currently works?
It does work, and it does support levels: BOOST_SCOPEDLOG and BOOST_SCOPEDLOGL
I think (fancy that - given the way it was in analog ;-)) that the named appenders need to be managed - currently, you can create multiple appenders with the same name, then when you delete by name you delete all appenders with that name. I don't see the utility of that model, which when combined with the wildcard matching is really fairly hard to use. For example, suppose I have an appender that logs to some sort of display for "real time" tracing. First off, I say:
manipulate_logs("error.*").add_appender(displaywrite, "display")
Then I notice an error about some component foo and decide to look at more detail about foo:
manipulate_logs("*.foo").add_appender(displaywrite, "display")
Now I get anything logged to "error.foo" written to "display" twice.
I then say:
manipulate_logs("error.*").del_appender("display")
You're right. What comes to mind, is to have an extra parameter: bool add_even_if_name_exists. So, if passing 'false', if "display" already exists, it's not added. If passing 'true', "display" is added even if it exists. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -v1.6.3 (Resource Splitter) -- http://www.torjo.com/cb/ - Click, Build, Run!

From: John Torjo <john.lists@torjo.com>
You're right. What comes to mind, is to have an extra parameter: bool add_even_if_name_exists.
So, if passing 'false', if "display" already exists, it's not added. If passing 'true', "display" is added even if it exists.
I suggest using an enumerated type. When called from user code, "true" and "false" convey no information. Enumerators can make the call self-documenting. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: John Torjo <john.lists@torjo.com>
You're right. What comes to mind, is to have an extra parameter: bool add_even_if_name_exists.
So, if passing 'false', if "display" already exists, it's not added. If passing 'true', "display" is added even if it exists.
I suggest using an enumerated type. When called from user code, "true" and "false" convey no information. Enumerators can make the call self-documenting.
Yup, you're right. Will do so. Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -v1.6.3 (Resource Splitter) -- http://www.torjo.com/cb/ - Click, Build, Run!

John Torjo wrote:
I don't think construction is tricky. I think knowing whether I'm still constructed - that's the problem.
You can never test for "still constructed" using data that is part of the possibly destructed object - all you get is undefined behavior. You don't need the test if you can live with never destroying the object.
The scoped log stuff doesn't seem to have been updated to support levels yet - in fact I'm not sure if it currently works?
It does work, and it does support levels: BOOST_SCOPEDLOG and BOOST_SCOPEDLOGL
It was just the problem fixed by Andreas confusing me.
You're right. What comes to mind, is to have an extra parameter: bool add_even_if_name_exists.
So, if passing 'false', if "display" already exists, it's not added. If passing 'true', "display" is added even if it exists.
That works, but I think the interface reflects a design choice (mixing naming/registering the appender and connecting it) that should be reconsidered. Regards Darryl. -- No virus found in this outgoing message. Checked by AVG Anti-Virus. Version: 7.0.338 / Virus Database: 267.10.10/73 - Release Date: 15/08/2005

Darryl Green wrote:
John Torjo wrote:
I don't think construction is tricky. I think knowing whether I'm still constructed - that's the problem.
You can never test for "still constructed" using data that is part of the possibly destructed object - all you get is undefined behavior. You don't need the test if you can live with never destroying the object.
But as you pointed out, it's only for statically constructed objects.
[...]
That works, but I think the interface reflects a design choice (mixing naming/registering the appender and connecting it) that should be reconsidered.
Yes, you're right. Your idea is much better, and I'll try to implement it ASAP. If you can do it, that would be even better :) (I've posted the latest version of Boost.Log at http://www.torjo.com) Best, John -- John Torjo, Contributing editor, C/C++ Users Journal -- "Win32 GUI Generics" -- generics & GUI do mix, after all -- http://www.torjo.com/win32gui/ -v1.6.3 (Resource Splitter) -- http://www.torjo.com/cb/ - Click, Build, Run!
participants (6)
-
Darryl Green
-
Darryl Green
-
David Abrahams
-
John Torjo
-
Markus Schöpflin
-
Rob Stewart