Logging Code Examples

Problem: You need a consistent logging mechanism across your application.

Solution:

Custom Object (LOG_LogMessage__c):

Apex (LOG_LogMessageUtility.cls):

/**
 * Utility class for structured logging
 * Uses custom LOG_LogMessage__c object
 */
public with sharing class LOG_LogMessageUtility {
    
    /**
     * Logs an info message
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     */
    public static void logInfo(String source, String function, String message) {
        createLog('INFO', source, function, message, null, null);
    }
    
    /**
     * Logs a warning message
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     */
    public static void logWarning(String source, String function, String message) {
        createLog('WARNING', source, function, message, null, null);
    }
    
    /**
     * Logs an error message
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     * @param exception Exception object (optional)
     */
    public static void logError(String source, String function, String message, Exception exception) {
        String stackTrace = exception != null ? exception.getStackTraceString() : null;
        createLog('ERROR', source, function, message, stackTrace, null);
    }
    
    /**
     * Logs a debug message
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     */
    public static void logDebug(String source, String function, String message) {
        createLog('DEBUG', source, function, message, null, null);
    }
    
    /**
     * Creates a log record
     * @param level Log level
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     * @param stackTrace Stack trace
     * @param recordId Related record ID
     */
    private static void createLog(String level, String source, String function, String message, String stackTrace, Id recordId) {
        try {
            LOG_LogMessage__c log = new LOG_LogMessage__c();
            log.Level__c = level;
            log.Source__c = source;
            log.Function__c = function;
            log.Message__c = message;
            log.Stack_Trace__c = stackTrace;
            log.Record_ID__c = recordId;
            log.User_ID__c = UserInfo.getUserId();
            log.Timestamp__c = DateTime.now();
            
            insert log;
            
        } catch (Exception e) {
            // Fallback to platform event if DML fails
            publishLogEvent(level, source, function, message, stackTrace, recordId);
        }
    }
    
    /**
     * Publishes log to platform event as fallback
     * @param level Log level
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     * @param stackTrace Stack trace
     * @param recordId Related record ID
     */
    private static void publishLogEvent(String level, String source, String function, String message, String stackTrace, Id recordId) {
        try {
            LOG_LogEvent__e event = new LOG_LogEvent__e();
            event.Level__c = level;
            event.Source__c = source;
            event.Function__c = function;
            event.Message__c = message;
            event.Stack_Trace__c = stackTrace;
            event.Record_ID__c = recordId;
            
            EventBus.publish(new List<LOG_LogEvent__e>{ event });
            
        } catch (Exception e) {
            // Last resort - use System.debug
            System.debug(LoggingLevel.ERROR, 'Logging failed: ' + source + '.' + function + ' - ' + message);
        }
    }
}

Usage:

// Log info
LOG_LogMessageUtility.logInfo('ContactService', 'processContacts', 'Processing 10 contacts');

// Log error
try {
    // Some operation
} catch (Exception e) {
    LOG_LogMessageUtility.logError('ContactService', 'processContacts', 'Error processing contacts', e);
}

Best Practices:

Example 2: Logging with Platform Event Fallback

Pattern: Platform event fallback when DML fails Use Case: Ensuring logs are captured even when DML fails Complexity: Intermediate Related Patterns: Error Handling and Logging

Problem: You need to ensure logs are captured even when DML operations fail (e.g., during trigger failures).

Solution:

Platform Event (LOG_LogEvent__e):

Apex (LOG_LogMessageUtility.cls - Enhanced):

/**
 * Enhanced logging utility with platform event fallback
 */
public with sharing class LOG_LogMessageUtility {
    
    /**
     * Creates log with automatic fallback
     * @param level Log level
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     * @param stackTrace Stack trace
     * @param recordId Related record ID
     */
    public static void createLog(String level, String source, String function, String message, String stackTrace, Id recordId) {
        // Try DML first
        try {
            LOG_LogMessage__c log = new LOG_LogMessage__c();
            log.Level__c = level;
            log.Source__c = source;
            log.Function__c = function;
            log.Message__c = message;
            log.Stack_Trace__c = stackTrace;
            log.Record_ID__c = recordId;
            log.User_ID__c = UserInfo.getUserId();
            log.Timestamp__c = DateTime.now();
            
            insert log;
            return; // Success - exit
            
        } catch (DmlException e) {
            // DML failed - use platform event fallback
            publishLogEvent(level, source, function, message, stackTrace, recordId);
            
        } catch (Exception e) {
            // Unexpected error - use platform event fallback
            publishLogEvent(level, source, function, message, stackTrace, recordId);
        }
    }
    
    /**
     * Publishes log to platform event
     * @param level Log level
     * @param source Source class/component
     * @param function Function/method name
     * @param message Log message
     * @param stackTrace Stack trace
     * @param recordId Related record ID
     */
    private static void publishLogEvent(String level, String source, String function, String message, String stackTrace, Id recordId) {
        try {
            LOG_LogEvent__e event = new LOG_LogEvent__e();
            event.Level__c = level;
            event.Source__c = source;
            event.Function__c = function;
            event.Message__c = message;
            event.Stack_Trace__c = stackTrace;
            event.Record_ID__c = recordId != null ? String.valueOf(recordId) : null;
            
            List<Database.SaveResult> results = EventBus.publish(new List<LOG_LogEvent__e>{ event });
            
            // Check for publish errors
            for (Database.SaveResult result : results) {
                if (!result.isSuccess()) {
                    // Last resort - System.debug
                    System.debug(LoggingLevel.ERROR, 'Log event publish failed: ' + source + '.' + function);
                }
            }
            
        } catch (Exception e) {
            // Last resort - System.debug
            System.debug(LoggingLevel.ERROR, 'Logging completely failed: ' + source + '.' + function + ' - ' + message);
        }
    }
}

Best Practices:

Example 3: External Logging Integration

Pattern: Integrating with external logging systems Use Case: Centralized logging across multiple systems Complexity: Advanced Related Patterns: Observability Patterns

Problem: You need to send logs to an external logging system (e.g., Splunk, OpenSearch).

Solution:

Apex (ExternalLoggingService.cls):

/**
 * Service for sending logs to external logging systems
 */
public with sharing class ExternalLoggingService implements Queueable, Database.AllowsCallouts {
    
    private List<LOG_LogMessage__c> logs;
    
    public ExternalLoggingService(List<LOG_LogMessage__c> logs) {
        this.logs = logs;
    }
    
    public void execute(QueueableContext context) {
        for (LOG_LogMessage__c log : logs) {
            try {
                sendToExternalSystem(log);
            } catch (Exception e) {
                // Log error but don't fail the job
                System.debug(LoggingLevel.ERROR, 'Failed to send log to external system: ' + e.getMessage());
            }
        }
    }
    
    /**
     * Sends log to external logging system
     * @param log Log message record
     */
    private void sendToExternalSystem(LOG_LogMessage__c log) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:ExternalLoggingApi/api/logs');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setTimeout(30000);
        
        // Build log payload
        Map<String, Object> payload = new Map<String, Object>{
            'level' => log.Level__c,
            'source' => log.Source__c,
            'function' => log.Function__c,
            'message' => log.Message__c,
            'stackTrace' => log.Stack_Trace__c,
            'recordId' => log.Record_ID__c,
            'userId' => log.User_ID__c,
            'timestamp' => log.Timestamp__c
        };
        
        req.setBody(JSON.serialize(payload));
        
        Http http = new Http();
        HttpResponse res = http.send(req);
        
        if (res.getStatusCode() >= 200 && res.getStatusCode() < 300) {
            // Success
            return;
        }
        
        throw new ExternalLoggingException('Failed to send log: ' + res.getStatusCode());
    }
    
    /**
     * Enqueues logs for external system
     * @param logs List of log records
     */
    public static void enqueueLogs(List<LOG_LogMessage__c> logs) {
        if (logs != null && !logs.isEmpty()) {
            System.enqueueJob(new ExternalLoggingService(logs));
        }
    }
    
    public class ExternalLoggingException extends Exception {}
}

Usage:

// After creating logs, send to external system
List<LOG_LogMessage__c> logs = new List<LOG_LogMessage__c>();
// ... create logs ...
insert logs;
ExternalLoggingService.enqueueLogs(logs);

Best Practices: