Skip to main content

Notifications

Announcements

No record found.

Customer experience | Sales, Customer Insights,...
Suggested answer

Why would RetrieveAttributeChangeHistoryRequest() only returns AuditDetail and no AttributeAuditDetail objects?

Posted on by 35

I'm using the standard Microsoft provided code to parse through audit records to determine if I can purge anything that we don't need to keep. My audit file has billions of records and CRM seems to be having some trouble with the size of the table. However, we are required by law to keep about 10-years worth of audits. So, I am working on some logic to purge the unneeded audit records to reduce the Audit table size as much as I can. I think I can find a few logical rules to apply such as, if the old and new values are both the same, then we'll purge those. I'm trying to come up with a few dozen rules like this to figure out what I can purge.  I'm hoping to find addition logic to identify more to purge. I'm open to suggestions as to what to purge or how to maybe remove some of those from being audited in the first place. For the most part, we turn on field level auditing for fields that we are required by law to audit. 

The audits with the same old/new values come from code in CRM plugins, integration services, etc. that pull in a field and then do not change the value, but the field is still there and it gets saved. CRM treats these as updates since it was saved even if the value does not change. I guess it makes sense, since the field was in fact saved. I guess it is just a how you take the save/update meaning. Apparently CRM treats anything that is saved, even NULL and empty values that do not change, as updates. It does make it easy when testing update plugins, just run a SQL update to set a field to it's current value and the update plugins fires. But it's annoying because we end up a billion audit records... literally.

I originally looked at cleaning up all of that code so that we only save what has changed and removing the field from the entity before we update, but that ended up being problematic and we can't entirely remove it in all cases and even when we do, we are still finding that CRM is still creating audits when you wouldn't think it would. So, I will continue working down that path over time, but with 1 billion audit records, I want  to try to clean it up as best I can. I will also look at archiving some fo the older data as well. But for this first pass I'm just cleaning up what I can. For other tables/entities like say the PluginTraceLogs, I am just clearing those out, anything over say 30-days old. But with 1 billion valid audit table records, I want to focus on cleaning up those. 

To do this, I am using some standard sample code from Microsoft as follows. But no matter what I do, I can't get it to return an AttributeAuditDetail and it only ever returns AuditDetail. Even when I use the RetrieveAtrributeChangeHistoryRequest() vs the RetrieveAuditChangeHistoryRequest(). It always just returns AuditDetail objects and nothing else. However, every example I see online does in fact return the attribute details as you would expect. I can use those examples for other entities and get the attribute details. But for my entity that I am searching for, which is custom, it only returns AuditDetails.

Does anyone have any idea what would cause this? Is there a config setting on the entity that needs to be set? Auditing on this entity works fine and we audit dozens of fields. So the attribute details should be there. Could it be permissions? 

Why would a custom entity not have AttributeAuditDetails but some of the build-in ones have those? Any idea what controls this?

Here's the core of the code I am using, which comes from Microsoft samples.

Any suggestions, thoughts, links, or ideas are much appreicated.   

Best regards,

Jon Rothlander

public List GetAuditHistory(IOrganizationService svc, string entityLogicalName, Guid entityId, string attributeName)
{
    var auditHistoryForRecord = new List();

    var attributeChangeHistoryRequest = new RetrieveAttributeChangeHistoryRequest
    {
        Target = new EntityReference(entityLogicalName, entityId),
        AttributeLogicalName = attributeName,
    };
    var attributeChangeHistoryResponse = (RetrieveAttributeChangeHistoryResponse)svc.Execute(attributeChangeHistoryRequest);

    foreach (var eachEditRecord in attributeChangeHistoryResponse.AuditDetailCollection.AuditDetails)
    {
        var detailType = eachEditRecord.GetType();
        if (detailType == typeof(AttributeAuditDetail))
        {
            // Never gets here. There are only AuditDetail types, not attribute types ever.
            // The problem there, is that only with attribute types can I determine old/new value.
        }
    }

  • jrothlander Profile Picture
    jrothlander 35 on at
    RE: Why would RetrieveAttributeChangeHistoryRequest() only returns AuditDetail and no AttributeAuditDetail objects?

    Yeah, we are auditing dozens of fields on the entity. When I go into Auditing, it is working as except and there's dozens of records for each record for that entity. So, that does seem to be working as expected.

    Nothing stands out to me as to why it would not return AttributeAuditDetails but does return AuditDetails. I'm going to try to focus in on the permissions today to make sure I am not overlooking something in that regards.

  • Suggested answer
    Bipin D365 Profile Picture
    Bipin D365 28,964 Super User 2024 Season 1 on at
    RE: Why would RetrieveAttributeChangeHistoryRequest() only returns AuditDetail and no AttributeAuditDetail objects?

    Hi,

    Audit history is turned on for you custom entity?

    May be I am asking dumb question as it should be turned on.

  • jrothlander Profile Picture
    jrothlander 35 on at
    RE: Why would RetrieveAttributeChangeHistoryRequest() only returns AuditDetail and no AttributeAuditDetail objects?

    "If problem with permission then Update role which user currently have under which your code is running to give View Audit History and Delete Audit History permission"

    Are you saying that by default, the user access only gives ViewAuditHistory and DeleteAuditHistory? Will that not give me access to the AttributeAuditDetails? If so, then that is the problem.

    Thanks for the comments and link. That code is just a copy of the Microsoft sample from the Microsoft documentation with a couple of minor tweaks. The code is a really good example of how to do what I am doing. But the problem I am having is that for my custom entities, the following code from that article is 100% of the time returning FALSE... [if (detailType == typeof(AttributeAuditDetail))].

    However, if I use some of the built-in entities, it does find a few with AttributeAuditDetail. What I can't figure out is what controls creating the AtributeAuditDetail vs the AuditDetail. Something is contolling this, which could be permissions. But I am a full admin on CRM and for this test app (built a little console app to test this and I will convert it to a Windows service in the end), I am hardcoding my userid and password in the connection string. So, it seems like I should have the necessary permisions. But maybe that is not working as expected. It seems to work the same if I include or exclude my userid/password. So that might be the issue.

    Maybe there is something that admin doesn't get by default that I need to add? What I find odd is that I can get AttributeAuditDetails from some of the built-in entities. So that seems to suggest something is setup or config in such a way as to not allow access to the AttributeAuditDetails at the entity level. But I don't really know. Just trying to think it through. Maybe I am wrong about that. I need to step back through and verify this again to make sure.

    But thanks for your comments and suggestions. I think you are on the right track, that it probably has something to do with my account, the connection string, or something related there.

  • Suggested answer
    Bipin D365 Profile Picture
    Bipin D365 28,964 Super User 2024 Season 1 on at
    RE: Why would RetrieveAttributeChangeHistoryRequest() only returns AuditDetail and no AttributeAuditDetail objects?

    Hi,

    I tried code from below article which you are referring if I am not wrong and it works with System Admin role user

    www.ashishvishwakarma.com/.../

    Can you also try to run your code under System Admin User to see if it works,

    If problem with permission then Update role which user currently have under which your code is running to give View Audit History and Delete Audit History permission

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

December Spotlight Star - Muhammad Affan

Congratulations to a top community star!

Top 10 leaders for November!

Congratulations to our November super stars!

Tips for Writing Effective Suggested Answers

Best practices for providing successful forum answers ✍️

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 291,280 Super User 2024 Season 2

#2
Martin Dráb Profile Picture

Martin Dráb 230,235 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Featured topics

Product updates

Dynamics 365 release plans