Over the last few months, we have been doing more and more in Salesforce. Adding new integrations, new features, new emails etc. I have been worried that we are not really watching the right things and soon, we will come into work one day and have bricked our org for a day because we have hit a hard limit.
In our offices, we display a dashboard that monitors some of the things that would give us indications that some of the features we have built are not working for one reason or another. But this just tells us if its working or not. I would also like to proactively monitor Salesforce limits that are most important to us. Luckily, there is a REST resource for Limits that allows us to monitor this.
My plan was to use this on our dashboards site so the monitor that displays our existing dashboard can cycle through this. However, according to the documentation, the user who is executing the Limits resource needs to have View Setup and Configuration and some of the Limits will require Manage User permissions. Unfortunately, for me, the user who will be executing the page can’t get these permissions. No matter how I access the resource, even when providing OAuth authentication with another user, I still am not able to execute and receive the limits appropriately. Pretty big bummer actually.
There is also a Limits class that has some cool stuff, but I don’t think this has most of what I’m looking to do. My options are to log into the dashboard monitor as a real user, and possibly allow someone to find the keyboard and get access to our org, or think of a different way to get the Limits resource data and display it on this monitor.
After kicking this around for a few weeks, going back and forth on if this was even valuable, we almost hit a limit and my decision was made for me. This not only had to be done, but needed to be displayed for all to see to help report a problem.
I decided that the easiest way to do this was to run a scheduled job at a regular interval and populate data into a custom setting. Then the page which would be available on a “hidden” public site would just render the data from the custom setting.
Quick note: some of this code probably sucks. There are most likely other ways of doing this, but I wanted to slap something together quickly so we could get this up and running. If you want to grab this code, make sure you understand what it does and think about optimizing it.
Ok, so let’s start with the REST resource. I have a class called ‘populateLimitsScheduler’ which is called as a scheduled job. I am running it every 15 minutes. The class uses ‘implements Schedulable’ so that it can be scheduled. It has an Execute method to trigger the API call, a method called populateLimits() to organize the data and save it, a method called runAPI() to access the REST resource and a wrapper for the incoming Limits. Lets start with the Wrapper:
If you execute the Limits resource by itself, you will notice that the limits will come with a name, a max and a remaining value. The Execute method will be used by the scheduled job to run the populateLimits method:
The ‘populateLimits’ method is where we are going to setup all of our data, assign variables and upsert into our Custom Setting:
You’ll notice that we call runAPI() and assign the values to a List of sfLimits. This method will access the Limits resource, parse the response and create a bunch of sfLimits:
This thing is REALLY complicated. I attempted to use JSON2Apex by pasting the response from Limits, but it was taking forever and the structure of the Limits response kind of makes it a pain to use. So, instead of using JSON2Apex, I created my own JSON parser for the structure of the Limits Resource. What makes it problematic is that limits are imbedded within other limits. There is probably an easy way to parse the response with JSON2Apex, but I was just having all kinds of issues and just did it on my own. This is probably the part that could use a rewrite.
ANYWAY, this method attempts to login using OAuth with a system user and then once a valid token is returned, access the Limits resource. We then parse the response from the Limits resource from the format we get and then make sfLimits out of each one. One problem that happens with this resource, is there are some Limits that are duplicated in the response under different parent Limits. This causes some funkiness but we try to resolve this later.
Once we return all of the sfLimits in runAPI to populateLimits, we put them into a Map to attempt to de-dupe based on the Limit name since we should never have more than 1 Limit with the same name anyway. After we created the Map, we create individual records in our custom setting called Limits__c and populate with objects with the variable name limitInstance. Then we just upsert a list of these based on the Name to replace the existing Limits in the custom setting. This data will just keep being replaced over and over again to get the newest numbers. Maybe some day we will redesign this to store data over time to do comparisons, but right now, I just want to show the current data. Complete code at the end of the blog post.
So after we have this code, we can schedule it every 15 minutes by running this in dev console:
So now every 15 minutes, the Limits API will be accessed, limits pulled down and saved to our custom setting.
We have Data!
Now we need a page though that will display the data we want. There are 6 limits that I want to monitor based on some of our previous experience and things that most companies will probably have trouble with:
- Daily API Limit
- Daily Asynchronous Apex
- Hourly oData Callout Limit (External Objects)
- Daily Emails sent from Apex
- Daily Workflow Emails
- Hourly Scheduled Workflow
We can then just create a Page and a Controller. The controller is pretty simple:
And the page:
We are using a couple of libraries such as jQuery and Bootstrap and then also my favorite charting library, Highcharts.
Then, we get a page that looks like this:
It is responsive with the Bootstrap and Highcharts, so looks pretty great on mobile too!
Last, we make this page available on our public dashboards site so it is accessible, but the underlying data, API access and credentials for the OAuth callout is not which is pretty cool. So now, we have our two dashboards that help our Salesforce team make sure they can easily monitor some of the things that we are important to us daily. When all is said and done, we come up with this for all to see in our IT department:
Test for our code:
Mock for our Limits callout for the test: