Class TracerFactory

java.lang.Object
de.christofreichardt.diagnosis.TracerFactory

public class TracerFactory extends Object

A factory and holder of tracers. Tracers will be created according to a given (XML-)configuration. So long as no configuration has been read some methods provide a default tracer. This default tracer traces nothing and routes log messages to the core logging facilities of the Java platform, see java.util.logging and JDKLoggingRouter.

The configuration file consists of four main sections. You can put tracer into a pool and access them by name. Second you may redefine the default tracer. Third you can map threads on tracer and subsequently access the primary tracer for a given thread. Or you may configure a blocking queue of tracer for multi-threading environments for which you cannot control thread creation. Consider for example the following definitions:

 <?xml version="1.0" encoding="UTF-8" ?>
 <TraceConfig xmlns="http://www.christofreichardt.de/java/tracer">
   <Pool>
     <TraceLogger name="ExampleTracer" class="de.christofreichardt.diagnosis.file.FileTracer">
       <LogDir>./log/</LogDir>
       <AutoFlush>true</AutoFlush>
       <BufSize>1024</BufSize>
       <Limit>1048576</Limit>
       <Context>
         <Thread name="main">
           <Online>true</Online>
           <DebugLevel>5</DebugLevel>
         </Thread>
       </Context>
     </TraceLogger>
   </Pool>
   <Map>
     <Threads>
       <Thread name="main">
         <TraceLogger ref="ExampleTracer" />
       </Thread>
     </Threads>
   </Map>
 </TraceConfig>

The definitions above make use of the first and the third section. A FileTracer has been configured. Its outputfile is located at ./log/ExampleTracer.log. The tracer is in autoflush mode, that is every time an observed method is popped from the stack the output stream will be flushed. The tracer will back up its file when it reaches the size of one MebiByte (1024*1024 Byte). The 'ExampleTracer' is interested in output from the main-Thread up to a stack size of five. Note that this is not the call stack of the Java Virtual Machine. You may put only methods you are interested in on a separate stack managed by a TracingContext. The main-Thread has been mapped on the 'ExampleTracer'. Therefore you may invoke a convenience method to retrieve the tracer for this thread. Assuming you put the configuration file into ./config/ExampleConfig.xml, the TracerFactory can be configured and used like this from the main-Thread:

 File configFile = new File("." + File.separator + "config" + File.separator + "ExampleConfig.xml");
 TracerFactory.getInstance().readConfiguration(configFile);
 final AbstractTracer tracer = TracerFactory.getInstance().getCurrentPoolTracer();
 tracer.open();
 try {
   class Foo {
     void bar() {
       tracer.entry("void", this, "bar()");
       try {
         tracer.out().printfIndentln("This is an example.");
       }
       finally {
         tracer.wayout();
       }
     }
   }
   Foo foo = new Foo();
   foo.bar(); // nothing will be printed because no tracing context has been provided
   tracer.initCurrentTracingContext(); // the configured tracing context will be used
   foo.bar(); // this will generate output
 }
 finally {
   tracer.close();
 }

The generated output can be found at ./log/ExampleTracer.log - whereas the directory ./log must exist - and looks like:

 --> TraceLog opened!
     Time     : Mi Apr 02 23:14:41 MESZ 2014
     Bufsize  : 512
     Autoflush: true
 
 ENTRY--void Foo[12275192].bar()--main[1]
   This is an example.
 RETURN-void Foo[12275192].bar()--(+0ms)--(+0ms)--main[1]
 
 --> TraceLog closing!
     Time     : Mi Apr 02 23:14:41 MESZ 2014

This approach makes sense if you control the creation of threads. Keep in mind that the Java Virtual Machine doesn't guarantee the uniqueness of thread names. That is when you invoke TracerFactory.getInstance().getCurrentPoolTracer() from another thread called 'main' later on, you will get the default tracer which routes log messages (but not the tracing output) to the JDK logger.

Author:
Christof Reichardt
  • Method Details

    • getInstance

      public static TracerFactory getInstance()
      Retrieves the single TracerFactory.
      Returns:
      the single TracerFactory
    • getDefaultTracer

      public NullTracer getDefaultTracer()
      Returns:
      the defaultTracer
    • getQueueSize

      public int getQueueSize()
      Returns:
      the size of the tracer queue
    • isQueueEnabled

      public boolean isQueueEnabled()
      Returns:
      indicates if the tracer queue is enabled
    • getQueueTracerClassname

      public String getQueueTracerClassname()
      Returns:
      the classname of the employed QueueTracer
    • readConfiguration

      public void readConfiguration(File configFile) throws TracerFactory.Exception, FileNotFoundException
      Reads the given configuration file, validates it against a XML-Schema and creates the tracer pool, its mappings and the queue accordingly. This method should normally be invoked once at program start. Multiple calls with the same configuration file leads to instantiations of new tracer objects and mappings which will replace the old tracers and their mappings.
      Parameters:
      configFile - the configuration file
      Throws:
      TracerFactory.Exception - indicates a configuration problem
      FileNotFoundException - indicates a missing configuration file
    • readConfiguration

      public void readConfiguration(InputStream inputStream) throws TracerFactory.Exception
      Reads the configuration from the given InputStream.
      Parameters:
      inputStream - the input stream providing the configuration.
      Throws:
      TracerFactory.Exception - indicates a configuration problem
      See Also:
    • getTracer

      public AbstractTracer getTracer(String name) throws TracerFactory.Exception
      Returns the pooled tracer with the given name.
      Parameters:
      name - the name of the desired tracer
      Returns:
      the pooled tracer
      Throws:
      TracerFactory.Exception - if no tracer exists with the given name
    • getTracer

      public AbstractTracer getTracer(Thread thread)
      Returns the mapped tracer for the given thread. The given Thread object is used as key to a map. If no tracer can be found within the map for the given Thread the configuration will be searched for the thread's name. That is initially the resolution is based on thread names (prior to program execution no threads do exist but someone may know the to be used thread names). If there isn't an entry for a given Thread but the name of the thread has been encountered before (thread names aren't unique) a NullTracer will be returned.
      Parameters:
      thread - the thread for which a tracer is searched
      Returns:
      the mapped tracer for the given thread
    • getCurrentPoolTracer

      public AbstractTracer getCurrentPoolTracer()
      Returns the mapped tracer for the current thread.
      Returns:
      the mapped tracer for the current thread
      See Also:
    • reset

      public void reset()
      Clears the pool, the mappings and the queue.
    • openPoolTracer

      public void openPoolTracer()
      Opens all pooled tracers.
    • closePoolTracer

      public void closePoolTracer()
      Closes all pooled tracers.
    • takeTracer

      public QueueTracer<?> takeTracer()
      Takes the tracer from the head of the deque. If the deque is empty the methods blocks until a tracer will become available. By default a QueueTracer wrapping a NullTracer will be (non-blocking) delivered.
      Returns:
      the tracer from the head of the deque
    • offerTracer

      protected boolean offerTracer(QueueNullTracer queueNullTracer)
      Required for symmetrical reasons. The code used for debugging (enabled queue) and for production (disabled queue) should not differ. In the latter case takeTracer() delivers by default a QueueNullTracer (without blocking) which must not be enqueued again. Hence this method will simply discard the given QueueNullTracer.
      Parameters:
      queueNullTracer - a previously taken QueueTracer
      Returns:
      always false
      See Also:
    • offerTracer

      protected boolean offerTracer(QueueTracer<?> tracer)
      Used to enqueue a tracer which has been previously retrieved by a call to takeTracer().
      Parameters:
      tracer - the to be enqueued tracer
      Returns:
      indicates if the tracer has been enqueued (true) or has been discarded (false)
    • openQueueTracer

      public boolean openQueueTracer()
      Tries to open all enqueued QueueTracer.
      Returns:
      true if all configured tracers has been opened, false otherwise
    • closeQueueTracer

      public boolean closeQueueTracer()
      Tries to close all enqueued QueueTracer.
      Returns:
      true if all configured tracers has been closed, false otherwise
    • getCurrentQueueTracer

      public QueueTracer<?> getCurrentQueueTracer()
      Returns the QueueTracer for the current thread. If no one was found a QueueNullTracer will be returned.
      Returns:
      the QueueTracer for the current thread