|
From: Geoghegan, W. A (Willie) <wil...@in...> - 2010-10-01 21:46:50
|
Part 2.
I also implemented a thread stack (NDC) for
Trace.CorrelationManager.LogicalOperationStack.
I also provided an implementation of GlobalProperties, ThreadProperties,
and ThreadStack (taken largely from NLog). They could be used in a
context where there is not a "real" logging platform behind the
Common.Logging abstraction. Say you have a logger for Silverlight that
logs to the debugger and might log to a WCF LogService. Context can
still be captured. The logging implementation, such as it is, can get
the context information and do something with it. Don't know how useful
it will prove to.
This could easily occur inside of LogManager so a user of Common.Logging
could write something like this:
LogManager.GlobalProperties["name"] = "hello"; //set the "name" global
property on currently abstracted logging platform.
Some notable items:
1. Log4net provides properties and stack info for both "thread"
and "logical thread". From what I can tell, the "thread" values
(formerly MDC and NDC) are way more commonly used then the "logical
thread" values. Castle did not implement an abstraction for the
"logical" flavor.
2. Log4net provides for multiple stacks per thread. Castle exposes
this.
3. NLog does not provide a "logical thread" context, even in NLog
2.0. Castle's implementation exposes "ThreadStacks" (presumably to
support log4net's multiple stacks) but the implementation always hands
back the one NLog stack (NDC/NestedDiagnosticContext) for the thread,
regardless of what stack was requested.
4. Log4net allows objects to be set in the "properties" collections
and strings to be pushed onto the stacks. NLog only allows strings as
"properties" and entries on the stack. Castle exposes a string for both
the "properties" and the stack.
5. Castle based their "properties" implementation on log4net's
"BaseProperties" (maybe not right name), which has only a get/set
property bag interface. As such, they did not implement Clear or
Remove. It seems to make more sense to have Clear and Remove.
If the most common usage of the thread stacks is to have one stack
(NDC), and since NLog has only one stack anyway, I wonder if it really
makes sense to expose the stacks/stack such that you have to write code
like this:
LogContext.ThreadStacks["NDC"].Push("whatever");
Maybe it is better to either only expose one stack or expose a stack AND
a dictionary of stacks. Normally one might just use the single (or
default) stack. If there is a particular application or workflow that
wants to use multiple stacks, they would be there.
LogContext.ThreadStack.Push("whatever"); //pushes onto NDC
LogContext.ThreadStacks["custom stack"].Push("whatever"); //pushes onto
custom stack.
If anyone at Common.Logging is interested in discussing this and whether
or it is relevant or not to Common.Logging's implementation (when?) of
logging contexts, please respond. Also, if anyone at Common.Logging
would like to see what I have done and how it might or might not fit
into Common.Logging, also please respond.
Thanks.
Willie Geoghegan.
|