Skip to content

Commit

Permalink
Added testing for the logger implementation
Browse files Browse the repository at this point in the history
Simplified the logger interface
Improved the output of the logger so it's clearer
  • Loading branch information
rob-baillie-ortoo committed Apr 7, 2022
1 parent 53caeec commit 778cafc
Show file tree
Hide file tree
Showing 8 changed files with 527 additions and 236 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ public interface ILoggerService
void log( LoggerService.Level logLevel, String message, Id relatedSobjectId );
void log( Exception exceptionToLog );
void log( Exception exceptionToLog, Id relatedSobject );
void log( DmlException exceptionToLog );
void log( ortoo_Exception exceptionToLog );
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ public inherited sharing class LoggerService
}

/**
* Log the given exception
* Log the given exception.
*
* Will produce output specific to different types:
* DmlException
* ortoo_Exception
* all other Exceptions
*
* @param Exception The exception to log
*/
Expand All @@ -95,51 +100,6 @@ public inherited sharing class LoggerService
return;
}

if ( exceptionToLog instanceOf DmlException )
{
service().log( (DmlException)exceptionToLog );
}
if ( exceptionToLog instanceOf ortoo_Exception )
{
service().log( (ortoo_Exception)exceptionToLog );
}
service().log( exceptionToLog );
}

/**
* Log the given DmlException
*
* @param DmlException The exception to log
*/
public static void log( DmlException exceptionToLog )
{
if ( ! shouldLogExceptions() )
{
return;
}

try
{
service().log( exceptionToLog );
}
catch ( Exception e )
{
System.debug( LoggingLevel.ERROR, 'Exception when attempting to log ' + exceptionToLog + ' - ' + e );
}
}

/**
* Log the given ortoo_Exception
*
* @param ortoo_Exception The exception to log
*/
public static void log( ortoo_Exception exceptionToLog )
{
if ( ! shouldLogExceptions() )
{
return;
}

try
{
service().log( exceptionToLog );
Expand Down Expand Up @@ -175,7 +135,7 @@ public inherited sharing class LoggerService

private static Boolean shouldLog( LoggerService.Level logLevel )
{
// If no config record exists, then get the whether the logging should be on from the service
// If no config record exists, then get the whether the logging should be on from the service implementation
switch on logLevel {
when INFO {
return config.Name != null ? config.Log_INFO_Level_Messages__c : service().getDefaultLoggingEnabled( logLevel );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
*/
public with sharing class LoggerServiceImpl implements ILoggerService
{
// TODO: should we output more from the standard exceptions?
// TODO: Test the static wrapper and references to the custom setting / defaults
// TODO: what can we output in the UI? Flag on custom settings to decide
// TODO: search for any System.debug in the code
// TODO: notes on testing if the logger is used - you have to set up the custom metadata first - create a test utils for it

private static final String BLANK_LINE = '';

public Boolean getDefaultLoggingEnabled( LoggerService.Level logLevel )
{
return true;
Expand All @@ -23,91 +25,163 @@ public with sharing class LoggerServiceImpl implements ILoggerService

public void log( LoggerService.Level logLevel, String message, Id relatedSobjectId )
{
logMessage( logLevel, relatedSObjectId, message );
logMessage( logLevel, 'On ' + relatedSobjectId + ': ' + message );
}

public void log( Exception exceptionToLog )
{
String exceptionName = exceptionToLog.getTypeName();
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName, exceptionToLog.getMessage() );
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName + '.stackTrace', exceptionToLog.getStackTraceString() );
logCausedByFor( exceptionToLog );
log( exceptionToLog, null );
}

public void log( DmlException exceptionToLog )
{
String exceptionName = exceptionToLog.getTypeName();
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName, exceptionToLog.getDmlId(0), exceptionToLog.getMessage() );
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName + '.stackTrace', exceptionToLog.getStackTraceString() );
logCausedByFor( exceptionToLog );
}

public void log( ortoo_Exception exceptionToLog )
public void log( Exception exceptionToLog, Id relatedSobjectId )
{
String exceptionName = exceptionToLog.getTypeName() + ' (' + exceptionToLog.getErrorCode() + ')';
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName, exceptionToLog.getMessage() );

ortoo_Exception.Contexts contexts = exceptionToLog.getContexts();
while ( contexts.hasNext() )
if ( exceptionToLog == null )
{
ortoo_Exception.Context thisContext = contexts.next();
// Put this into toString on Context?
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName + '.context', thisContext.getName() + ' = ' + thisContext.getValue() + ' @ ' + thisContext.getRecordPoint() );
return;
}

for ( MessageDetail thisMessageDetail : exceptionToLog.getMessageDetails() )
{
// Put this into toString on MessageDetail?
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName + '.messageDetail', thisMessageDetail.getFieldContext() + ' => "' + thisMessageDetail.getContent() + '" on ' + thisMessageDetail.getObjectContext() );
}
String message = String.join( genericBuildExceptionMessages( exceptionToLog, relatedSobjectId ), '\n' );

logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName + '.stackTrace', exceptionToLog.getStackTraceString() );
logCausedByFor( exceptionToLog );
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, message );
}

public void log( Exception exceptionToLog, Id relatedSobjectId )
private List<String> genericBuildExceptionMessages( Exception exceptionToLog )
{
String exceptionName = ObjectUtils.getClassName( exceptionToLog );
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName, relatedSobjectId, exceptionToLog.getMessage() );
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName + '.stackTrace', exceptionToLog.getStackTraceString() );
logCausedByFor( exceptionToLog );
return genericBuildExceptionMessages( exceptionToLog, null );
}

private void logMessage( LoggerService.Level logLevel, String message )
private List<String> genericBuildExceptionMessages( Exception exceptionToLog, Id relatedSobjectId )
{
System.debug( translateDebugLevel( logLevel ), message );
if ( exceptionToLog instanceOf ortoo_Exception )
{
return buildExceptionMessages( (ortoo_Exception)exceptionToLog, relatedSobjectId );
}
if ( exceptionToLog instanceOf DmlException )
{
return buildExceptionMessages( (DmlException)exceptionToLog, relatedSobjectId );
}
return buildExceptionMessages( exceptionToLog, relatedSobjectId );
}

private void logMessage( LoggerService.Level logLevel, Id relatedSobjectId, String message )
private List<String> buildExceptionMessages( Exception exceptionToLog, Id relatedSobjectId )
{
logMessage( logLevel, 'On ' + relatedSobjectId, message );
String exceptionName = exceptionToLog.getTypeName();

List<String> messages = new List<String>{ exceptionName + ': ' + exceptionToLog.getMessage() };
if ( relatedSobjectId != null )
{
messages.add( 'Against Id: ' + relatedSobjectId );
}
messages.addAll( buildStackTraceMessages( exceptionToLog ) );
messages.addAll( buildCausedByMessages( exceptionToLog ) );
return messages;
}

private void logMessage( LoggerService.Level logLevel, String reference, String message )
private List<String> buildExceptionMessages( DmlException exceptionToLog, Id relatedSobjectId )
{
logMessage( logLevel, reference + ': ' + message );
String exceptionName = exceptionToLog.getTypeName();

List<String> messages = new List<String>{ exceptionName + ': ' + exceptionToLog.getMessage() };

if ( relatedSobjectId != null )
{
messages.add( 'Against Id: ' + relatedSobjectId );
}

Integer numberOfDmlErrors = exceptionToLog.getNumDml();
for ( Integer i=0; i<numberOfDmlErrors; i++ )
{
if ( i==0 )
{
messages.add( BLANK_LINE );
messages.add( 'Row details:' );
}

String rowMessage = i + ' - ' + exceptionToLog.getDmlType( i ) + ': ';
if ( exceptionToLog.getDmlId( i ) != null )
{
rowMessage += ' Id = ' + exceptionToLog.getDmlId( i ) + ' - ';
}
rowMessage += exceptionToLog.getDmlMessage( i );
messages.add( rowMessage );
}

messages.addAll( buildStackTraceMessages( exceptionToLog ) );
messages.addAll( buildCausedByMessages( exceptionToLog ) );
return messages;
}

private void logMessage( LoggerService.Level logLevel, String reference, Id relatedSobjectId, String message )
private List<String> buildExceptionMessages( ortoo_Exception exceptionToLog, Id relatedSobjectId )
{
String exceptionName = exceptionToLog.getTypeName() + ' (' + exceptionToLog.getErrorCode() + '): ';

List<String> messages = new List<String>{ exceptionName + exceptionToLog.getMessage() };

if ( relatedSobjectId != null )
{
logMessage( logLevel, reference + ' on ' + relatedSobjectId, message );
messages.add( 'Against Id: ' + relatedSobjectId );
}
else

ortoo_Exception.Contexts contexts = exceptionToLog.getContexts();

Boolean first = true;
while ( contexts.hasNext() )
{
logMessage( logLevel, reference, message );
if ( first )
{
messages.add( BLANK_LINE );
messages.add( 'Context: ' );
first = false;
}
ortoo_Exception.Context thisContext = contexts.next();
messages.add( thisContext.getName() + ' = ' + thisContext.getValue() + ' @ ' + thisContext.getRecordPoint() );
}

first = true;
for ( MessageDetail thisMessageDetail : exceptionToLog.getMessageDetails() )
{
if ( first )
{
messages.add( BLANK_LINE );
messages.add( 'Message Detail: ' );
first = false;
}
messages.add( thisMessageDetail.getFieldContext() + ' => "' + thisMessageDetail.getContent() + '" on ' + thisMessageDetail.getObjectContext() );
}

messages.add( BLANK_LINE );
messages.addAll( buildStackTraceMessages( exceptionToLog ) );
messages.addAll( buildCausedByMessages( exceptionToLog ) );
return messages;
}

private void logCausedByFor( Exception mainException )
private List<String> buildCausedByMessages( Exception mainException )
{
String exceptionName = mainException.getTypeName();
if ( mainException.getCause() != null )
if ( mainException.getCause() == null )
{
logMessage( LoggerService.EXCEPTION_LOG_LEVEL, exceptionName, 'Caused By' );
log( mainException.getCause() );
return new List<String>();
}

List<String> messages = new List<String>{
BLANK_LINE,
'Caused By:'
};
messages.addAll( genericBuildExceptionMessages( mainException.getCause() ) );
return messages;
}

private List<String> buildStackTraceMessages( Exception exceptionToLog )
{
return new List<String>{
BLANK_LINE,
'Stack Trace:',
exceptionToLog.getStackTraceString()
};
}

private void logMessage( LoggerService.Level logLevel, String message )
{
System.debug( translateDebugLevel( logLevel ), message );
}

private LoggingLevel translateDebugLevel( LoggerService.Level logLevel )
Expand Down
Loading

0 comments on commit 778cafc

Please sign in to comment.