In order to achieve that below is what I did-
First I have created an object(API Name: Custom_Log__c) to store the exception logs-
Below are the custom field inside the object-
- Class__c(Text Area(255)) From which class the exception is coming
- Method__c(Text Area(255)) From which method the exception is coming
- Message__c(Long Text Area(32768)) Stack trace of the exception
- Priority__c(Picklist) – Possible values are DEBUG, ERROR, FATAL, INFO, WARNING
<apex:page controller="CustomLogController">
<apex:form >
<apex:commandButton value="Divide By Zero Exception!" action="{!divideByZeroException}" />
<br/>
<apex:commandButton value="Null Pointer Exception!" action="{!nullPointerException}" />
</apex:form>
</apex:page>

Now the controller – CustomLogController:
public class CustomLogController {
public void divideByZeroException(){
Integer number1, number2;
try{
number1 = 10;
number2 = 0;
Integer number3 = number1/number2;
}catch(Exception ex){
String message = 'Error: ' + ex.getMessage() + '; Stack Trace:' + ex.getStackTraceString();
CustomLogging.logMessage('CustomLogController', 'divideByZeroException', message, CustomLogging.WARNING);
}
}
public void nullPointerException(){
Contact aContact = null;
try{
String email = aContact.Email;
}catch(Exception ex){
String message = 'Error: ' + ex.getMessage() + '; Stack Trace:' + ex.getStackTraceString();
CustomLogging.logMessage('CustomLogController', 'nullPointerException', message, CustomLogging.ERROR);
}
}
}
Now the CustomLogging class-
public class CustomLogging {
public static String INFO = 'INFO';
public static String DEBUG = 'DEBUG';
public static String WARNING = 'WARNING';
public static String ERROR = 'ERROR';
public static String FATAL = 'FATAL';
private static Boolean isEnabled(){
Decision_Object__c enableCustomLogging = Decision_Object__c.getInstance('EnableCustomLogging');
System.debug('IsEnabled: ' + enableCustomLogging.Value__c);
return enableCustomLogging.Value__c;
}
public static void logMessage(String className, String methodName, String message, String Priority){
if(isEnabled()){
Custom_Log__c newLogMessage = new Custom_Log__c(
Class__c = className,
Method__c = methodName,
Message__c = message,
Priority__c = Priority);
try{
Database.insert(newLogMessage);
}catch(Exception ex){
System.debug(
'Failed to INSERT the [Apex Debug Log] ADL record. ' +
'Error: ' + ex.getMessage()
);
}
}else{
String completeErrorMessage = 'Error occured at class: ' + className + ' method: ' + methodName +
' and the error is: ' + message;
System.debug(completeErrorMessage);
}
}
}
And finally the test class – This is very important
@isTest
private class UnitTestCustomLogController {
private static void setEnableCustomLoggingFlag(Boolean value){
insert(new Decision_Object__c(Name='EnableCustomLogging', Value__c=value));
}
static testMethod void testWhetherCustomLoggingIsGettingCreatedWhileDisabled() {
setEnableCustomLoggingFlag(false);
CustomLogController customLogController = new CustomLogController();
customLogController.divideByZeroException();
Integer numberOfCustomLogs= [Select count() From Custom_Log__c];
System.assertEquals(0, numberOfCustomLogs);
}
static testMethod void testDivideByZeroException(){
setEnableCustomLoggingFlag(true);
CustomLogController customLogController = new CustomLogController();
customLogController.divideByZeroException();
Integer numberOfCustomLogs= [Select count() From Custom_Log__c];
Custom_Log__c customLog= [Select Class__c, Priority__c, Method__c, Message__c From Custom_Log__c LIMIT 1];
System.assertEquals('CustomLogController', customLog.Class__c);
System.assertEquals('divideByZeroException', customLog.Method__c);
System.assertEquals(CustomLogging.WARNING, customLog.Priority__c);
}
static testMethod void testNullPointerException(){
setEnableCustomLoggingFlag(true);
CustomLogController customLogController = new CustomLogController();
customLogController.nullPointerException();
Integer numberOfCustomLogs= [Select count() From Custom_Log__c];
Custom_Log__c customLog= [Select Class__c, Priority__c, Method__c, Message__c From Custom_Log__c LIMIT 1];
System.assertEquals('CustomLogController', customLog.Class__c);
System.assertEquals('nullPointerException', customLog.Method__c);
System.assertEquals(CustomLogging.ERROR, customLog.Priority__c);
}
}
Done. That’s all.
So now if I click on any of the buttons in VisualForce page and EnableCustomLogging = true, I can see one record is getting inserted into the Custom_Log__c object like below-
If you have any feedback, please share. Thanks.