13.2. Audit Log

Storing information about the execution of process instances can be useful when you need to, for example:
  • Verify which actions have been executed in a particular process instance.
  • Monitor and analyze the efficiency of a particular process.
However, storing history information in the runtime database can result in the database rapidly increasing in size. Additionally, monitoring and analysis queries might influence the performance of your runtime engine. This is why process execution history logs are stored separately.
The JBoss BPM Suite creates a history log of execution based on events generated by the process engine during execution. This is possible because the JBoss BPM Suite runtime engine provides a generic event listener. That's why you can easily retrieve and store any information from the events and store it in a database. You can also use filters to limit the scope of the logged information.

13.2.1. Audit Data Model

The jbpm-audit module contains an event listener that stores process-related information in a database using Java Persistence API (JPA). The data model contains three entities: one for process instance information, one for node instance information, and one for (process) variable instance information:
  • The ProcessInstanceLog table contains the basic log information about a process instance.
  • The NodeInstanceLog table contains information about which nodes were actually executed inside each process instance. Whenever a node instance is entered from one of its incoming connections or is exited through one of its outgoing connections, that information is stored in this table.
  • The VariableInstanceLog table contains information about changes in variable instances. The default is to only generate log entries when (after) a variable changes. It is also possible to log entries before the variable (value) changes.

13.2.2. Audit Data Model Description

Each of the entities in the audit data model contain following elements:
An audit data model that provides ProcessInstanceLog, NodeInstanceLog, and VariableInstanceLog nodes.

Figure 13.2. Audit Data Model

Table 13.8. ProcessInstanceLog

Field Description Nullable
id The primary key and id of the log entity. NOT NULL
duration Duration of a process instance since its start date.  
end_date The end date of a process instance when applicable.  
externalId Optional external identifier used to correlate various elements, for example deployment id.  
user_identity Optional identifier of the user who started the process instance.  
outcome Contains the outcome of a process instance, for example the error code.  
parentProcessInstanceId The process instance id of the parent process instance.  
processid Id of the executed process.  
processinstanceid The process instance id. NOT NULL
processname The name of the process.  
processversion The version of the process.  
start_date The start date of the process instance.  
status The status of process instance that maps to process instance state.  

Table 13.9. NodeInstanceLog

Field Description Nullable
id Primary key and id of the log entity. NOT NULL
connection Identifier of the sequence flow that led to this node instance.  
log_date Date of the event.
externalId Optional external identifier used to correlate various elements, for example deployment id.
nodeid Node id of the corresponding node in the process definition.
nodeinstanceid Instance id of the node.
nodename Name of the node.
nodetype The type of the node.
processid Id of the executed process.
processinstanceid Id of the process instance. NOT NULL
type The type of the event (0 = enter, 1 = exit). NOT NULL
workItemId Optional identifier of work items available only for certain node types.  

Table 13.10. VariableInstanceLog

Field Description Nullable
id Primary key and id of the log entity. NOT NULL
externalId Optional external identifier used to correlate various elements, for example deployment id.
log_date Date of the event.
processid Id of the executed process.
processinstanceid Id of the process instance. NOT NULL
oldvalue Previous value of the variable at the time of recording of the log.
value The value of the variable at the time of recording of the log.
variableid Variable id in the process definition.
variableinstanceid The id of the variable instance.

13.2.3. Storing Process Events in a Database

To log process history in a database, register a logger in your session:
EntityManagerFactory emf = ...;
StatefulKnowledgeSession ksession = ...;
AbstractAuditLogger auditLogger = AuditLoggerFactory.newJPAInstance(emf);
ksession.addProcessEventListener(auditLogger);

// invoke methods one your session here
Modify persistence.xml to specify a database. You need to include audit log classes as well (ProcessInstanceLog, NodeInstanceLog, and VariableInstanceLog). See the example:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>


<persistence
  version="2.0"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd
  http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance>

  <persistence-unit name="org.jbpm.persistence.jpa" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/jbpm-ds</jta-data-source>
    <mapping-file>META-INF/JBPMorm.xml</mapping-file>
    <class>org.drools.persistence.info.SessionInfo</class>
    <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
    <class>org.drools.persistence.info.WorkItemInfo</class>
    <class>org.jbpm.persistence.correlation.CorrelationKeyInfo</class>
    <class>org.jbpm.persistence.correlation.CorrelationPropertyInfo</class>
    <class>org.jbpm.runtime.manager.impl.jpa.ContextMappingInfo</class>

    <class>org.jbpm.process.audit.ProcessInstanceLog</class>
    <class>org.jbpm.process.audit.NodeInstanceLog</class>
    <class>org.jbpm.process.audit.VariableInstanceLog</class>

    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
      <property name="hibernate.max_fetch_depth" value="3"/>
      <property name="hibernate.hbm2ddl.auto" value="update"/>
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.transaction.jta.platform"
      value="org.hibernate.service.jta.platform.internal.BitronixJtaPlatform"/>
    </properties>
  </persistence-unit>
</persistence>

13.2.4. Storing Process Events in a JMS Queue

Synchronous storing of history logs and runtime data in one database may be undesirable due to performance reasons. In that case, you can use JMS logger to send data into a JMS queue instead of directly storing it into a database. You can also configure it to be transactional in order to avoid issues with inconsistent data (for example when the process engine transaction is reversed).
Example configuration of JMS queue:
ConnectionFactory factory = ...;
Queue queue = ...;
StatefulKnowledgeSession ksession = ...;
Map<String, Object> jmsProps = new HashMap<String, Object>();
jmsProps.put("jbpm.audit.jms.transacted", true);
jmsProps.put("jbpm.audit.jms.connection.factory", factory);
jmsProps.put("jbpm.audit.jms.queue", queue);
AbstractAuditLogger auditLogger = AuditLoggerFactory.newInstance(Type.JMS, session, jmsProps);
ksession.addProcessEventListener(auditLogger);

// invoke methods of your session here