Audit

Audit assigns semantic meaning to CRUD operations for the purposes of logging and audit. For example, we may want to log when users change their password or when an account is locked. Both actions are mutations on a user entity that update different fields. Audit can assign these actions to parameterized, human readable logging statements that can be logged to a file, written to a database, etc.

Core Concepts

A model’s lineage is the path taken through the entity relationship graph to reach it. A model and every prior model in its lineage are fully accessible to parameterize audit logging in Elide.

Annotations

Elide audits operations on classes and class fields marked with the Audit annotation.

The Audit annotation takes several arguments:

  1. The CRUD action performed (CREATE, DELETE, or UPDATE).
  2. An operation code which uniquely identifies the semantic meaning of the action.
  3. The statement to be logged. This is a template string that allows ‘{}’ variable substitution.
  4. An ordered list of Unified Expression Language expressions that are used to subtitute ‘{}’ in the log statement. Elide binds the model that is being audited and every model in its lineage to variables that are accessible to the UEL expressions. The variable names map to model’s type (typically the class name).

Example

Let’s say I have a simple user entity with a password field. I want to audit whenever the password is changed. The user is accessed via the URL path ‘/company/53/user/21’. I could annotate this action as follows:

@Entity
@Include
public class User {
    @Audit(action = Audit.Action.UPDATE,
           operation = 572,
           logStatement = "User {0} from company {1} changed password.",
           logExpressions = {"${user.userid}", "${company.name}"})
    private String password;
    private String userid;
}

Elide binds the User object to the variable name user and the Company object to the variable name company. The Company object is bound because it belongs to the User object’s lineage.

Customizing Logging

Customizing audit functionality in elide requires two steps:

  1. Define audit annotations on JPA entity classes and fields.
  2. Provide a Logger implementation to customize the handling of audit triggers. The default logger simply logs to slf4j.

Logger Implementation

A customized logger extends the following abstract class:

public abstract class AuditLogger {
    public void log(LogMessage message);
    public abstract void commit(RequestScope requestScope) throws IOException;
}