This is available in Grouper API 2.3.0 patch 97+.
Delete audit entries with no logged in user
Configured in grouper-loader properties
############################################ ## audit entries with no logged in user aren't really all that useful. There is point in time data still. So removing these shouldn't be a big deal ## default is remove these that are 5 years old. ############################################ # number of days to retain db rows in grouper_audit_entry with no logged in user (loader, gsh, etc). -1 is forever. suggested is 365 or five years: 1825. Default is -1 loader.retain.db.audit_entry_no_logged_in_user.days=-1
Call from GSH
edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldAuditEntryNoLoggedInUser(1825); // delete records older than the configured amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldAuditEntryNoLoggedInUser(); // delete records older than the specified amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldAuditEntryNoLoggedInUser(int);
Example logs in grouper daemon log
2018-02-19 14:54:17,684: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditNotLoggedInDays: -1, threadId: 1, elapsed: 0 ms 2018-02-19 14:54:17,694: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditNotLoggedInDays: 9, deleteOldAuditNotLoggedInCount: 0, threadId: 1, elapsed: 2 ms 2018-02-19 14:54:17,715: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditNotLoggedInDays: 7, deleteOldAuditNotLoggedInCount: 1, threadId: 1, elapsed: 15 ms 2018-02-19 14:54:17,736: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditNotLoggedInDays: 5, deleteOldAuditNotLoggedInCount: 1, threadId: 1, elapsed: 14 ms
Delete audit entries
Configured in grouper-loader properties
############################################ ## Some think its ok to remove all audit entries over 10 (or X) years, but will default this ## to never since even at large institutions there aren't that many records. ## These are audits for things people do on the UI or WS generally (as a different to records with no logged in user) ############################################ # number of days to retain db rows in grouper_audit_entry. -1 is forever. suggested is -1 or ten years: 3650 loader.retain.db.audit_entry.days=-1
Call from GSH
edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldAuditEntry(3650); // delete records older than the configured amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldAuditEntry(); // delete records older than the specified amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldAuditEntry(int);
Example logs in grouper daemon log
2018-02-19 14:54:25,125: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditDays: -1, threadId: 1, elapsed: 0 ms 2018-02-19 14:54:25,132: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditDays: 9, deleteOldAuditCount: 0, threadId: 1, elapsed: 2 ms 2018-02-19 14:54:25,143: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditDays: 7, deleteOldAuditCount: 2, threadId: 1, elapsed: 5 ms 2018-02-19 14:54:25,154: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteOldAuditDays: 5, deleteOldAuditCount: 2, threadId: 1, elapsed: 5 ms
Delete old deleted point in time data
Configured in grouper-loader.properties
############################################ ## After you delete an object in grouper, it is still in point in time. So if you want to know who ## was in a group a year ago, you need this info ## However, after some time it might be ok to let it go. So the default is 5 years ############################################ # number of days to retain db rows for point in time deleted objects. -1 is forever. suggested is 365 or five years: 1825. Default is -1 loader.retain.db.point_in_time_deleted_objects.days=-1
Call from GSH
edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldDeletedPointInTimeObjects(1825); // delete records older than the configured amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldDeletedPointInTimeObjects(); // delete records older than the specified amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.deleteOldDeletedPointInTimeObjects(int);
Example logs in grouper daemon log
2018-02-19 14:54:39,461: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteDeletedPointInTimeObjectsDays: -1, threadId: 1, elapsed: 0 ms 2018-02-19 14:54:39,491: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteDeletedPointInTimeObjectsDays: 9, deleteDeletedPointInTimeObjectsCount: 0, threadId: 1, elapsed: 25 ms 2018-02-19 14:54:39,520: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteDeletedPointInTimeObjectsDays: 7, deleteDeletedPointInTimeObjectsCount: 3, threadId: 1, elapsed: 24 ms 2018-02-19 14:54:39,601: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, deleteDeletedPointInTimeObjectsDays: 5, deleteDeletedPointInTimeObjectsCount: 3, threadId: 1, elapsed: 76 ms
Delete old folders
Configured in grouper-loader.properties
############################################ ## This is optional. You can just automatically obliterate folders *directly in a parent folder* that are a certain age old e.g. courses. ## so you could delete a term of courses 4 years old if you like. Note, make sure the loader isn't going to recreate or you will get churn ## Note this will also delete the point in time data as well. ############################################ # number of days after a subfolder (directly in a parent folder) is created that it will be obliterated (deleted) # and point in time will be deleted too. # "courses" or "anotherLabel" are variables you make up in these examples #loader.retain.db.folder.courses.days=1825 #loader.retain.db.folder.courses.parentFolderName=my:folder:for:courses #loader.retain.db.folder.courses.deletePointInTime=true #loader.retain.db.folder.anotherLabel.days=1825 #loader.retain.db.folder.anotherLabel.parentFolderName=my:folder:for:something #loader.retain.db.folder.anotherLabel.deletePointInTime=false
Call from GSH
edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.obliterateOldStemsDirectlyInStem(Set<DeleteOldStem>); // delete records older than the configured amount of days edu.internet2.middleware.grouper.app.loader.GrouperDaemonDeleteOldRecords.obliterateOldStemsDirectlyInStem();
Example logs in grouper daemon log
2018-02-19 14:51:57,161: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, obliterateOldStemsCount: 0, threadId: 1, elapsed: 0 ms 2018-02-19 14:51:57,168: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, obliterateOldStemsCount: 1, obliterateOldStems.0.stem: test, obliterateOldStems.0.days: 9, obliterateOldStems.0.deletePointInTime: true, obliterateOldStems.0.stem.subFolderCount: 2, obliterateOldStems.0.stem.test1.notOldEnoughToDelete: true, obliterateOldStems.0.stem.test2.notOldEnoughToDelete: true, threadId: 1, elapsed: 6 ms 2018-02-19 14:53:06,383: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, obliterateOldStemsCount: 1, obliterateOldStems.0.stem: test, obliterateOldStems.0.days: 7, obliterateOldStems.0.deletePointInTime: true, obliterateOldStems.0.stem.subFolderCount: 2, obliterateOldStems.0.stem.test1.notOldEnoughToDelete: true, obliterateOldStems.0.stem.test2.deleting: true, obliterateOldStems.0.stem.test2.folderCreatedOn: 2018-02-11 14:51:57.096, threadId: 1, elapsed: 60744 ms 2018-02-19 14:54:06,941: [main] DEBUG GrouperLoaderLog.logDebug(33) - - logType: maintenanceDeleteOldRecords, overallId: null, obliterateOldStemsCount: 1, obliterateOldStems.0.stem: test, obliterateOldStems.0.days: 5, obliterateOldStems.0.deletePointInTime: true, obliterateOldStems.0.stem.subFolderCount: 1, obliterateOldStems.0.stem.test1.deleting: true, obliterateOldStems.0.stem.test1.folderCreatedOn: 2018-02-13 14:51:57.096, threadId: 1, elapsed: 60538 ms
Experience at Grouper Demo
Pre-patch
-- Audit entries: 137210 select count(1) from grouper_audit_entry_v; -- Audit entries no logged in user: 128204 select count(1) from grouper_audit_entry_v where logged_in_subject_id is null; -- Audit entries no logged in user older than a month old: 82201 select count(1) from grouper_audit_entry_v where logged_in_subject_id is null and created_on < 1516338000000; -- PIT entries: 148907 SELECT (SELECT COUNT(1) FROM grouper_pit_attribute_assign) + (SELECT COUNT(1) FROM grouper_pit_attribute_def) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn_set) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_value) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name_set) + (SELECT COUNT(1) FROM grouper_pit_fields) + (SELECT COUNT(1) FROM grouper_pit_groups) + (SELECT COUNT(1) FROM grouper_pit_group_set) + (SELECT COUNT(1) FROM grouper_pit_members) + (SELECT COUNT(1) FROM grouper_pit_memberships) + (SELECT COUNT(1) FROM grouper_pit_role_set) + (SELECT COUNT(1) FROM grouper_pit_stems) AS pit_count FROM DUAL; -- PIT entries of deleted objects: 126095 SELECT (SELECT COUNT(1) FROM grouper_pit_attribute_assign WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attribute_def WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_value WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_fields WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_groups WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_group_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_members WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_memberships WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_role_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_stems WHERE end_time IS NOT NULL) AS pit_count FROM DUAL; -- PIT entries of deleted objects older than a month: 80342 SELECT (SELECT COUNT(1) FROM grouper_pit_attribute_assign WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_attribute_def WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn_set WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_value WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name_set WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_fields WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_groups WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_group_set WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_members WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_memberships WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_role_set WHERE end_time IS NOT NULL and end_time < 1516338000000000) + (SELECT COUNT(1) FROM grouper_pit_stems WHERE end_time IS NOT NULL and end_time < 1516338000000000) AS pit_count FROM DUAL; -- Folders in delete folder 'users:penn' newer than 5 years: 5 SELECT COUNT(1) FROM grouper_stems WHERE NAME LIKE 'users:penn:%' AND create_time > 1361250000000; -- Folders in delete folder 'users:penn' older than 5 years: 39 SELECT COUNT(1) FROM grouper_stems WHERE NAME LIKE 'users:penn:%' AND create_time < 1361250000000;
Post-patch: (dont configure anything)
Run the clean logs job
gsh 0% grouperSession = GrouperSession.startRootSession(); edu.internet2.middleware.grouper.GrouperSession: 7f8474d2914a4cecac143be77768a34b,'GrouperSystem','application' gsh 1% loaderRunOneJob("MAINTENANCE_cleanLogs"); loader ran successfully: Deleted 3872 records from grouper_loader_log older than 7 days old. Deleted 2038 records from grouper_change_log_entry older than 14 days old. (1517867128940000) Deleted 0 instrumentation records older than 30 days old. (1516484734612) Configured to not delete records from audit_entry table with null logged in member idConfigured to not delete records from audit_entry tableConfigured to not delete records from DeletedPointInTimeObjects
Do counts
Audit entries: 137214 Audit entries no logged in user: 128207 Audit entries no logged in user older than a month old: 82201 PIT entries: 148913 PIT entries of deleted objects: 126096 PIT entries of deleted objects older than a month: 80342 Folders in delete folder 'users:penn' newer than 5 years: 5 Folders in delete folder 'users:penn' older than 5 years: 39
Configure deletes in grouper-loader.properties
############################################ ## audit entries with no logged in user aren't really all that useful. There is point in time data still. ## So removing these shouldn't be a big deal ## default is remove these that are 5 years old. ############################################ # number of days to retain db rows in grouper_audit_entry with no logged in user (loader, gsh, etc). -1 is forever. # suggested is 365 or five years: 1825. Default is -1 loader.retain.db.audit_entry_no_logged_in_user.days=31 ############################################ ## Some think its ok to remove all audit entries over 10 (or X) years, but will default this ## to never since even at large institutions there aren't that many records. ## These are audits for things people do on the UI or WS generally (as a different to records with no logged in user) ############################################ # number of days to retain db rows in grouper_audit_entry. -1 is forever. suggested is -1 or ten years: 3650 loader.retain.db.audit_entry.days=365 ############################################ ## After you delete an object in grouper, it is still in point in time. So if you want to know who ## was in a group a year ago, you need this info ## However, after some time it might be ok to let it go. So the default is 5 years ############################################ # number of days to retain db rows for point in time deleted objects. -1 is forever. suggested is 365 or five years: 1825. # Default is -1 loader.retain.db.point_in_time_deleted_objects.days=31 ############################################ ## This is optional. You can just automatically obliterate folders *directly in a parent folder* ## that are a certain age old e.g. courses. ## so you could delete a term of courses 4 years old if you like. Note, make sure the loader isn't going to recreate ## or you will get churn ## Note this will also delete the point in time data as well. ############################################ # number of days after a subfolder (directly in a parent folder) is created that it will be obliterated (deleted) # and point in time will be deleted too. # "courses" or "anotherLabel" are variables you make up in these examples loader.retain.db.folder.test.days=1825 loader.retain.db.folder.test.parentFolderName=users:penn loader.retain.db.folder.test.deletePointInTime=true
Run the daemon with GSH
[appadmin@i2midev6 tomcats]$ cd tomcat_f_gsh/webapps/grouper_v2_3/WEB-INF/bin/ gsh 0% grouperSession = GrouperSession.startRootSession(); edu.internet2.middleware.grouper.GrouperSession: 7f8474d2914a4cecac143be77768a34b,'GrouperSystem','application' gsh 1% loaderRunOneJob("MAINTENANCE_cleanLogs"); loader ran successfully: Deleted 3872 records from grouper_loader_log older than 7 days old. Deleted 2038 records from grouper_change_log_entry older than 14 days old. (1517867128940000) Deleted 0 instrumentation records older than 30 days old. (1516484734612) Configured to not delete records from audit_entry table with null logged in member idConfigured to not delete records from audit_entry tableConfigured to not delete records from DeletedPointInTimeObjects
Counts afterwards
-- Audit entries: 3727 -- Audit entries no logged in user: 275 -- Audit entries no logged in user older than a month old: 0 -- PIT entries: 19859 -- PIT entries of deleted objects: 46 -- PIT entries of deleted objects older than a month: 0 -- Folders in delete folder 'users:penn' newer than 5 years: 5 -- Folders in delete folder 'users:penn' older than 5 years: 5
Experience at Penn test env
Pre-patch counts
-- Audit entries: 12538020 SELECT COUNT(1) FROM grouper_audit_entry_v; -- Audit entries no logged in user: 12234228 SELECT COUNT(1) FROM grouper_audit_entry_v WHERE logged_in_subject_id IS NULL; -- Audit entries no logged in user older than 1 year old: 8804148 SELECT COUNT(1) FROM grouper_audit_entry_v WHERE logged_in_subject_id IS NULL AND created_on < 1490839886000; -- PIT entries: 16644841 SELECT (SELECT COUNT(1) FROM grouper_pit_attribute_assign) + (SELECT COUNT(1) FROM grouper_pit_attribute_def) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn_set) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_value) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name_set) + (SELECT COUNT(1) FROM grouper_pit_fields) + (SELECT COUNT(1) FROM grouper_pit_groups) + (SELECT COUNT(1) FROM grouper_pit_group_set) + (SELECT COUNT(1) FROM grouper_pit_members) + (SELECT COUNT(1) FROM grouper_pit_memberships) + (SELECT COUNT(1) FROM grouper_pit_role_set) + (SELECT COUNT(1) FROM grouper_pit_stems) AS pit_count FROM DUAL; -- PIT entries of deleted objects: 6954271 SELECT (SELECT COUNT(1) FROM grouper_pit_attribute_assign WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attribute_def WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_value WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_fields WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_groups WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_group_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_members WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_memberships WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_role_set WHERE end_time IS NOT NULL) + (SELECT COUNT(1) FROM grouper_pit_stems WHERE end_time IS NOT NULL) AS pit_count FROM DUAL; -- PIT entries of deleted objects older than 3 years: 0 SELECT (SELECT COUNT(1) FROM grouper_pit_attribute_assign WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_attribute_def WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_actn_set WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_attr_assn_value WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_attr_def_name_set WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_fields WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_groups WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_group_set WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_members WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_memberships WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_role_set WHERE end_time IS NOT NULL AND end_time < 1490839886000000) + (SELECT COUNT(1) FROM grouper_pit_stems WHERE end_time IS NOT NULL AND end_time < 1490839886000000) AS pit_count FROM DUAL; -- Folders in delete folder 'users:penn' newer than 5 years: 13097 SELECT COUNT(1) FROM grouper_stems WHERE NAME LIKE 'penn:community:student:course:%' AND create_time > 1364609486000; -- Folders in delete folder 'users:penn' older than 5 years: 3095 SELECT COUNT(1) FROM grouper_stems WHERE NAME LIKE 'penn:community:student:course:%' AND create_time < 1364609486000;