1

I know the approach for deleting ApexLogs to get back under capacity and avoid the error when you are over capacity on tracking Debug Logs (as listed here for example) - however I'm wondering is there a way to query for when your user hits that limit? I didn't see anything in the Limits class.

In an ideal world it would be great to trigger a process which deletes the ApexLog records automatically. This would help some of our less technically savvy debug log testers/users. This may not be possible or I probably would have found steps on how to complete from one of you smarter developers already ha :)

3
  • 3
    You can't delete the logs from Apex itself afaik, which is really annoying anyway. I Just end up querying in the devconsole, sorted by length so I can get the big ones out of the way and carry on working.
    – Matt Lacey
    Commented Sep 29, 2022 at 16:04
  • 1
    Hey @MattLacey - I saw your blog post on that idea - great shout - thanks. I had built out a handy flow which works for querying and deleting ApexLogs which are over 3 days old but a 3 day window isn't very useful when you're really in the trenches. I would love if it could be a bit smarter/more dynamic about things.
    – cloudcap
    Commented Sep 29, 2022 at 16:21
  • Flows can delete them? That's good to know! Might be worth a new post
    – Matt Lacey
    Commented Sep 30, 2022 at 8:38

1 Answer 1

4

Make a scheduled job out of it!

public class TruncateLog implements Database.AllowsCallouts, Schedulable, Queueable {
    Integer currentUsage;
    public void execute(SchedulableContext context) {
        AggregateResult[] results = [SELECT SUM(LogLength) sum FROM ApexLog];
        // Adjust to your liking. I set to 750,000,000/1,000,000,000 allowed.
        if(results.isEmpty() || ((Integer)results[0].get('sum')<750000000)) {
            return;
        }
        currentUsage = (Integer)results[0].get('sum');
        System.enqueueJob(this);
    }
    public void execute(QueueableContext context) {
        Url baseUrl = Url.getSalesforceBaseUrl();
        String baseEndpoint = '/services/data/v55.0/composite/sobjects?ids=';
        List<String[]> batches = new List<String[]>();
        {
            String[] batch = new String[0];
            Integer accumulatedLogSize = 0;
            for(ApexLog log: [SELECT LogLength FROM ApexLog ORDER BY LastModifiedDate ASC LIMIT 20000]) {
                accumulatedLogSize += log.LogLength;
                batch.add(log.Id);
                // Reduces by 500,000,000. Adjust to your liking.
                if(accumulatedLogSize > 500000000) {
                    break;
                }
                // Can only do 200 at a time unless we want do to JSON stuff. I do not.
                if(batch.size() == 200) {
                    batches.add(batch);
                    batch = new String[0];
                }
            }
            if(batch.size() > 0) {
                batches.add(batch);
            }
        }
        for(String[] batch: batches) {
            HttpRequest req = new HttpRequest();
            req.setHeader('Authorization', 'OAuth '+UserInfo.getSessionId());
            req.setMethod('DELETE');
            req.setEndpoint(new Url(baseUrl, baseEndpoint+String.join(batch,'&')).toExternalForm());
            try {
                new Http().send(req);
            } catch(Exception e) {
                // It didn't like that batch for some reason. We'll try to get it next time
            }
        }
    }
}

Schedule this to run hourly:

System.schedule('TruncateLogsHourly', '0 0 * * * ?', new TruncateLog());

Now, assuming your users haven't hit the maximum of 1GB in an hour, they'll magically have at least 500,000,000 bytes of log data removed.

2
  • I like it! Do you use this in your org(s)? If so, do you have it auto-scheduled in new sandboxes by scheduling it from a have a SandboxPostCopy Apex class? Commented Sep 30, 2022 at 3:48
  • 2
    @Bow-chicawow-ers I literally wrote this like ten minutes ago. I'm probably going to make a package out of it, so I can install and schedule it in my Scratch Orgs as part of the build process. Not sure if a SandboxPostCopy will work correctly, I'm not sure the installation user has the permissions to delete logs; I'd probably set this up in a deploy/install script instead for Sandboxes.
    – sfdcfox
    Commented Sep 30, 2022 at 3:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .