Hi,

Here, a Documentum DFC standalone sample program in order to create entries in dm_audittrail. DCTM provides several more evolved methods for example to register an audit event (dm_save) for specific custom object and its subtypes and including new values of attributes in order to create automatically entries,

Very good article : https://www.bluefishgroup.com/insights/articles/the-content-server-audit-facility/

public void registerAudit(IDfSession session) throws DfException {
	// Get an instance of the audit manager using the session
	IDfAuditTrailManager auditMgr = session.getAuditTrailManager();
	// Setup the request parameters
	String objectType = "vendor_admin";
	String eventName = "dm_save";

	boolean auditSubTypes = true; // we want to audit subtypes also
	boolean signAuditEntries = false; // disable tamper-evident Audit Trail
	int authentication = 0; // we don't require user to authenticate
	String description = "Save Vendor Admin"; // shows up in each audit entry
	String[] auditAttrs = { "va_name, "va_tax_id" };

	// Use the audit manager to register the audit.
	// We do not care about controlling applications or workflows,
	// so we pass null for those arguments.
	auditMgr.registerEventForType(objectType, eventName, auditSubTypes, 
		null, // controllingApp
		null, // policyId
		null, // stateName
		signAuditEntries,
		authenticate,
		description,
		new DfList(attrs));
}

 
Here, a simple code in order to create audit entries without registration:

package com.huo.test.ecm.test2;

import com.documentum.fc.client.DfClient;
import com.documentum.fc.client.DfQuery;
import com.documentum.fc.client.IDfAuditTrailManager;
import com.documentum.fc.client.IDfClient;
import com.documentum.fc.client.IDfCollection;
import com.documentum.fc.client.IDfQuery;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.common.DfId;
import com.documentum.fc.common.DfLoginInfo;
import com.documentum.fc.common.IDfLoginInfo;

/*
 Documentum DFC Standalone Sample Program

 Creation of audit trail entries
 */

public class DMAuditTrailTest {

	IDfSysObject sysObject = null;
	IDfSession idfSession = null;
	IDfSessionManager sessMgr = null;

	public DMAuditTrailTest(String user, String passwd, String docbase) throws Exception {
		getDfSession(user, passwd, docbase);
	}

	public IDfSession getDfSession(String args1, String args2, String args3) throws Exception {
		
		IDfLoginInfo login = new DfLoginInfo();
		login.setUser(args1);
		login.setPassword(args2);
		IDfClient client = DfClient.getLocalClient(); //new DfClient();
		sessMgr = client.newSessionManager();
		sessMgr.setIdentity(args3, login);
		idfSession = sessMgr.getSession(args3);

		if (idfSession != null)
			System.out.println("Session created successfully");

		return idfSession;
	}


	public void releaseSession() throws Exception {
		sessMgr.release(idfSession);
	}
	
	public void createAuditTrailEntry(String objectId, String eventName) throws Exception {
		IDfAuditTrailManager mgr = idfSession.getAuditTrailManager();
		//  createAudit(IDfId objectId, String event, String[] stringArgs, IDfId[] idArgs)  
		mgr.createAudit(new DfId(objectId), eventName, null, null);
	}

	public int getNbEntriesOfAuditTrail(String eventName) throws Exception{
		IDfCollection resCount = null;
		int nbEntries = 0;
		try{
			String dql = "select count(r_object_id) as cnt from dm_audittrail where event_name = '"+eventName+"' order by time_stamp desc";
			IDfQuery query = new DfQuery();
			query.setDQL(dql);
			resCount = query.execute(idfSession, IDfQuery.DF_EXEC_QUERY);
			if(resCount!=null){
				resCount.next();
				nbEntries = resCount.getInt("cnt");
			}
			
		} finally {
			if (resCount!=null) {
				resCount.close();
			}
		}//end-if
		return nbEntries;
	}
	
	public static void main(String[] args) throws Exception {

		String user = "huouser";
		String passwd = "pwd_4huouser";
		String docbase = "MY_DOCBASE_DEV";

		boolean isTransactionalSession = false;
		boolean noErrorWithCurrentDocument = false;

		DMAuditTrailTest object = new DMAuditTrailTest(user, passwd, docbase);

		try {
			if (!object.idfSession.isTransactionActive()) {
				object.idfSession.beginTrans();
				isTransactionalSession = true;
			}
			String eventName =  "Executing createAuditTrailInput :)";
			String objectId = "090xxxxxxxxf1d";
			//
			int nbEntries1 = object.getNbEntriesOfAuditTrail(eventName);
			System.out.println("Nb of audit trail for the event '"+eventName+"' = "+ nbEntries1 + "(BEFORE adding)");
			//
			object.createAuditTrailEntry(objectId, eventName);
			//
			int nbEntries2 = object.getNbEntriesOfAuditTrail(eventName);
			System.out.println("Nb of audit trail for the event '"+eventName+"' = "+ nbEntries2 + "(AFTER adding) - under condition that the transaction is committed!!!!");
			
			noErrorWithCurrentDocument = true;
		} finally {
			if(object!=null){
				if (isTransactionalSession) {
					if (noErrorWithCurrentDocument) {
						object.idfSession.commitTrans();
					} else {
						object.idfSession.abortTrans();
					}
				}
				
				// to release a docbase session
				object.releaseSession();
			}
		}
		
	}
}

 
Below, an example of output for this program:

Session created successfully
Nb of audit trail for the event 'Executing createAuditTrailInput :)' = 2(BEFORE adding)
Nb of audit trail for the event 'Executing createAuditTrailInput :)' = 3(AFTER adding) - under condition that the transaction is committed!!!!

 
The important point of code is :

	public void createAuditTrailEntry(String objectId, String eventName) throws Exception {
		IDfAuditTrailManager mgr = idfSession.getAuditTrailManager();
		//  createAudit(IDfId objectId, String event, String[] stringArgs, IDfId[] idArgs)  
		mgr.createAudit(new DfId(objectId), eventName, null, null);
	}

 
 
Extended User Privileges
To do anything on auditing, the current user must have specific extended user privileges. There are three extended user privileges which the Content Server
uses to manage security authorization for audit requests:

  • Config Audit : User can execute the Audit and Unaudit methods to start and stop auditing, its integer value is 8
  • Purge Audit : User can remove Audit Trail entries from the Docbase, its integer value is 16
  • View Audit : User can view Audit Trail entries, its integer value is 32

 
We have an user yith the Extended Privileges = Config, View and Purge Audit:

select user_xprivileges from dm_user where user_name = 'gedadm';
= 56
= 8 + 16 + 32

 
TEST 1 :
Even if the maximum extended user privileges, it is not possible to modify an existing AuditTrail object via DFC/DQL/API, any tentative will get the exception DfException:: THREAD: main; MSG: [DM_AUDITTRAIL_E_CANT_MODIFY]error: “You can not modify any existing AuditTrail object 5f0xxxxxxxxxxxxxbf.”; ERRORCODE: 100; NEXT: nullerror:

	public void createAuditTrailEntry(String objectId, String eventName) throws Exception {
		IDfAuditTrailManager mgr = idfSession.getAuditTrailManager();
		//  createAudit(IDfId objectId, String event, String[] stringArgs, IDfId[] idArgs)  
		IDfId auditTrailId = mgr.createAudit(new DfId(objectId), eventName, null, null);
		
		// => Exception in thread "main" DfException:: THREAD: main; MSG: [DM_AUDITTRAIL_E_CANT_MODIFY]error:  "You can not modify any existing AuditTrail object 5f0xxxxxxxxxxxxxbf."; ERRORCODE: 100; NEXT: null
		try{
			IDfAuditTrail auditTrailObj = (IDfAuditTrail) idfSession.getObject(auditTrailId);
			auditTrailObj.setString("event_description", "event_description for the "+objectId+" object" );
			auditTrailObj.save();
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}

 
TEST 2 :
Howvever, it is possible to modify any existing AuditTrail object via SQL:

			// MAIN 2 : Modification of audit trail
			{
				String auditTrailId = "5f0xxxxxx7";
				StringBuilder sql = new StringBuilder();
				sql.append("UPDATE ").append(object.idfSession.getDocbaseOwnerName()).append(".dm_audittrail_s");
				sql.append(" SET ");
				sql.append(" event_description = '").append("event_description for the "+auditTrailId+" object").append("' ");
				sql.append(" WHERE R_OBJECT_ID = '").append(auditTrailId).append("'");
				IDfApplyExecSQL dfApplyExecSQL = (IDfApplyExecSQL) DfAdminCommand.getCommand(DfAdminCommand.APPLY_EXEC_SQL);
				dfApplyExecSQL.setQuery(sql.toString());
				IDfCollection coll = dfApplyExecSQL.execute(object.idfSession);
				try {
					if (coll.next()) {
						IDfValue dfValue = coll.getValueAt(0);
						if (!dfValue.asBoolean()) {
							throw new RuntimeException("Error in modification of existing AuditTrail object via SQL :" + sql);
						}
					} else {
						throw new RuntimeException("Error in modification of existing AuditTrail object via SQL :" + sql);
					}
				} finally {
					if(coll!=null){
						coll.close();
					}
				}
			}

 
Example of deleting of existing AuditTrail object via pure API:

API> retrieve,c,dm_audittrail where r_object_id ='5f0xxxxxx7'
...
5f0xxxxxx7
API> destroy,c,l
...
OK

 
Example of creation of AuditTrail object via pure API:

create,c,dm_audittrail
set,c,l,event_name
my_event_huo_name
set,c,l,event_source
My process
set,c,l,user_name
My process
set,c,l,audited_obj_id
09xxxxxx62
set,c,l,string_1
Value Str 1
set,c,l,string_2
Value Str 2
set,c,l,string_3
Value Str 3
set,c,l,id_1
09xxxxx621
set,c,l,id_2
09xxxxxx622
set,c,l,sid_3
09xxxxxx623
save,c,l

The informations user_id, session_id, owner_name, time_stamp, time_stamp_utc, host_name are filled automatically by Content Server. Yet, the informations acl_name, acl_domain, chronicle_id, object_type, version_label, object_name are extracted from the audited object (audited_obj_id).
 
 
Resources : https://www.bluefishgroup.com/insights/articles/the-content-server-audit-facility/
Best regards,

Huseyin