Error Handling & Logging

This chapter describes error handling using the Ibex API. Ibex associates an error handler with the library as a whole.
Generally this error handler will log a message and not throw an exception.
The Ibex Logger object is a singleton which is retrieved using a call to the ibex4.logging.Logger.getLogger() method. Typically you would import the ibex4.logging namespace and then access the logger as shown in Figure 6-1.

using ibex4.logging;
void sumfunc() {
  Logger.getLogger().clearHandlers();
}
    

Figure 6-1: Clearing existing error handlers

The default error handler writes messages to the console. Messages are displayed in various circumstances including:

  • when an invalid attribute is found;
  • when a reference is made to a font or image file which cannot be found;
  • when a formatting error occurs, such as defining the widths of columns in table that exceed the available width.

As the Ibex Logger is a singleton object, logging should be configured once at the start of an application, not on a per-document basis.

Error severity

To change the level of information logged you can set the level on the logging object to one of the values defined in the ibex4.logging.Level object. Possible levels of logging which can be set are: SEVERE WARNING INFO CONFIG FINE FINER FINEST

An example of how to set the logger to log only messages which are WARNING or worse is shown in Figure 6-2.

  
using System;
using ibex4;
using ibex4.logging;
		
public class Create {
		
  public static void Main( string[] args ) {
		
    PDFDocument doc = new PDFDocument();
		
    Logger.getLogger().setLevel( Level.WARNING );

Figure 6-2: Setting the error level

Logging to a file

To log messages to a file, create an ibex4.logging.FileHandler object and then tell the logger to log to this object. The example in Figure 6-3 logs to the file "log.txt", but any valid file name can be used.

using System;
using ibex4;
using ibex4.logging;
		
public class Create {
		
  public static void Main( string[] args ) {
		
    Logger.getLogger()
      .setLevel( Level.SEVERE )
      .clearHandlers()
      .addHandler( 
        new FileHandler("log.txt") );
	

Figure 6-3: Logging to a file

The FileHandler object synchronises access to the log file. If you omit the clearHandlers() call shown in the above example, log records will be written to the default console handler and also to the file handler. You will see error messages on the console and they will also be written to the file.

Logging to a stream

Ibex can log messages to a stream created by the caller. The stream is any object which implements the System.IO.Stream interface. To log messages to a stream, create an ibex4.logging.StreamHandler object and then tell the logger to log to this object. The example in Figure 6-4 logs to a MemoryStream, but any valid stream can be used.

using System;
using System.IO;
using ibex4;
using ibex4.logging;
		
public class Create {
		
  public static void Main( string[] args ) {
		
    Logger.getLogger().clearHandlers();
    MemoryStream stream = new MemoryStream();
    StreamHandler h = new StreamHandler( stream );
    Logger.getLogger().addHandler( h )

Figure 6-4: Logging to a stream

If you omit the clearHandlers() call shown in the above example log records will be written to the default console handler and to the stream handler as well.

Logging to multiple destinations

Errors can be logged to any number of handlers. The example in Figure 6-5 logs to a file called "xslfo.log", to a memory stream and to the console.

using System;
using System.IO;
using ibex4;
using ibex4.logging;
public class Create {
public static void Main( string[] args ) {
 
   MemoryStream stream = new MemoryStream();
   Logger.getLogger()
        .addHandler( new ConsoleHandler() )
        .addHandler( new StreamHandler( stream ) )
        .addHandler( new FileHandler("xslfo.log") );
   }
}
      

Figure 6-5: Logging to multiple destinations