03-27-2018 08:52 AM
Hello
I am trying to get audit data for READ events on nodes of type cm:content.
I'm using an alfresco-all-in-one project (artifactId is alfresco-all-in-one) created with the maven alfresco sdk so I added two files in "alfresco-all-in-one/alfresco-all-in-one-platform-jar/src/main/resources/alfresco/module/alfresco-all-in-one-platform-jar/" namely:
alfresco-global.properties
audit.enabled=true
audit.alfresco-access.enabled=true
audit.filter.alfresco-access.transaction.action=READ
audit.filter.alfresco-access.transaction.type=cm:content
log4j.properties
log4j.logger.org.alfresco.repo.audit.AuditComponentImpl=DEBUG
log4j.logger.org.alfresco.repo.audit.inbound=DEBUG
log4j.logger.org.alfresco.repo.audit.access=DEBUG
Then i tried to redo the steps from this Example Audit Trail. Not only did I not see the READ events on cm:content I was looking for (from step 3), it seems the audit.filter properties I defined didn't have any effect...I got CREATE events, READ events for other types like cmerson. I went over the logs a bunch of times so I know I didn't miss anything. I even tried using the audit query API http://localhost:8080/alfresco/s/api/audit/query/alfresco-access?verbose=true but the results were the same.
Now I know from Axel Faust's reply to this question that filters should act on inbound audit values generated by the two producers: "alfresco-access" and "alfresco-api" so data shouldn't even appear in the "alfresco-access" audit application. I even tried with
audit.alfresco-access.enabled=false
but I still got unwanted data from the alfresco-access producer as inbound audit values in the logs.
So my two questions so far are:
- how to make audit filters work?
- how to make alfresco-access producer generate READ audit data for cm:content types?
Thank you!
P.S.: I know the data I am looking for should be accessible because when I go to an alfresco site I created there is that "Site activites" dashlet that clearly shows:
04-02-2018 05:39 AM
For anyone still interested in a solution for this specific issue:
I ended up not using the audit feature at all. What I did instead was use a java repo side web-script to access the database directly. The information I was looking for was stored in the "alf_activity_feed" table. The database name is "alfrescoaio" in my case because I am using the alfresco maven sdk to create an all-in-one project for development. The results are filtered so only one entry per user exists (the most recent one).
private Map<String, Map> getPreviews(String currentNode) {
Map<String, Map> finalPreviewsMap = new HashMap<>();
try {
// Connect to db
String dbUrl = "jdbc:postgresql:alfrescoaio";
Connection db = DriverManager.getConnection(dbUrl, "alfresco", "alfresco");
PreparedStatement st = db.prepareStatement("SELECT DISTINCT post_date,activity_summary FROM alf_activity_feed WHERE activity_type='org.alfresco.documentlibrary.file-previewed'");
ResultSet rs = st.executeQuery();
// Init variables
Date post_date;
String activity_summary;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> summary, previewMap;
// Iterate through results from db
while (rs.next()) {
activity_summary = rs.getString(2);
if (activity_summary.indexOf(currentNode) != -1) {
summary = mapper.readValue(activity_summary, Map.class);
previewMap = new HashMap<>();
String fullName = summary.get("firstName") + " " + summary.get("lastName");
String fullNameId = fullName.replace(" ","").replace("-","");
post_date = df.parse(rs.getString(1));
if (finalPreviewsMap.get(fullNameId) != null) {
long oldPostDate = (long) finalPreviewsMap.get(fullNameId).get("post_date");
if (post_date.getTime() > oldPostDate) {
previewMap.put("post_date", post_date.getTime());
previewMap.put("fullName", fullName);
finalPreviewsMap.put(fullNameId, previewMap);
}
} else {
previewMap.put("post_date", post_date.getTime());
previewMap.put("fullName", fullName);
finalPreviewsMap.put(fullNameId, previewMap);
}
}
}
// Close db connection
rs.close();
st.close();
db.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return finalPreviewsMap;
}
03-27-2018 05:01 PM
Do not confuse site activities with auditing - these are two completely different functionalities and not at all related to one another.
Also, be aware that there is both a data producer called "alfresco-access" and an audit application ("recorder") called "alfresco-access" (thanks Alfresco for a properly confusing naming without a clear separation). When you configure audit.alfresco-access.enabled, you are only enabling / disabling the audit application, not the data producer. So even if alfresco-access is not enabled as a recorder you'll still get the inbound data from the producer (which may be consumed by other audit applications).
Only the audit.filter.xx settings apply the producer as I stated in the linked thread.
To me it sounds like your alfresco-global.properties may not be picked up properly / correctly. Have you tried configuring this in a regular Alfresco system outside of the SDK (I only trust the SDK as far as I can throw it, and never use it myself)?
03-28-2018 02:49 AM
Thank you for your response, Axel.
I am aware of the difference between the "alfresco-access" data producer and the "alfresco-access" audit application.
I tried using a regular Alfresco system today. I put the changes in {alfresco_root_dir}/tomcat/shared/classes/alfresco-global.properties. Unfortunately the audit.filter.xx settings were ignored just like with the SDK. I was thinking the default alfresco-acccess filters were interfering so I also put
audit.filter.alfresco-access.default.enabled=false
Still no effect. I'm out of ideas.
I could probably do with no filtering for now if only I could solve the other problem, namely making the alfresco-access producer generate READ audit data for cm:content types. Any ideas on that issue?
You were saying site activities are different from auditing...is there a way to get the data from there?
Thank you for your time!
// Edit
I finally managed to get filters working. I had to enable the default alfresco-access filters in the first place:
audit.filter.alfresco-access.default.enabled=true
I don't know if this behavior is intended or if it's a bug... Anyway, then I could overwrite the defaults to anything I wanted. I needed to see all inbound audit values so I put these settings:
audit.filter.alfresco-access.transaction.user=.*
audit.filter.alfresco-access.transaction.path=.*
audit.filter.alfresco-access.transaction.type=.*
However, even with allowing all kinds of audit data, I still couldn't get the READ audit values for documents in the document library. I also looked through the audit values produced by "alfresco-api" and tried to find inbound audit values that were only generated when I opened the document. I got pretty close with /alfresco-api/post/NodeService/getPath/args/nodeRef=... but these events are also triggered in other situations (for example when the site activities dashlet loads and the file is present there).
Any ideas for how I could proceed?
Thanks again!
04-02-2018 05:39 AM
For anyone still interested in a solution for this specific issue:
I ended up not using the audit feature at all. What I did instead was use a java repo side web-script to access the database directly. The information I was looking for was stored in the "alf_activity_feed" table. The database name is "alfrescoaio" in my case because I am using the alfresco maven sdk to create an all-in-one project for development. The results are filtered so only one entry per user exists (the most recent one).
private Map<String, Map> getPreviews(String currentNode) {
Map<String, Map> finalPreviewsMap = new HashMap<>();
try {
// Connect to db
String dbUrl = "jdbc:postgresql:alfrescoaio";
Connection db = DriverManager.getConnection(dbUrl, "alfresco", "alfresco");
PreparedStatement st = db.prepareStatement("SELECT DISTINCT post_date,activity_summary FROM alf_activity_feed WHERE activity_type='org.alfresco.documentlibrary.file-previewed'");
ResultSet rs = st.executeQuery();
// Init variables
Date post_date;
String activity_summary;
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.ENGLISH);
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> summary, previewMap;
// Iterate through results from db
while (rs.next()) {
activity_summary = rs.getString(2);
if (activity_summary.indexOf(currentNode) != -1) {
summary = mapper.readValue(activity_summary, Map.class);
previewMap = new HashMap<>();
String fullName = summary.get("firstName") + " " + summary.get("lastName");
String fullNameId = fullName.replace(" ","").replace("-","");
post_date = df.parse(rs.getString(1));
if (finalPreviewsMap.get(fullNameId) != null) {
long oldPostDate = (long) finalPreviewsMap.get(fullNameId).get("post_date");
if (post_date.getTime() > oldPostDate) {
previewMap.put("post_date", post_date.getTime());
previewMap.put("fullName", fullName);
finalPreviewsMap.put(fullNameId, previewMap);
}
} else {
previewMap.put("post_date", post_date.getTime());
previewMap.put("fullName", fullName);
finalPreviewsMap.put(fullNameId, previewMap);
}
}
}
// Close db connection
rs.close();
st.close();
db.close();
} catch (SQLException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (JsonParseException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return finalPreviewsMap;
}
Explore our Alfresco products with the links below. Use labels to filter content by product module.