You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-user@logging.apache.org by Duncan Woods <du...@garradhassan.com> on 2006/06/26 16:22:31 UTC

Format of the NDC

I was delighted by the NDC feature of log4net/log4j as my own tracing
framework had the same feature. Its only when I wished to add things
like the Smtp and Ado appenders that I choose to switch to ready made
library.
 
My question is, how do you format your NDC messages to be easily
readable? It seems that by default, different levels of the context
stack are not distinguished and allowed to run on into one string. I was
thinking of adding a terminator e.g.  | or \\ to my NDC to each message.
Is it perhaps assumed that NDC context strings do not contain spaces? 
 
Is there something that I'm not understanding here?
 
Thanks,
Duncan

Re: Format of the NDC

Posted by Ron Grabowski <ro...@yahoo.com>.
--- Ron Grabowski <ro...@yahoo.com> wrote:

>  // requires changing log4net.Util.ThreadContextStacks:77
>  // requires changing log4net.Util.ThreadContextStacks:99
>  ThreadContextStack threadContextStack = (ThreadContextStack)obj;
>  if (threadContextStack.Name == "NDC")
>  {
>   writer.Write(threadContextStack.Count);
>  }
>  else
>  {
>   LogManager.GetRepository().RendererMap.FindAndRender(
>    threadContextStack,
>    writer);
>  }

else
{
 rendererMap.FindAndRender(threadContextStack, writer);
}

RE: Format of the NDC

Posted by Duncan Woods <du...@garradhassan.com>.
Hi Ron,

Thanks for the great examples.

>> You could write your own IObjectRenderer that rendered the 
>> NDC like this:
>>
>> Goodbye {Hello|World}

That's the sort of output I was expecting by default but does this mean
that most other people's NDC is unformatted and does not clarify levels
between frames? 

I'm sure log4net can be bent to satisfy any particular whim but I'm
trying to eek out what the best practices are and stick to the
conventional\common uses. 

Thanks,
Duncan




-----Original Message-----
From: Ron Grabowski [mailto:rongrabowski@yahoo.com] 
Sent: 30 June 2006 05:20
To: Log4NET User
Subject: Re: Format of the NDC

Log4net delegates the rendering of objects through the IObjectRenderer
interface. The DefaultRenderer:IObjectRenderer formats IEnumerable
objects (i.e. IList, ICollection, etc.) like this:

 {item1, item2, item3}

When you add items to the NDC, you're actually adding items to
ThreadContext.Stacks["NDC"]:

http://logging.apache.org/log4net/release/manual/contexts.html
"
The NDC (Nested Diagnostic Context) exists for compatibility with older
versions of log4net. This helper class implements a stack which is
stored in the thread context property named NDC.
"

The short answer as to why this code:

 using (log4net.NDC.Push("Hello"))
 {
  using (log4net.NDC.Push("World"))
  {
   log.Info("Goodbye");
  }
 }

doesn't print out like this (assuming a pattern of "%message %ndc"):
 
 Goodbye {Hello, World}

is that ThreadContextStack is not a System.Collection.Stack. In fact it
doesn't implement any of the System.Collection interfaces.

Its possible to register an IObjectRenderer for objects of type
ThreadContextStack:

 LogManager.GetRepository().RendererMap.Put(
  typeof(ThreadContextStack), 
  new ThreadContextStackRenderer());

ThreadContextStackRenderer displays the number of items in the
ThreadContextStack object instead of outputing the items themselves:

public class ThreadContextStackRenderer : IObjectRenderer
{
 public void RenderObject(
  RendererMap rendererMap, object obj, TextWriter writer)
 {
  ThreadContextStack threadContextStack = (ThreadContextStack)obj;
  writer.Write(threadContextStack.Count);
 }
}

The output for the "%message %ndc" pattern will now be:

 Goodbye 2

Unfortunately the ThreadContextStack does not record the key used to
access it so the ThreadContextStackRenderer will process all
ThreadContext instances. Changing the ThreadContextStack class so it
did record its name would allow code like this:

 // requires changing log4net.Util.ThreadContextStacks:77
 // requires changing log4net.Util.ThreadContextStacks:99
 ThreadContextStack threadContextStack = (ThreadContextStack)obj;
 if (threadContextStack.Name == "NDC")
 {
  writer.Write(threadContextStack.Count);
 }
 else
 {
  LogManager.GetRepository().RendererMap.FindAndRender(
   threadContextStack,
   writer);
 }

You could write your own IObjectRenderer that rendered the NDC like
this:

 Goodbye {Hello|World}

Is that what you want? Is all of this a little too complex...maybe ;-)
Show us what you want/expect and maybe we can give better feedback or
examples.

- Ron

--- Duncan Woods <du...@garradhassan.com> wrote:

> I was delighted by the NDC feature of log4net/log4j as my own tracing
> framework had the same feature. Its only when I wished to add things
> like the Smtp and Ado appenders that I choose to switch to ready made
> library.
>  
> My question is, how do you format your NDC messages to be easily
> readable? It seems that by default, different levels of the context
> stack are not distinguished and allowed to run on into one string. I
> was
> thinking of adding a terminator e.g.  | or \\ to my NDC to each
> message.
> Is it perhaps assumed that NDC context strings do not contain spaces?
> 
>  
> Is there something that I'm not understanding here?
>  
> Thanks,
> Duncan
> 

Re: Format of the NDC

Posted by Ron Grabowski <ro...@yahoo.com>.
Log4net delegates the rendering of objects through the IObjectRenderer
interface. The DefaultRenderer:IObjectRenderer formats IEnumerable
objects (i.e. IList, ICollection, etc.) like this:

 {item1, item2, item3}

When you add items to the NDC, you're actually adding items to
ThreadContext.Stacks["NDC"]:

http://logging.apache.org/log4net/release/manual/contexts.html
"
The NDC (Nested Diagnostic Context) exists for compatibility with older
versions of log4net. This helper class implements a stack which is
stored in the thread context property named NDC.
"

The short answer as to why this code:

 using (log4net.NDC.Push("Hello"))
 {
  using (log4net.NDC.Push("World"))
  {
   log.Info("Goodbye");
  }
 }

doesn't print out like this (assuming a pattern of "%message %ndc"):
 
 Goodbye {Hello, World}

is that ThreadContextStack is not a System.Collection.Stack. In fact it
doesn't implement any of the System.Collection interfaces.

Its possible to register an IObjectRenderer for objects of type
ThreadContextStack:

 LogManager.GetRepository().RendererMap.Put(
  typeof(ThreadContextStack), 
  new ThreadContextStackRenderer());

ThreadContextStackRenderer displays the number of items in the
ThreadContextStack object instead of outputing the items themselves:

public class ThreadContextStackRenderer : IObjectRenderer
{
 public void RenderObject(
  RendererMap rendererMap, object obj, TextWriter writer)
 {
  ThreadContextStack threadContextStack = (ThreadContextStack)obj;
  writer.Write(threadContextStack.Count);
 }
}

The output for the "%message %ndc" pattern will now be:

 Goodbye 2

Unfortunately the ThreadContextStack does not record the key used to
access it so the ThreadContextStackRenderer will process all
ThreadContext instances. Changing the ThreadContextStack class so it
did record its name would allow code like this:

 // requires changing log4net.Util.ThreadContextStacks:77
 // requires changing log4net.Util.ThreadContextStacks:99
 ThreadContextStack threadContextStack = (ThreadContextStack)obj;
 if (threadContextStack.Name == "NDC")
 {
  writer.Write(threadContextStack.Count);
 }
 else
 {
  LogManager.GetRepository().RendererMap.FindAndRender(
   threadContextStack,
   writer);
 }

You could write your own IObjectRenderer that rendered the NDC like
this:

 Goodbye {Hello|World}

Is that what you want? Is all of this a little too complex...maybe ;-)
Show us what you want/expect and maybe we can give better feedback or
examples.

- Ron

--- Duncan Woods <du...@garradhassan.com> wrote:

> I was delighted by the NDC feature of log4net/log4j as my own tracing
> framework had the same feature. Its only when I wished to add things
> like the Smtp and Ado appenders that I choose to switch to ready made
> library.
>  
> My question is, how do you format your NDC messages to be easily
> readable? It seems that by default, different levels of the context
> stack are not distinguished and allowed to run on into one string. I
> was
> thinking of adding a terminator e.g.  | or \\ to my NDC to each
> message.
> Is it perhaps assumed that NDC context strings do not contain spaces?
> 
>  
> Is there something that I'm not understanding here?
>  
> Thanks,
> Duncan
>