Direct Incident Logging (Using QueueAdapters)

Necessary Steps

To log incidents directly in your code, the following requirements have to be fulfilled:

1. all necessary libs (bugtrap-main and required plugin jars) have to be present on the classpath of the application
2. a configuration that determines the required working and desired plugins has to be present
3. error handling code blocks of the application need to be extended with calls of the BugTrap logging methods\

Point 1 won`t be described here; please have a look at the Plugins Overview Page, pick necessary plugins, the bugtrap-main jar and put them on the classpath.

Configuring BugTrap: Abstract

Internally, BugTrap basically knows 2 things: incident data and data queues that cache these incident data. If you run into the situation where an incident is to be reported, you ask BugTrap to (re-)open such a queue for the hosting application and put the incident data into it. Per definition, there is one queue for a specific application that takes all reports. To create a queue for the hosting application, BugTrap needs the following informations:

1. the name of the monitored application
2. the current version of the application
3. the number of acceptabe iterations of the same incident before it BugTrap will discard further reports which is meant to prevent unnecessary reporting redundancy\

As a queue itself does not do anything, plugins will be registered at the queue, performing tasks on the incoming incident data. To be able to initialise said plugins, the following informations are necessary as well:

4. a declaration of the required plugins
5. a plugin-specific configuration for each plugin\

Configuring BugTrap: Where

The configuration is done by declaring string key-value pairs which will be mapped to the base module or the requested plugins.
There are 2 approaches when configuring BugTrap:

1. you can provide the properties using a Properties object at runtime
2. you can provide a file (./bugtrap-PROJECTNAME.properties) on the classpath which will be read upon cache initialisation\

The latter is recommended as it does not require you to recompile your application to change the BugTrap configuration. You always have to provide the configuration completely, containing the properties for the base module and the plugins.

Configuration BugTrap: How

If you want to use plugins (you surely want to, as bugtrap-base only provides the data queue), you just have to make sure, that the plugin jars and their dependencies are present on the classpath. Furthermore, you declare the bugtrap.worker property and plugin properties (have a look at the corresponding plugin pages for the expected additional plugin properties). Following a list of common properties, which are read by bugtrap-base:

Property Namemandatory/optionalValue TypeDescription
bugtrap.projectnamemandatorystringThe name of your application (length < 33, a-zA-Z_.0-9-)
bugtrap.projectversionmandatorystringThe version of your application.
bugtrap.maxincidentsoptional, default 2shortThe maximum number of equal incident reports that are to be accepted.
bugtrap.workeroptionalcomma-separated
list of strings
A list of freely ("bugtrap" is a reserved name for bugtrap-base) choosable worker names that are used for the subsequent worker configurations.

See below for a configuration example.

Configuring a Queue, Logging Data (Example Code)

As stated above, you always deal with a data queue, which caches the incident reports. To (re-)open a queue, you call the Adapters class, providing a configuration as a Properties or indirectly using a file. Let`s try it with a Properties object:

Properties properties = new Properties();

properties.setProperty("bugtrap.projectname", "myProject");
properties.setProperty("bugtrap.projectversion","0.01");
properties.setProperty("bugtrap.worker","worker1,worker2");
properties.setProperty("bugtrap.maxincidents","2");

properties.setProperty("worker1.factory","...");
properties.setProperty("worker1.aProperty","...");
...

properties.setProperty("worker2.factory","...");
properties.setProperty("worker2.aProperty","...");

Now that we have a configuration, we can open the queue:

// a QueueAdapter gets created by providing the configuration
QueueAdapter queueAdapter = Adapters.getAdapter(properties);

// once created, the queueAdapter can always be accessed providing the projectName
// given upon the first call of Adapters
queueAdapter = Adapters.getAdapter("myProject");

The actual incident reporting is done using different logIncident methods:

// creates an incident based on a message string and a app component string
Incident incident = queueAdapter.logIncident("Could not read source file!", "fileImporter");

// creates an incident based on a Throwable (e.g. an Exception) and an app component string
incident = queueAdapter.logIncident(new Exception("Exception occurred while reading source file."),
                                    "fileImporter"); 

The Incident return object models the incident. Lets start to add further properties and a binary attachment:

/* Now that you have an Incident, you can populate it with 
further properties of interest or add binary data */

// adds a property that might be interesting for the later debugging
incident.setProperty("anInterestingProperty", "thePropertyValue");

// now lets add the faulty import target file
incident.addAttachment(new AttachmentImpl(new File("./sourceTextfile.txt"), "text/plain"));

Thats it! Once you called one of the queueAdapter.logIncident methods, the incident resides in the internal cache and gets treated according to the configuration.