Class 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 Detail

      • getInstance

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

        public NullTracer getDefaultTracer()
        Returns the configured default tracer (a NullTracer).
        Returns:
        the defaultTracer
      • getQueueSize

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

        public boolean isQueueEnabled()
        Indicates if the tracer queue is enabled.
        Returns:
        true if the tracer queue is enabled
      • getQueueTracerClassname

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

        public void readConfiguration​(File configFile)
                               throws TracerFactory.Exception,
                                      IOException
        Reads the given configuration file, validates it against an 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
        IOException - indicates an I/O problem, e.g. a missing configuration file
      • 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:
        getTracer(java.lang.Thread)
      • 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<? extends AbstractTracer> 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​(QueueTracer<? extends AbstractTracer> 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