Document Audit

🔖 Document Audit and Record Change Tracking

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:

Outcome

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:

Example

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:

Metric

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:

Stage

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.

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:

Step

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:

germain.apm.documentAudit.rule

to either:

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
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
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
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

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.

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
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;
};

warning Browser-Side Configuration Considerations

When generating document updates from a monitored user interface:

Consideration

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:

Step

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:

Capability

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:

Control

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:

Check

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.

ℹ️ Get Help

The Germain Team can help you set this up. Contact GermainUX Support.


Service: Analytics

Feature Availability: 2022.1 or later