Winter’16 was a bit low on API for me, but one thing i just found hiding in the New Objects section, was this…
SetupAuditTrail, “Represents changes you or other administrators made in your organization’s Setup area.”
Wow, this is a BIG thing and opens up a lot of tooling and greater compliance support for changes around orgs. Prior to this, folks where so keen to get hold of this information programatically they would resort to web scraping it from the Salesforce Setup menu! So I set about giving it a spin via Developer Workbench and learning more about the object.
There is also much better data export support via tools such as DataLoader.io (and of course other tools)….
So in addition to Salesforce API’s (used by the above tools), it is also available via Apex SOQL! The following selects all audit records relating to users from a certain email domain.
List<SetupAuditTrail> stuffDoneByConsultants = [SELECT Id, Action, CreatedBy.Name, CreatedDate, Display, Section FROM SetupAuditTrail WHERE CreatedBy.Email LIKE '%xyzconsulting.com%'];
So what else can we do with it? Well… not a lot more sadly, doing an Apex Describe shows that its basically only query-able, no triggers, replication API or indeed streaming API, which while not a total surprised would have been very cool!
Age of Records?
Through the long standing CSV download facility under setup, only 6 months worth of data is available. However running queries in my various long standing orgs i’m seeing data going back as far as all time?!? Although there is no documentation to confirm, and i would honestly would not be surprised to see some limit here, perhaps those of you running long standing production orgs can confirm via the comments below?
What are its fields?
As you can see the SetupAuditTrail objects fields are not the most ideal to interpret the data, aside from CreatedBy field (which supports relationship walking to the User object). The most interesting are Action, Section and Display, the later is the one that actually contains the object, field, layout or whatever has changed. The challenge here is its embedded in a message and not called out separately, so there is a bit of parsing to be done here.
IMPORTANT NOTE: The only gap i can see so far is the Delegate User (found in the Setup UI and CSV download) appears to be missing from the API at the moment. Yet it is documented as follows… ‘The Login-As user who executed the action in Setup. If a Login-As user didn’t perform the action, this field is blank.’
So what next?
- Well i see AuditForce is an example of application tool that was created to better report and dashboard on this information, this tool could be enhanced to use this API now and remove the current web scraping hack the developer (Daniel Peter) was forced to utilise back then.
- With Apex support its also possible to write Apex Scheduled jobs that periodically scan for certain updates and apply your own rules and notifications.
- I was thinking it might also be useful to have a nice Lighting Component perhaps?
- The Setup UI does not permit filtering or even sorting, it would probably not require to much coding to get something like the excellent Data Table component show results of queries from this object (as featured in my List View API blog).
- Finally given this is available from Salesforce REST API, its also feasible to aggregate into a single console audit information from say multiple sandboxes (something Daniel hints at in his AuditForce blog).
October 21, 2015 at 8:14 am
I am unable to download the declarative lookup rollup summary app. Kindly advise why this would be?
Thank you so much
October 21, 2015 at 8:18 am
Please click on the install link in the read me file for the tool. If you get an error please raise a GitHub issue or post in the Chatter group (link on the readme file) to get some more help. Thanks
October 28, 2015 at 6:33 am
Great post! Another use case is to add support for this (setup type) object too in Metadata Search AppExchange app, we are working on same to implement it asap.
October 28, 2015 at 9:03 pm
Great use case!
January 4, 2016 at 2:05 pm
One thing missing is to be not able to filter on Section and Display 😦
November 2, 2015 at 11:40 pm
We’re on a really old org (2007) and I was able to pull back 100k records in the SetupAuditTrail object going back to 2012-12-26. That roughly puts it at Winter13/v26.
November 3, 2015 at 12:12 am
Wow that’s a lot, thanks for sharing!
November 8, 2015 at 3:41 pm
Thanks for this post, these are indeed great news!
We, in SkyFormation, were also been using a scraper to extract this information for all our customers.
I want to mention that one important data dimension is still missing (both from the UI and from the SObject) – the target user identifier for all user’s related operations. At the moment the only identifying attribute given is the user’s display name which is not unique.
November 11, 2015 at 6:23 pm
Hi Andrew, I wrote the doc for this object and wanted to let you know that DelegateUser is only available in API v35.0 and later. That was my mistake, and I appreciate you pointing out the gap. I’ll fix it in the doc ASAP. Thanks for the great post!
November 12, 2015 at 7:58 am
Hi Justin, thanks for stopping by, honoured for you to read my blog! I will update accordingly. Thanks again!
December 1, 2015 at 3:03 pm
First off, great post on this new feature. I was playing around a bit with this and came across a limitation (or at least that’s my perception) and wanted to get your thoughts on it. I’m specifically focused on the “Logged in using Login-As access for User ABC” action – in this situation the admin user invoking this action is stored as the CreatedById; however I do not see where User ABC (the user the admin is logging in as) is stored, other than in the action text. But, when you look at this record in the Setup menu, User ABC is displayed in the User column. Thoughts?
Thanks in advance,
December 1, 2015 at 3:31 pm
Yes, the Delegate User field I noted in the blog. I received a tweet from the Salesforce Product Manager on this shortly after publishing. It seems this is available in the latest API version. “@andyinthecloud try Ver 35 to see DelegateUser in setup audit trial API. If you don’t see it, let me know.”. I have not had chance to check yet, if you do let me know. 🙂
December 1, 2015 at 3:45 pm
From the Setup menu the Delegate User field is the admin user performing the ‘log in as’ action, I want to know the user that is being logged in as – shown in the User field in Setup menu.
Also in my testing from both the Workbench & the Dev Console, even using API v35 I am seeing null values for the DelegateUser field – even though the value is populated when viewing the same record in the Setup menu.
December 1, 2015 at 3:48 pm
Ok let’s see if Adam can clarify, I will tweet him back.
December 18, 2015 at 6:34 pm
is there a way to know the predefined list of values in Type and Section field as if i want to write a batch to capture setup related changes?
December 18, 2015 at 6:47 pm
If it’s not in the Salesforce docs I linked to above, I would say not.
December 18, 2015 at 6:37 pm
hi Andy is there any way i can pull predefined list of values for the Action and Section fields?
December 18, 2015 at 6:47 pm
If it’s not in the links above to the Salesforce docs, I would say no.
January 13, 2016 at 11:42 am
can any one knows how to capture the audit details to custom object
January 13, 2016 at 12:20 pm
You could write a apex scheduled job to copy it over periodically. Keep in mind this could become a lot of data depending on activity of changes in your org of course
January 18, 2016 at 10:15 am
Update : Metadata Search AppExchange app now supports searching Setup Audit Trails. View/Install app from http://goo.gl/qOJCIM. Disclosure : Apologies for self promotion 🙂
March 24, 2016 at 8:37 pm
i wrote a batch class to replicate this data to a custom object where i can build some analytic on it. But when i am trying to write test class for that batch stuck because we cannot insert a test record into setupAuditTrail object. Any idea how to overcome this other than using SeeAllData?
March 25, 2016 at 11:42 am
You will likely have to just create the records in memory and use Test.isTesting to condition using the real query vs in memory. I know this will reduce coverage but it’s the best I can think. You could get more advanced and use something like ApexMocks but it amounts to the same
April 14, 2016 at 2:29 pm
I exported the data from the SetupAuditTrail object(using Data Loader) and our data goes back to 7/1/2012. I noticed two things missing initially: I didn’t the DelegateUser field, which was solved(as mentioned in a previous comment) when I upgraded my Data Loader to a current version(36.0). I see that field as their logon/email, and I was expecting a UserID, but that’s fine. The second thing that I do not see, is in the ‘Login-As’ situations, the exported data does not show the ‘Logged in’ action. It only shows the ‘Logged out’ action. In the UI, you will see both the ‘Logged in’ and the ‘Logged out’ as two separate line items. In other words, in the API data, you cannot see when the logged in action took place, you only know when they logged out.
April 14, 2016 at 9:18 pm
Great insight Eric, thanks for sharing!
May 4, 2017 at 9:34 am
Are there any news regarding the missing ‘Logged in’?
May 6, 2017 at 2:07 am
Its seems not, https://developer.salesforce.com/docs/atlas.en-us.208.0.api.meta/api/sforce_api_objects_setupaudittrail.htm
May 6, 2017 at 7:36 am
Is there a way that you familiar with beside the forum (which they ignore) to contact them?
August 3, 2018 at 7:19 am
Is there any way to write a trigger on SetupAuditTrail Object?
August 8, 2018 at 5:06 pm
No sorry not as far as I know, it’s a setup object