# Logging and Auditing

Logging is an important means of gaining insight into your application's runtime behavior. OpenJPA provides a flexible logging system that integrates with many existing runtime systems, such as application servers and servlet runners.

There are five built-in logging plugins: a default logging framework that covers most needs, a Log4J delegate, a SLF4J delegate, an Apache Commons Logging delegate, and a no-op implementation for disabling logging.

Logging can have a negative impact on performance. Disable verbose logging (such as logging of SQL statements) before running any performance tests. It is advisable to limit or disable logging for a production system. You can disable logging altogether by setting the `openjpa.Log` property to `none`.

## Logging Channels

Logging is done over a number of logging channels, each of which has a logging level which controls the verbosity of log messages recorded for the channel. OpenJPA uses the following logging channels:

- `openjpa.Tool`: Messages issued by the OpenJPA command line and Ant tools. Most messages are basic statements detailing which classes or files the tools are running on. Detailed output is only available via the logging category the tool belongs to, such as `openjpa.Enhance` for the enhancer (see ) or `openjpa.MetaData` for the mapping tool (see ). This logging category is provided so that you can get a general idea of what a tool is doing without having to manipulate logging settings that might also affect runtime behavior.

- `openjpa.Enhance`: Messages pertaining to enhancement and runtime class generation.

  enhancement log messages

- `openjpa.MetaData`: Details about the generation of metadata and object-relational mappings.

  metadata log messages

- `openjpa.Runtime`: General OpenJPA runtime messages.

- `openjpa.Query`: Messages about queries. Query strings and any parameter values, if applicable, will be logged to the `TRACE` level at execution time. Information about possible performance concerns will be logged to the `INFO` level.

  Query log messages

- `openjpa.DataCache`: Messages from the L2 data cache plugins.

  caching log messages

- `openjpa.jdbc.JDBC`: JDBC connection information. General JDBC information will be logged to the `TRACE` level. Information about possible performance concerns will be logged to the `INFO` level.

  JDBC log messages

- `openjpa.jdbc.SQL`: This is the most common logging channel to use. Detailed information about the execution of SQL statements will be sent to the `TRACE` level. It is useful to enable this channel if you are curious about the exact SQL that OpenJPA issues to the datastore.

  The SQL issued to the database may contain sensitive information. By default the parameter values used in the prepared statements generated by OpenJPA will not be printed in the SQL log - instead you will see a ? for each value. The actual values may be printed by adding `PrintParameters=True` to the `openjpa.ConnectionFactoryProperties` property. Also see `Using the OpenJPA DataSource`
  SQL log messages

  When using the built-in OpenJPA logging facilities, you can enable SQL logging by adding `SQL=TRACE` to your `openjpa.Log` property.

  OpenJPA can optionally reformat the logged SQL to make it easier to read. To enable pretty-printing, add `PrettyPrint=true` to the `openjpa.ConnectionFactoryProperties` property. You can control how many columns wide the pretty-printed SQL will be with the `PrettyPrintLineLength` property. The default line length is 60 columns.

  While pretty printing makes things easier to read, it can make output harder to process with tools like grep.

  Pretty-printing properties configuration might look like so:

      <property name="openjpa.Log" value="SQL=TRACE"/>
      <property name="openjpa.ConnectionFactoryProperties"
          value="PrettyPrint=true, PrettyPrintLineLength=72"/>

- `openjpa.jdbc.SQLDiag`: This logging channel provides additional information about entity actitvies such as create, find, update or delete, and eager loading of relation or field properties. If you enable this channel, it is recommended that `openjpa.jdbc.SQL` channel is also enabled. The additional trace can help you relate the entity activities to the execution of SQL statements that OpenJPA issued to the datastore.

  SQLDiag log messages

  When using the built-in OpenJPA logging facilities, you can enable SQLDiag logging by adding `SQLDiag=TRACE` to your `openjpa.Log` property.

- `openjpa.jdbc.Schema`: Details about operations on the database schema.

  schema log messages

logging channels

## OpenJPA Logging

By default, OpenJPA uses a basic logging framework with the following output format:

`millis` `diagnostic context` `level` [`thread name`] `channel` - `message`

For example, when loading an application that uses OpenJPA, a message like the following will be sent to the `openjpa.Runtime` channel:

    2107  INFO   [main] openjpa.Runtime - Starting OpenJPA 2.2.0

The default logging system accepts the following parameters:

- `File`: The name of the file to log to, or `stdout` or `stderr` to send messages to standard out and standard error, respectively. By default, OpenJPA sends log messages to standard error.

- `DefaultLevel`: The default logging level of unconfigured channels. Recognized values are `TRACE, INFO, WARN, ERROR` and `FATAL`. Defaults to `INFO`.

- `DiagnosticContext`: A string that will be prepended to all log messages. If this is not supplied and an `openjpa.Id` property value is available, that value will be used.

- `<channel>`: Using the last token of the logging channel name, you can configure the log level to use for that channel. See the examples below.

Standard OpenJPA Log Configuration

    <property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO"/>

Standard OpenJPA Log Configuration + All SQL Statements

    <property name="openjpa.Log" value="DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>

Logging to a File

    <property name="openjpa.Log" value="File=/tmp/org.apache.openjpa.log, DefaultLevel=WARN, Runtime=INFO, Tool=INFO"/>

logging default

## Disabling Logging

Disabling logging can be useful to analyze performance without any I/O overhead or to reduce verbosity at the console. To do this, set the `openjpa.Log` property to `none`.

Disabling logging permanently, however, will cause all warnings to be consumed. We recommend using one of the more sophisticated mechanisms described in this chapter.

logging disabling

## Log4J

When `openjpa.Log` is set to `log4j`, OpenJPA will delegate to Log4J for logging. In a standalone application, Log4J logging levels are controlled by a resource named `log4j.properties` , which should be available as a top-level resource (either at the top level of a jar file, or in the root of one of the `CLASSPATH` directories). When deploying to a web or EJB application server, Log4J configuration is often performed in a `log4j.xml` file instead of a properties file. For further details on configuring Log4J, please see the Log4J Manual. We present an example `log4j.properties` file below.

Standard Log4J Logging

    log4j.rootCategory=WARN, console
    log4j.category.openjpa.Tool=INFO
    log4j.category.openjpa.Runtime=INFO
    log4j.category.openjpa.Remote=WARN
    log4j.category.openjpa.DataCache=WARN
    log4j.category.openjpa.MetaData=WARN
    log4j.category.openjpa.Enhance=WARN
    log4j.category.openjpa.Query=WARN
    log4j.category.openjpa.jdbc.SQL=WARN
    log4j.category.openjpa.jdbc.SQLDiag=WARN
    log4j.category.openjpa.jdbc.JDBC=WARN
    log4j.category.openjpa.jdbc.Schema=WARN

    log4j.appender.console=org.apache.log4j.ConsoleAppender

logging Log4j

## Apache Commons Logging

Set the `openjpa.Log` property to `commons` to use the Apache Commons Logging thin library for issuing log messages. The Commons Logging library act as a wrapper around a number of popular logging APIs, including the Jakarta Log4J project, and the native java.util.logging package in JDK.

When using the Commons Logging framework in conjunction with Log4J, configuration will be the same as was discussed in the Log4J section above.

### JDK java.util.logging

When using JDK logging in conjunction with OpenJPA's Commons Logging support, logging will proceed through Java's built-in logging provided by the java.util.logging package. For details on configuring the built-in logging system, please see the Java Logging Overview.

By default, JDK's logging package looks in the `JAVA_HOME/lib/logging.properties` file for logging configuration. This can be overridden with the `java.util.logging.config.file` system property. For example:

    java -Djava.util.logging.config.file=mylogging.properties com.company.MyClass

JDK Log Properties

    # specify the handlers to create in the root logger
    # (all loggers are children of the root logger)
    # the following creates two handlers
    handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler

    # set the default logging level for the root logger
    .level=ALL

    # set the default logging level for new ConsoleHandler instances
    java.util.logging.ConsoleHandler.level=INFO

    # set the default logging level for new FileHandler instances
    java.util.logging.FileHandler.level=ALL

    # set the default formatter for new ConsoleHandler instances
    java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter

    # set the default logging level for all OpenJPA logs
    openjpa.Tool.level=INFO
    openjpa.Runtime.level=INFO
    openjpa.Remote.level=INFO
    openjpa.DataCache.level=INFO
    openjpa.MetaData.level=INFO
    openjpa.Enhance.level=INFO
    openjpa.Query.level=INFO
    openjpa.jdbc.SQL.level=INFO
    openjpa.jdbc.SQLDiag.level=INFO
    openjpa.jdbc.JDBC.level=INFO
    openjpa.jdbc.Schema.level=INFO

logging JDK
logging Apache Commons

## SLF4J

When `openjpa.Log` is set to `slf4j`, OpenJPA will delegate to SLF4J API for logging, which provides several adapters or a simple logging mechanism. For further details on logging adapters and configuring SLF4J, please see the SLF4J website.

Note, as SLF4J does not provide a `FATAL` log level the `SLF4JLogFactory` will map it to the `ERROR` log level.

logging SLF4j

## Custom Log

If none of available logging systems meet your needs, you can configure the logging system with a custom logger. You might use custom logging to integrate with a proprietary logging framework used by some applications servers, or for logging to a graphical component for GUI applications.

A custom logging framework must include an implementation of the org.apache.openjpa.lib.log.LogFactory interface. We present a custom LogFactory below.

Custom Logging Class

    package com.xyz;

    import org.apache.openjpa.lib.log.*;

    public class CustomLogFactory
        implements LogFactory {

        private String _prefix = "CUSTOM LOG";

        public void setPrefix(String prefix) {
            _prefix = prefix;
        }

        public Log getLog(String channel) {
            // Return a simple extension of AbstractLog that will log
            // everything to the System.err stream. Note that this is
            // roughly equivalent to OpenJPA's default logging behavior.
            return new AbstractLog() {

                protected boolean isEnabled(short logLevel) {
                    // log all levels
                    return true;
                }

                protected void log(short type, String message, Throwable t) {
                    // just send everything to System.err
                    System.err.println(_prefix + ": " + type + ": "
                        + message + ": " + t);
                }
            };
        }
    }

To make OpenJPA use your custom log factory, set the `openjpa.Log` configuration property to your factory's full class name. Because this property is a plugin property (see ), you can also pass parameters to your factory. For example, to use the example factory above and set its prefix to "LOG MSG", you would set the `openjpa.Log` property to the following string:

    com.xyz.CustomLogFactory(Prefix="LOG MSG")

logging custom

## OpenJPA Audit

Transactional applications often require to audit changes in persistent objects. OpenJPA can enable audit facility for all persistent entities in few simple steps.

### Configuration

Annotate Persistent Entity Any persistence entity can be enabled for audit by annotating with `org.apache.openjpa.audit.Auditable`.

          @javax.persistence.Entity
          @org.apache.openjpa.audit.Auditable
          public class MyDomainObject { ...}

This `Auditable` annotation enables auditing of creation, update or delete of `MyDomainObject` instances. The `Auditable` annotation accepts list of enumerated values `org.apache.openjpa.audit.AuditableOperation` namely `CREATE`, `UPDATE` and `DELETE` to customize only appropriate operations be audited. By deafult, all of the above operations are audited.

Configure Persistence Configuration The audit facility is invoked at runtime via configuration of `META-INF/persistence.xml`. The following property configures auditing via a default auditor

    <property name="openjpa.Auditor" value="default"/>

The default auditor does not do much. It simply prints each auditable instance with its latest and original states on a standard console (or to a designated file).

The latest state of an instance designates the state which is commited to the database. The originalstate designates the state when the instance entered the managed persistent context. For example, when a new instance is persisted or a existing instance is loaded from the database.

### Developing custom auditing

For real use case, an application will prefer more than printing the changed instances. The application, in such case, needs to implement `org.apache.openjpa.audit.Auditor` interface. This simple interface has the following method:

        /**
    	 * OpenJPA runtime will invoke this method with the given parameters
    	 * within a transaction.
    	 *
    	 * @param broker the active persistence context.
    	 * @param newObjects the set of auditable objects being created. Can be empty, but never null.
    	 * @param updates the set of auditable objects being updated. Can be empty, but never null.
    	 * @param deletes the set of auditable objects being deleted. Can be empty, but never null.
    	 */
    	public void audit(Broker broker, Collection<Audited> newObjects, Collection<Audited> updates,
    			Collection<Audited> deletes);

OpenJPA runtime will invoke this method before database commit. Via this callback method, the application receives the auditable instances in three separate collections of `org.apache.openjpa.audit.Auditable`. An `Auditable` instance provides the latest and original state of a persistent object. The latest object is the same persistent instance to be committed. The original instance is a transient instance holding the original state of the instance when it entered the managed context. The active persistence context is also supplied in this callback method, so that an application may decide to persist the audit log in the same database.

It is important to note that the original object can not be persisted in the same transaction, because it has the same persistent identity of the latest object.

A single instance of implemented `org.apache.openjpa.audit.Auditor` interface is available for a persistence unit. However, an application's own implementation of this interface need not be thread-safe, because OpenJPA runtime guards against concurrent invocation of the callback method.

The `org.apache.openjpa.audit.Auditor` interface is configurable. Hence any bean style getter and setter method on its implementation will be populated as usual for any other OpenJPA plugin. In the following example,

        <property name="openjpa.Auditor" value="com.acme.Auditor(param2=10,param2='hello')"/>

An instance of `com.acme.Auditor` will be instantiated and if it has been style getter and setter methods for `param1` and `param2`, then the respective setters will be called with `10` and `"hello"` before the instance being used.

logging
Log