Document Audit
Feature
Germain's Document Audit mechanism enables the storage and tracking of document changes as events, providing a real-time history of document modifications. This mechanism is beneficial in various use cases:
Data Audit Trail
The Document Audit mechanism supports tracking and auditing changes to structured data—such as records—in external systems. Germain can connect to these systems via REST, SQL, SOAP, or other supported protocols to capture and store data changes.
Data Status Tracking
It also tracks the amount of time a record remains in a particular status. This insight is valuable for monitoring and analyzing metrics such as ticket response times, service request resolution times, or the progress of any business process where status changes are key.
Configuration
Consume DocumentChange outputs
To process DocumentChange events output by the Document Service, customize the document-audit-default
Rule or create a new rule tailored to your needs.
In the Configuration Console, ensure that the germain.apm.documentAudit.rule
property is set to either document-audit-default
or the name of your custom rule.
Example
A customized version of the document-audit-default
Rule for Siebel Service Requests:
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 new SR Status Changed 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
Schema of a DocumentChange:
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 (engine)
Customize the rule(s) used by various monitoring components (e.g., QueryMonitor) to generate DocumentUpdate
events as input for the Document Service.
Example
The following example is based on Siebel Service Requests. It shows the SQL used by the QueryMonitor:
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 Rule referenced by the QueryMonitor:
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), "Siebel SR", $msg.getString(4));
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
Schema of a DocumentUpdate:
interface DocumentUpdate {
DocumentUpdate(String documentId, String documentType, String author);
OffsetDateTime timestamp;
HashMap<String, String> documentMetadata; // Custom properties about the document e.g. { title: 'My First Opportunity' }
void addAttribute(String attributeName, String value); // Set custom properties about this change
void set(String path, @Nullable Object value); // Set fields of the document. The format of paths: "child.grandchild.greatgrandchild"
void deletePath(String path); // To drop a field from a document.
}
Generate DocumentUpdate inputs (Web UX)
Customize the initScript
of the corresponding Web-UX Monitoring Profile to generate DocumentUpdate
events as input for the Document Service.
BOOMR.utils.addToDocumentAuditQueue(update: DocumentUpdate);
type DocumentUpdate = {
documentId: string
documentType: string
documentMetadata: Record<string, string> // Custom properties about the document
timestamp: number
author: string
metadata: Record<string, string> // Custom properties about this change
fieldUpdates: FieldUpdate[]
}
type FieldUpdate = {
path: string
valueJson: string
spliceIndex: number
deleteCount: number
}
As with anything else, we're here to help with configuration. Please don't hesitate to contact us.
Service: Analytics
Feature Availability: 2022.1 or later