> ## Documentation Index
> Fetch the complete documentation index at: https://docs.germainux.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Document Audit

> GermainUX Document Audit records changes to business records as time-stamped events, showing what changed, when, who made the change, and which field.

Service
`Analytics`

Availability
2022.1 or later

> **[Business Outcomes](#business-outcomes)**
>
> Audit trail benefits

> **[Core Data Types](#core-data-types)**
>
> Records tracked for audit

> **[Track Status Duration](#track-status-duration)**
>
> Time spent in each status

> **[Troubleshooting](#troubleshooting)**
>
> Fix missing audit changes

## Overview

GermainUX Document Audit records changes to structured business records as time-stamped events, providing a near-real-time history of what changed, when it changed, who made the change and which field was affected. In this context, a **document** is a structured record or object snapshot—not necessarily a file—such as a service request, ticket, order, opportunity, customer record or configuration object.

Document Audit helps organizations monitor data changes, measure how long records remain in each status and connect those changes with business processes, users and application activity. Effective audit controls should focus on stable record identifiers, targeted field selection, consistent timestamp and author attribution, secure data-source access, and rules that convert only relevant changes into events, KPIs, alerts or reports.

To maintain reliable audit visibility, organizations should minimize unnecessary data collection, mask or exclude sensitive values, restrict access to audit history, define retention expectations and validate that generated changes align with the intended business process and compliance requirements.

## Business Outcomes

GermainUX Document Audit helps organizations:

* Maintain a searchable history of record and field changes.
* Identify who changed a record and when the change occurred.
* Compare current and previous values.
* Measure how long records remain in a status or process stage.
* Detect delayed, unexpected or unauthorized changes.
* Analyze ticket, request, order and workflow progression.
* Turn selected changes into GermainUX events, KPIs, alerts and reports.
* Correlate data changes with user sessions, application transactions and business outcomes.

## Common Use Cases

### Data Audit Trail

Document Audit tracks changes to structured data maintained in external systems. GermainUX can retrieve or receive record updates through supported sources such as SQL queries, REST APIs, SOAP services, browser monitoring and other integrations.

Examples include:

* Service-request status, priority or ownership changes
* Opportunity stage and amount changes
* Order, inventory or fulfillment updates
* Ticket assignment and resolution changes
* Customer, account or profile updates
* Configuration and metadata changes

### Status-Duration Tracking

By recording each status transition, GermainUX can calculate how long a record remains in a particular state.

Examples include:

* Time before a ticket receives its first response
* Time spent waiting for approval
* Service-request resolution time
* Duration of each order-fulfillment stage
* Time an opportunity remains in a sales stage
* Process bottlenecks and SLA violations

## How Document Audit Works

The audit workflow has three main stages:

* A monitoring component creates a `DocumentUpdate` representing the latest known state of a record.
* The Document Service compares that update with the previously stored state.
* For each detected field change, the service produces a `DocumentChange` that can be processed by a rule and converted into an analytical event.

```text theme={null}
External record or application
        ↓
DocumentUpdate
        ↓
Document Service: compare and store state
        ↓
DocumentChange
        ↓
Rule → Event, KPI, alert, report or automation
```

The exact behavior depends on the monitoring component, document identifiers, field paths, rules and storage configuration.

## Core Data Types

### `DocumentUpdate`

A `DocumentUpdate` describes the latest state—or a partial update—of a tracked record.

Important fields include:

| Field | Purpose |
| - | - |
| `documentId` | Stable identifier for the tracked record |
| `documentType` | Logical record type, such as `Siebel SR` |
| `author` | User or system associated with the update |
| `timestamp` | Time associated with the update |
| `documentMetadata` | Searchable properties describing the record |
| Field paths and values | Current values to compare with the stored document state |

### `DocumentChange`

A `DocumentChange` represents a field-level difference detected by the Document Service.

Important fields include:

| Field | Purpose |
| - | - |
| `documentId` | Identifier of the changed record |
| `documentType` | Logical record type |
| `path` | Path of the field that changed |
| `oldValue` | Previous value |
| `value` | New value |
| `author` | User or system associated with the change |
| `timeCreated` | Time when the change event was created |
| `documentMetadata` | Context describing the record |
| `metadata` | Context describing the specific change |

## Configuration Overview

To configure Document Audit:

* Identify the record type and stable identifier.
* Select the fields and metadata to monitor.
* Configure a source to create `DocumentUpdate` objects.
* Send updates to the Document Service.
* Configure a rule to process the resulting `DocumentChange` objects.
* Convert relevant changes into GermainUX facts or events.
* Create the required KPIs, dashboards, alerts or process analytics.

Avoid using mutable values as `documentId`. The identifier must consistently represent the same business record across updates.

## Process `DocumentChange` Outputs

The Document Service outputs `DocumentChange` events when it detects differences between the incoming update and the stored record state.

Customize the `document-audit-default` rule or create a dedicated rule for the monitored record type.

In the Configuration Console, set:

```text theme={null}
germain.apm.documentAudit.rule
```

to either:

```text theme={null}
document-audit-default
```

or the name of the custom rule.

### Example: Siebel Service Request Status Change

The following rule processes status changes for Siebel Service Requests and creates a GermainUX `GenericEvent`.

```go theme={null}
package com.germainsoftware.apm.analytics.audit;

dialect "mvel"

import com.germainsoftware.apm.data.model.*;
import com.germainsoftware.apm.storage.documentAudit.DocumentChange;
import java.time.*;

global org.slf4j.Logger logger;
global com.germainsoftware.apm.storage.StorageService storage;

rule "Siebel Service Request Rule"
when
    $update : DocumentChange(
        documentType == "Siebel SR",
        path == "status"
    )
then
    logger.info("SR Change: {}", $update.value);

    // Create a new Service Request status-change event.
    GenericEvent ev = new GenericEvent();
    ev.name = $update.documentType;
    ev.type = "Siebel:SR Change";
    ev.timestamp = $update.timeCreated;
    ev.businessObject = $update.value;
    ev.sequence = $update.documentId;

    storage.insertFact(ev);
    retract($update);
end
```

This example stores the new status in `businessObject` and uses the Service Request document ID as the event sequence. Adapt the event fields to the KPI and analysis required by your environment.

### `DocumentChange` Schema

```ruby theme={null}
class DocumentChange {
    String documentId;
    String documentType;
    Map<String, String> documentMetadata;
    ValueMap documentBody;
    OffsetDateTime timeCreated;
    Map<String, String> metadata;
    String author;
    String path;
    Object value;
    Object oldValue;
}
```

## Generate `DocumentUpdate` Inputs from the Engine

Monitoring components such as `QueryMonitor` can retrieve records and use a rule to create `DocumentUpdate` objects.

### Example: Query Siebel Service Requests

```sql theme={null}
select
    LAST_UPD,
    ROW_ID,
    CREATED,
    CREATED_BY,
    LAST_UPD_BY,
    SR_NUM,
    SR_PRIO_CD,
    SR_SEV_CD,
    SR_STAT_ID,
    SR_TITLE
from SIEBEL.S_SRV_REQ
where LAST_UPD > ?
order by LAST_UPD asc
```

The query retrieves Service Requests changed since the last monitored timestamp.

### Example: Convert the Query Result to `DocumentUpdate`

```text theme={null}
import java.util.Calendar;
import java.util.regex.*;
import java.time.*;
import java.time.temporal.*;
import com.germainsoftware.apm.config.data.*;
import com.germainsoftware.apm.converter.*;
import com.germainsoftware.apm.data.model.*;
import com.germainsoftware.apm.data.indexer.*;
import com.germainsoftware.apm.message.*;
import com.germainsoftware.apm.model.*;
import com.germainsoftware.apm.router.*;

global org.slf4j.Logger logger;
global com.germainsoftware.apm.converter.DatamartConverter datamart;
global com.germainsoftware.apm.router.RouterContext context;

rule "Siebel SR"
when
    $msg : QueryResultMessage(category == "Siebel SR")
then
    DocumentUpdate doc = new DocumentUpdate(
        $msg.getString(1), // ROW_ID: stable document identifier
        "Siebel SR",      // Document type
        $msg.getString(4)  // LAST_UPD_BY: author
    );

    doc.timestamp = $msg.getTimestamp(0);                  // LAST_UPD
    doc.set("created", $msg.getTimestamp(2).toString());   // CREATED
    doc.set("createdBy", $msg.getString(3));               // CREATED_BY
    doc.set("number", $msg.getString(5));                  // SR_NUM
    doc.set("priority", $msg.getString(6));                // SR_PRIO_CD
    doc.set("severity", $msg.getString(7));                // SR_SEV_CD
    doc.set("status", $msg.getString(8));                  // SR_STAT_ID
    doc.set("title", $msg.getString(9));                   // SR_TITLE

    Queues.postDocumentUpdate(doc);
    retract($msg);
end
```

The array indexes in this rule depend on the order of columns in the SQL query. If the query changes, update the indexes and field mapping together.

### `DocumentUpdate` API Schema

The following is a simplified schema for reference; it is not intended to be copied as a compilable Java interface.

```text theme={null}
interface DocumentUpdate {
    DocumentUpdate(
        String documentId,
        String documentType,
        String author
    );

    OffsetDateTime timestamp;

    // Searchable properties describing the document.
    HashMap<String, String> documentMetadata;

    // Add metadata describing this update.
    void addAttribute(String attributeName, String value);

    // Set a document field. Nested paths use dot notation:
    // child.grandchild.greatgrandchild
    void set(String path, @Nullable Object value);

    // Remove a field from the document.
    void deletePath(String path);
}
```

## Generate `DocumentUpdate` Inputs from Web UX

A Web UX Monitoring Profile can generate `DocumentUpdate` objects from authorized browser-side application activity.

Customize the profile’s `initScript` and add the update to the Document Audit queue:

```typescript theme={null}
BOOMR.utils.addToDocumentAuditQueue(update);

type DocumentUpdate = {
  documentId: string;
  documentType: string;
  documentMetadata: Record<string, string>;
  timestamp: number;
  author: string;
  metadata: Record<string, string>;
  fieldUpdates: FieldUpdate[];
};

type FieldUpdate = {
  path: string;
  valueJson: string;
  spliceIndex: number;
  deleteCount: number;
};
```

### Browser-Side Configuration Considerations

When generating document updates from a monitored user interface:

* Use a stable record identifier.
* Send only fields required for the audit use case.
* Avoid collecting passwords, payment data or other unnecessary sensitive content.
* Apply masking or exclusion before data is transmitted.
* Set timestamps consistently.
* Include an author only when collection is authorized.
* Test create, update, nested-field and deletion behavior.
* Confirm that repeated identical updates do not generate unwanted change noise.

## Track Status Duration

To measure how long a record remains in a status:

* Generate a `DocumentUpdate` whenever the status changes.
* Convert the resulting `DocumentChange` into a time-stamped status event.
* Use the stable document ID to order events for the same record.
* Calculate the duration between consecutive status events.
* Define KPIs and SLAs for expected status duration.

Status analysis can then be segmented by record type, priority, owner, team, application, customer or other captured metadata.

## Analytics, Alerts and Automation

Document Audit events can support:

* Audit-history dashboards
* Field-change frequency and trends
* Status-duration and aging reports
* Detection of unexpected or prohibited changes
* SLA alerts for records remaining too long in a status
* Correlation with user sessions and application transactions
* Business-process and workflow analysis
* Approved follow-up or remediation workflows

Rules should create only the analytical events required by the use case to avoid unnecessary data volume and noise.

## Security and Data Governance

Document Audit can collect sensitive business and personal data. Configure it according to the organization’s security, privacy, retention and access requirements.

Recommended controls include:

* Monitor only required record types and fields.
* Mask, anonymize or exclude sensitive values.
* Restrict audit-history access to authorized roles.
* Define retention requirements for document state and change events.
* Protect credentials used by SQL, REST, SOAP and other data sources.
* Validate author attribution and timestamp accuracy.
* Document the rules that convert changes into alerts or automated actions.

Document Audit provides application-level change visibility; whether it satisfies a particular legal or regulatory audit requirement depends on the organization’s configuration, controls and governance.

## Troubleshooting

If expected changes are not appearing:

* Confirm that the source is producing `DocumentUpdate` objects.
* Verify that `documentId` and `documentType` are populated consistently.
* Check the field path and incoming value.
* Confirm that updates are reaching the Document Service.
* Verify the `germain.apm.documentAudit.rule` property.
* Confirm that the rule matches the expected `documentType` and `path`.
* Review rule execution and storage logs.
* Verify that the generated event is supported by the intended KPI and dashboard.

## Additional Resources

> **[Compliance](https://docs.germainux.com/main/compliance-privacy-and-security.md)**
>
> Read more

> **[Analytics](https://docs.germainux.com/main/analytics.md)**
>
> More Analytics Features

> **[Automation](https://docs.germainux.com/main/automation.md)**
>
> More Automation Features

> **[Dashboards](https://docs.germainux.com/main/dashboard-and-report.md)**
>
> Dashboards and reports overview

> **[Reports](https://docs.germainux.com/main/reporting-automatic.md)**
>
> Automatic and scheduled reports

> **[Management](https://docs.germainux.com/main/management.md)**
>
> More Management Features

## Get Help

> **[Contact GermainUX Support](https://docs.germainux.com/main/support.md)**
>
> The Germain Team can help you set this up.

> **Can't find what you need?**
>
> Search all GermainUX docs with **Ctrl + K**, or use the feedback buttons at the bottom of this page to tell us what is missing.

The content of this document is proprietary to GERMAIN SOFTWARE.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.