diff --git a/framework/default/modules/logger/services/logger/classes/ILoggerService.cls b/framework/default/modules/logger/services/logger/classes/ILoggerService.cls index db60cbe2593..174e7eef451 100644 --- a/framework/default/modules/logger/services/logger/classes/ILoggerService.cls +++ b/framework/default/modules/logger/services/logger/classes/ILoggerService.cls @@ -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 ); } \ No newline at end of file diff --git a/framework/default/modules/logger/services/logger/classes/LoggerService.cls b/framework/default/modules/logger/services/logger/classes/LoggerService.cls index 742ef4fec41..85246c4d9b1 100644 --- a/framework/default/modules/logger/services/logger/classes/LoggerService.cls +++ b/framework/default/modules/logger/services/logger/classes/LoggerService.cls @@ -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 */ @@ -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 ); @@ -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 ); diff --git a/framework/default/modules/logger/services/logger/classes/LoggerServiceImpl.cls b/framework/default/modules/logger/services/logger/classes/LoggerServiceImpl.cls index 6a3bbe2bd8f..b9a629a9f64 100644 --- a/framework/default/modules/logger/services/logger/classes/LoggerServiceImpl.cls +++ b/framework/default/modules/logger/services/logger/classes/LoggerServiceImpl.cls @@ -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; @@ -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 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 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 buildExceptionMessages( Exception exceptionToLog, Id relatedSobjectId ) { - logMessage( logLevel, 'On ' + relatedSobjectId, message ); + String exceptionName = exceptionToLog.getTypeName(); + + List messages = new List{ 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 buildExceptionMessages( DmlException exceptionToLog, Id relatedSobjectId ) { - logMessage( logLevel, reference + ': ' + message ); + String exceptionName = exceptionToLog.getTypeName(); + + List messages = new List{ exceptionName + ': ' + exceptionToLog.getMessage() }; + + if ( relatedSobjectId != null ) + { + messages.add( 'Against Id: ' + relatedSobjectId ); + } + + Integer numberOfDmlErrors = exceptionToLog.getNumDml(); + for ( Integer i=0; i buildExceptionMessages( ortoo_Exception exceptionToLog, Id relatedSobjectId ) { + String exceptionName = exceptionToLog.getTypeName() + ' (' + exceptionToLog.getErrorCode() + '): '; + + List messages = new List{ 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 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(); } + + List messages = new List{ + BLANK_LINE, + 'Caused By:' + }; + messages.addAll( genericBuildExceptionMessages( mainException.getCause() ) ); + return messages; + } + + private List buildStackTraceMessages( Exception exceptionToLog ) + { + return new List{ + 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 ) diff --git a/framework/default/modules/logger/services/logger/classes/tests/LoggerServiceImplTest.cls b/framework/default/modules/logger/services/logger/classes/tests/LoggerServiceImplTest.cls new file mode 100644 index 00000000000..df311c673f4 --- /dev/null +++ b/framework/default/modules/logger/services/logger/classes/tests/LoggerServiceImplTest.cls @@ -0,0 +1,183 @@ +@isTest +private without sharing class LoggerServiceImplTest +{ + // + // Note that these tests call the Impl directly since the static wrapper is + // not guaranteed to call the child because of configuration + // + @isTest + private static void getDefaultLoggingEnabled_returnsTrue() // NOPMD: Test method name format + { + ILoggerService loggerServiceImpl = new LoggerServiceImpl(); + + System.assertEquals( true, loggerServiceImpl.getDefaultLoggingEnabled( LoggerService.Level.ERROR ), 'getDefaultLoggingEnabled, when called with ERROR, returns true' ); + System.assertEquals( true, loggerServiceImpl.getDefaultLoggingEnabled( LoggerService.Level.WARN ), 'getDefaultLoggingEnabled, when called with WARN, returns true' ); + System.assertEquals( true, loggerServiceImpl.getDefaultLoggingEnabled( LoggerService.Level.INFO ), 'getDefaultLoggingEnabled, when called with INFO, returns true' ); + } + + @isTest + private static void log_whenGivenLogLevelAndMessage_willLog() // NOPMD: Test method name format + { + LoggerService.Level logLevel = LoggerService.Level.INFO; + String message = 'a message'; + + Test.startTest(); + new LoggerServiceImpl().log( logLevel, message ); + Test.stopTest(); + + System.assert( true, 'log, when given a log level and message, will log using system debug - which is not testable' ); + } + + @isTest + private static void log_whenGivenNullLogLevelAndMessage_willNotThrowAnException() // NOPMD: Test method name format + { + LoggerService.Level logLevel = null; + String message = null; + + Test.startTest(); + new LoggerServiceImpl().log( logLevel, message ); + Test.stopTest(); + + System.assert( true, 'log, when given a null log level and message, will not throw an exception' ); + } + + @isTest + private static void log_whenGivenLogLevelMessageAndId_willLog() // NOPMD: Test method name format + { + LoggerService.Level logLevel = LoggerService.Level.WARN; + String message = 'message'; + Id sobjectId = TestIdUtils.generateId( Contact.sobjectType ); + + Test.startTest(); + new LoggerServiceImpl().log( logLevel, message, sobjectId ); + Test.stopTest(); + + System.assert( true, 'log, when given a log level, message and sobject Id, will log using system debug - which is not testable' ); + } + + @isTest + private static void log_whenGivenLogLevelMessageAndNullId_willLog() // NOPMD: Test method name format + { + LoggerService.Level logLevel = LoggerService.Level.WARN; + String message = 'message'; + Id sobjectId = null; + + Test.startTest(); + new LoggerServiceImpl().log( logLevel, message, sobjectId ); + Test.stopTest(); + + System.assert( true, 'log, when given a log level, message and null sobject Id, will log using system debug - which is not testable' ); + } + + @isTest + private static void log_whenGivenNullLogLevelMessageAndId_willNotThrowAnException() // NOPMD: Test method name format + { + LoggerService.Level logLevel = null; + String message = null; + Id sobjectId = null; + + Test.startTest(); + new LoggerServiceImpl().log( logLevel, message, sobjectId ); + Test.stopTest(); + + System.assert( true, 'log, when given a log level, message and sobject Id, will not throw an exception' ); + } + + @isTest + private static void log_whenGivenAnException_willLog() // NOPMD: Test method name format + { + Exception e = new LocalException( 'message' ); + + Test.startTest(); + new LoggerServiceImpl().log( e ); + Test.stopTest(); + + System.assert( true, 'log, when given an exception, will log using system debug - which is not testable' ); + } + + @isTest + private static void log_whenGivenANullException_willNotThrowAnException() // NOPMD: Test method name format + { + Exception e = null; + + Test.startTest(); + new LoggerServiceImpl().log( e ); + Test.stopTest(); + + System.assert( true, 'log, when given a null exception, will not throw an exception' ); + } + + @isTest + private static void log_whenGivenAnExceptionAndAnId_willLog() // NOPMD: Test method name format + { + Exception causedBy = new LocalException( 'causedBy' ); + Exception e = new LocalException( 'message', causedBy ); + Id sobjectId = TestIdUtils.generateId( Contact.sobjectType ); + + Test.startTest(); + new LoggerServiceImpl().log( e, sobjectId ); + Test.stopTest(); + + System.assert( true, 'log, when given an exception and an sobject Id, will log using system debug - which is not testable' ); + } + + @isTest + private static void log_whenGivenAnExceptionAndAnId_willNotThrowAnException() // NOPMD: Test method name format + { + Exception e = null; + Id sobjectId = null; + + Test.startTest(); + new LoggerServiceImpl().log( e, sobjectId ); + Test.stopTest(); + + System.assert( true, 'log, when given an exception and an sobject Id, will not throw an exception' ); + } + + @isTest + private static void log_whenGivenANullDmlException_willNotThrowAnException() // NOPMD: Test method name format + { + DmlException e = null; + + Test.startTest(); + new LoggerServiceImpl().log( e ); + Test.stopTest(); + + System.assert( true, 'log, when given a null dml exception, will not throw an exception' ); + } + + // Note we cannot test the logging of the DmlException since we cannot set up the DML Ids, etc, and any call to these methods + // will cause uncatchable exceptions if they are not set up. + + @isTest + private static void log_whenGivenAnOrtooException_willLog() // NOPMD: Test method name format + { + Exception causedBy = new ortoo_Exception( 'caused by message' ); + ortoo_Exception e = new ortoo_Exception( 'message', causedBy ); + e.addContext('context', 'some context'); + e.setMessageDetails( new List{ + new MessageDetail( 'detail content') + }); + Id sobjectId = null; + + Test.startTest(); + new LoggerServiceImpl().log( e ); + Test.stopTest(); + + System.assert( true, 'log, when given an ortoo exception, will log using system debug - which is not testable' ); + } + + @isTest + private static void log_whenGivenANullOrtooException_willNotThrowAnException() // NOPMD: Test method name format + { + ortoo_Exception e = null; + + Test.startTest(); + new LoggerServiceImpl().log( e ); + Test.stopTest(); + + System.assert( true, 'log, when given a null ortoo exception, will not throw an exception' ); + } + + class LocalException extends Exception {} +} \ No newline at end of file diff --git a/framework/default/modules/logger/services/logger/classes/tests/LoggerServiceImplTest.cls-meta.xml b/framework/default/modules/logger/services/logger/classes/tests/LoggerServiceImplTest.cls-meta.xml new file mode 100644 index 00000000000..40d67933d00 --- /dev/null +++ b/framework/default/modules/logger/services/logger/classes/tests/LoggerServiceImplTest.cls-meta.xml @@ -0,0 +1,5 @@ + + + 54.0 + Active + diff --git a/framework/default/modules/logger/services/logger/classes/tests/NullLoggerServiceImplTest.cls b/framework/default/modules/logger/services/logger/classes/tests/NullLoggerServiceImplTest.cls index 509b3637650..2dd1712c538 100644 --- a/framework/default/modules/logger/services/logger/classes/tests/NullLoggerServiceImplTest.cls +++ b/framework/default/modules/logger/services/logger/classes/tests/NullLoggerServiceImplTest.cls @@ -1,6 +1,10 @@ @isTest private without sharing class NullLoggerServiceImplTest { + // + // Note that these tests call the Impl directly since the static wrapper is + // not guaranteed to call the child because of configuration + // @isTest private static void getDefaultLoggingEnabled_returnsFalse() // NOPMD: Test method name format { @@ -14,13 +18,11 @@ private without sharing class NullLoggerServiceImplTest @isTest private static void log_whenGivenLogLevelAndMessage_doNothing() // NOPMD: Test method name format { - Application.SERVICE.setMock( ILoggerService.class, new NullLoggerServiceImpl() ); - LoggerService.Level logLevel = null; String message = null; Test.startTest(); - LoggerService.log( logLevel, message ); + new NullLoggerServiceImpl().log( logLevel, message ); Test.stopTest(); System.assert( true, 'log, when given a log level and message, will do nothing' ); @@ -29,14 +31,12 @@ private without sharing class NullLoggerServiceImplTest @isTest private static void log_whenGivenLogLevelMessageAndId_doNothing() // NOPMD: Test method name format { - Application.SERVICE.setMock( ILoggerService.class, new NullLoggerServiceImpl() ); - LoggerService.Level logLevel = null; String message = null; Id sobjectId = null; Test.startTest(); - LoggerService.log( logLevel, message, sobjectId ); + new NullLoggerServiceImpl().log( logLevel, message, sobjectId ); Test.stopTest(); System.assert( true, 'log, when given a log level, message and sobject Id, will do nothing' ); @@ -45,12 +45,10 @@ private without sharing class NullLoggerServiceImplTest @isTest private static void log_whenGivenAnException_doNothing() // NOPMD: Test method name format { - Application.SERVICE.setMock( ILoggerService.class, new NullLoggerServiceImpl() ); - Exception e = null; Test.startTest(); - LoggerService.log( e ); + new NullLoggerServiceImpl().log( e ); Test.stopTest(); System.assert( true, 'log, when given an exception, will do nothing' ); @@ -59,45 +57,37 @@ private without sharing class NullLoggerServiceImplTest @isTest private static void log_whenGivenAnExceptionAndAnId_doNothing() // NOPMD: Test method name format { - Application.SERVICE.setMock( ILoggerService.class, new NullLoggerServiceImpl() ); - Exception e = null; Id sobjectId = null; Test.startTest(); - LoggerService.log( e, sobjectId ); + new NullLoggerServiceImpl().log( e, sobjectId ); Test.stopTest(); System.assert( true, 'log, when given an exception and an sobject Id, will do nothing' ); } @isTest - private static void log_whenGivenADmlExceptionAndAnId_doNothing() // NOPMD: Test method name format + private static void log_whenGivenADmlException_doNothing() // NOPMD: Test method name format { - Application.SERVICE.setMock( ILoggerService.class, new NullLoggerServiceImpl() ); - DmlException e = null; - Id sobjectId = null; Test.startTest(); - LoggerService.log( e, sobjectId ); + new NullLoggerServiceImpl().log( e ); Test.stopTest(); - System.assert( true, 'log, when given a dml exception and an sobject Id, will do nothing' ); + System.assert( true, 'log, when given a dml exception, will do nothing' ); } @isTest - private static void log_whenGivenAnOrtooExceptionAndAnId_doNothing() // NOPMD: Test method name format + private static void log_whenGivenAnOrtooException_doNothing() // NOPMD: Test method name format { - Application.SERVICE.setMock( ILoggerService.class, new NullLoggerServiceImpl() ); - ortoo_Exception e = null; - Id sobjectId = null; Test.startTest(); - LoggerService.log( e, sobjectId ); + new NullLoggerServiceImpl().log( e ); Test.stopTest(); - System.assert( true, 'log, when given an ortoo exception and an sobject Id, will do nothing' ); + System.assert( true, 'log, when given an ortoo exception, will do nothing' ); } } \ No newline at end of file diff --git a/scripts/apex/illustrateSimpleLogger.apex b/scripts/apex/illustrateSimpleLogger.apex index e2e0cc61ba9..78e2043c174 100644 --- a/scripts/apex/illustrateSimpleLogger.apex +++ b/scripts/apex/illustrateSimpleLogger.apex @@ -1,4 +1,9 @@ -Id id = '0032D00000WOOux'; +List ids = new List{ + '0032D00000WOOuw', + '0032D00000WOOux', + '0032D00000WOOuy', + '0032D00000WOOuz' +}; System.debug( 'Simple log messages' ); System.debug( '' ); @@ -9,16 +14,16 @@ LoggerService.log( LoggerService.Level.ERROR, 'This is an error message' ); System.debug( '' ); System.debug( 'Log messages with a related SObject' ); System.debug( '' ); -LoggerService.log( LoggerService.Level.INFO, 'This is an info message', id ); -LoggerService.log( LoggerService.Level.WARN, 'This is a warning message', id ); -LoggerService.log( LoggerService.Level.ERROR, 'This is an error message', id ); +LoggerService.log( LoggerService.Level.INFO, 'This is an info message', ids[0] ); +LoggerService.log( LoggerService.Level.WARN, 'This is a warning message', ids[0] ); +LoggerService.log( LoggerService.Level.ERROR, 'This is an error message', ids[0] ); System.debug( '' ); System.debug( 'Log of DML Exception with an Id' ); System.debug( '' ); try { - update new Contact( Id = id ); + update new Contact( Id = ids[0] ); } catch ( DmlException e ) { @@ -30,7 +35,11 @@ System.debug( 'Log of DML Exceptionm, handled with Exception with an Id' ); System.debug( '' ); try { - update new Contact( Id = id ); + update new List{ + new Contact( Id = ids[0] ), + new Contact( Id = ids[1] ), + new Contact( Id = ids[2] ) + }; } catch ( Exception e ) { @@ -42,7 +51,11 @@ System.debug( 'Log of DML Exception without an Id' ); System.debug( '' ); try { - insert new Contact(); + insert new List{ + new Contact(), + new Contact(), + new Contact() + }; } catch ( DmlException e ) { @@ -82,7 +95,7 @@ try } catch ( Exception e ) { - LoggerService.log( e, id ); + LoggerService.log( e, ids[0] ); } System.debug( '' ); @@ -127,11 +140,31 @@ catch ( ortoo_Exception e ) class OrtooExceptionThrower { + DmlException dmlExceptionThrown + { + get { + try + { + update new List{ + new Contact( Id = ids[0] ), + new Contact( Id = ids[1] ), + new Contact( Id = ids[2] ), + new Contact( Id = ids[3] ) + }; + } + catch ( DmlException e ) + { + return e; + } + return null; + } + } + public void throwException() { throw new Exceptions.DeveloperException( 'This is a developer exception' ) .setErrorCode( '12345' ) - .addContext( 'id', id ) + .addContext( 'id', ids[0] ) .addContext( 'otherThing', 'thingvalue' ) .setMessageDetails( new List{ new MessageDetail( new Contact( LastName = 'thingthatwentwrong' ), Contact.LastName, 'The last name went wrong' ) @@ -140,9 +173,9 @@ class OrtooExceptionThrower public void throwExceptionWithCausedBy() { - throw new Exceptions.DeveloperException( 'This is a developer exception', new DmlException( 'The cause of the exception' ) ) + throw new Exceptions.DeveloperException( 'This is a developer exception', dmlExceptionThrown ) .setErrorCode( '12345' ) - .addContext( 'id', id ) + .addContext( 'id', ids[0] ) .addContext( 'otherThing', 'thingvalue' ) .setMessageDetails( new List{ new MessageDetail( new Contact( LastName = 'thingthatwentwrong' ), Contact.LastName, 'The last name went wrong' ) diff --git a/scripts/apex/illustrateSimpleLogger.output.txt b/scripts/apex/illustrateSimpleLogger.output.txt index 83669fcbe5f..4c99c7d42f2 100644 --- a/scripts/apex/illustrateSimpleLogger.output.txt +++ b/scripts/apex/illustrateSimpleLogger.output.txt @@ -1,105 +1,153 @@ -02:51:00.791 (791678386)|EXECUTION_STARTED -02:51:00.791 (791694273)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex -02:51:00.791 (792377345)|USER_DEBUG|[3]|DEBUG|Simple log messages -02:51:00.791 (792401485)|USER_DEBUG|[4]|DEBUG| -02:51:01.935 (1935209042)|USER_DEBUG|[67]|INFO|This is an info message -02:51:01.935 (1935558809)|USER_DEBUG|[67]|WARN|This is a warning message -02:51:01.935 (1935812015)|USER_DEBUG|[67]|ERROR|This is an error message -02:51:01.935 (1935846467)|USER_DEBUG|[9]|DEBUG| -02:51:01.935 (1935862137)|USER_DEBUG|[10]|DEBUG|Log messages with a related SObject -02:51:01.935 (1935872814)|USER_DEBUG|[11]|DEBUG| -02:51:01.935 (1936189302)|USER_DEBUG|[67]|INFO|On 0032D00000WOOuxQAH: This is an info message -02:51:01.935 (1936443191)|USER_DEBUG|[67]|WARN|On 0032D00000WOOuxQAH: This is a warning message -02:51:01.935 (1936854864)|USER_DEBUG|[67]|ERROR|On 0032D00000WOOuxQAH: This is an error message -02:51:01.935 (1936905300)|USER_DEBUG|[16]|DEBUG| -02:51:01.935 (1936932495)|USER_DEBUG|[17]|DEBUG|Log of DML Exception with an Id -02:51:01.935 (1936951327)|USER_DEBUG|[18]|DEBUG| -02:51:01.935 (1953554596)|EXCEPTION_THROWN|[21]|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuxQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] -02:51:01.935 (1964267890)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (1964538318)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.DmlException to Datetime -02:51:01.935 (1965044400)|USER_DEBUG|[67]|ERROR|System.DmlException on 0032D00000WOOuxQAH: Update failed. First exception on row 0 with id 0032D00000WOOuxQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] -02:51:01.935 (1965268393)|USER_DEBUG|[67]|ERROR|System.DmlException.stackTrace: AnonymousBlock: line 21, column 1 -02:51:01.935 (1965316407)|USER_DEBUG|[28]|DEBUG| -02:51:01.935 (1965339303)|USER_DEBUG|[29]|DEBUG|Log of DML Exceptionm, handled with Exception with an Id -02:51:01.935 (1965356877)|USER_DEBUG|[30]|DEBUG| -02:51:01.935 (1972980002)|EXCEPTION_THROWN|[33]|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuxQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] -02:51:01.935 (1974428727)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (1974469663)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.DmlException to Datetime -02:51:01.935 (1974703407)|USER_DEBUG|[67]|ERROR|System.DmlException on 0032D00000WOOuxQAH: Update failed. First exception on row 0 with id 0032D00000WOOuxQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] -02:51:01.935 (1974772660)|USER_DEBUG|[67]|ERROR|System.DmlException.stackTrace: AnonymousBlock: line 33, column 1 -02:51:01.935 (1985162537)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (1985231110)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.DmlException to Datetime -02:51:01.935 (1985510402)|USER_DEBUG|[67]|ERROR|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuxQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] -02:51:01.935 (1985632539)|USER_DEBUG|[67]|ERROR|System.DmlException.stackTrace: AnonymousBlock: line 33, column 1 -02:51:01.935 (1985684026)|USER_DEBUG|[40]|DEBUG| -02:51:01.935 (1985711709)|USER_DEBUG|[41]|DEBUG|Log of DML Exception without an Id -02:51:01.935 (1985728986)|USER_DEBUG|[42]|DEBUG| -02:51:01.935 (2015827389)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector -02:51:01.935 (2186162000)|CODE_UNIT_FINISHED|DuplicateDetector -02:51:01.935 (2188225501)|EXCEPTION_THROWN|[45]|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] -02:51:01.935 (2189360275)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2189411859)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.DmlException to Datetime -02:51:01.935 (2189688138)|USER_DEBUG|[67]|ERROR|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] -02:51:01.935 (2189792264)|USER_DEBUG|[67]|ERROR|System.DmlException.stackTrace: AnonymousBlock: line 45, column 1 -02:51:01.935 (2190405508)|USER_DEBUG|[52]|DEBUG| -02:51:01.935 (2190427591)|USER_DEBUG|[53]|DEBUG|Log of DML Exception as Exception without an Id -02:51:01.935 (2190438543)|USER_DEBUG|[54]|DEBUG| -02:51:01.935 (2192472306)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector -02:51:01.935 (2209035541)|CODE_UNIT_FINISHED|DuplicateDetector -02:51:01.935 (2210562454)|EXCEPTION_THROWN|[57]|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] -02:51:01.935 (2211534916)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2211571908)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.DmlException to Datetime -02:51:01.935 (2211740656)|USER_DEBUG|[67]|ERROR|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] -02:51:01.935 (2211814622)|USER_DEBUG|[67]|ERROR|System.DmlException.stackTrace: AnonymousBlock: line 57, column 1 -02:51:01.935 (2212143632)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2212176697)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.DmlException to Datetime -02:51:01.935 (2212325013)|USER_DEBUG|[67]|ERROR|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] -02:51:01.935 (2212413099)|USER_DEBUG|[67]|ERROR|System.DmlException.stackTrace: AnonymousBlock: line 57, column 1 -02:51:01.935 (2212462478)|USER_DEBUG|[64]|DEBUG| -02:51:01.935 (2212487261)|USER_DEBUG|[65]|DEBUG|Log of System Exception without an Id -02:51:01.935 (2212506239)|USER_DEBUG|[66]|DEBUG| -02:51:01.935 (2212939746)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2212964227)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.ListException to Datetime -02:51:01.935 (2213063462)|USER_DEBUG|[67]|ERROR|System.ListException: List index out of bounds: 1 -02:51:01.935 (2213127893)|USER_DEBUG|[67]|ERROR|System.ListException.stackTrace: AnonymousBlock: line 69, column 1 -02:51:01.935 (2213154598)|USER_DEBUG|[76]|DEBUG| -02:51:01.935 (2213169184)|USER_DEBUG|[77]|DEBUG|Log of System Exception with an Id -02:51:01.935 (2213180086)|USER_DEBUG|[78]|DEBUG| -02:51:01.935 (2213574398)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2213599086)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type System.ListException to Datetime -02:51:01.935 (2213728002)|USER_DEBUG|[67]|ERROR|System.ListException on 0032D00000WOOuxQAH: List index out of bounds: 1 -02:51:01.935 (2213796224)|USER_DEBUG|[67]|ERROR|System.ListException.stackTrace: AnonymousBlock: line 81, column 1 -02:51:01.935 (2213833219)|USER_DEBUG|[88]|DEBUG| -02:51:01.935 (2213854295)|USER_DEBUG|[89]|DEBUG|Log of Ortoo Exception -02:51:01.935 (2213870070)|USER_DEBUG|[90]|DEBUG| -02:51:01.935 (2268644921)|EXCEPTION_THROWN|[118]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception -02:51:01.935 (2268714664)|EXCEPTION_THROWN|[94]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception -02:51:01.935 (2269353565)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2269407229)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type ortoo_qra.Exceptions.DeveloperException to Datetime -02:51:01.935 (2269652077)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345): This is a developer exception -02:51:01.935 (2270475427)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).context: id = 0032D00000WOOuxQAH @ OrtooExceptionThrower.throwException on Line: 120, Column 1 -02:51:01.935 (2270774457)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).context: otherThing = thingvalue @ OrtooExceptionThrower.throwException on Line: 121, Column 1 -02:51:01.935 (2271130489)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).messageDetail: LastName => "The last name went wrong" on Contact:{LastName=thingthatwentwrong} -02:51:01.935 (2271211562)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).stackTrace: Class.OrtooExceptionThrower.throwException: line 118, column 1 +04:39:01.130 (1130102616)|EXECUTION_STARTED +04:39:01.130 (1130119517)|CODE_UNIT_STARTED|[EXTERNAL]|execute_anonymous_apex +04:39:01.130 (1131094497)|USER_DEBUG|[8]|DEBUG|Simple log messages +04:39:01.130 (1131143797)|USER_DEBUG|[9]|DEBUG| +04:39:01.130 (1941858446)|USER_DEBUG|[184]|INFO|This is an info message +04:39:01.130 (1942810027)|USER_DEBUG|[184]|WARN|This is a warning message +04:39:01.130 (1943548865)|USER_DEBUG|[184]|ERROR|This is an error message +04:39:01.130 (1943588614)|USER_DEBUG|[14]|DEBUG| +04:39:01.130 (1943605004)|USER_DEBUG|[15]|DEBUG|Log messages with a related SObject +04:39:01.130 (1943615817)|USER_DEBUG|[16]|DEBUG| +04:39:01.130 (1944431805)|USER_DEBUG|[184]|INFO|On 0032D00000WOOuwQAH: This is an info message +04:39:01.130 (1945217503)|USER_DEBUG|[184]|WARN|On 0032D00000WOOuwQAH: This is a warning message +04:39:01.130 (1945992545)|USER_DEBUG|[184]|ERROR|On 0032D00000WOOuwQAH: This is an error message +04:39:01.130 (1946027662)|USER_DEBUG|[21]|DEBUG| +04:39:01.130 (1946043671)|USER_DEBUG|[22]|DEBUG|Log of DML Exception with an Id +04:39:01.130 (1946054323)|USER_DEBUG|[23]|DEBUG| +04:39:01.130 (1960347522)|EXCEPTION_THROWN|[26]|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuwQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] +04:39:01.130 (1974251517)|USER_DEBUG|[184]|ERROR|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuwQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] + +Row details: +0 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuwQAH - invalid cross reference id + +Stack Trace: +AnonymousBlock: line 26, column 1 +04:39:01.130 (1974304471)|USER_DEBUG|[33]|DEBUG| +04:39:01.130 (1974319139)|USER_DEBUG|[34]|DEBUG|Log of DML Exceptionm, handled with Exception with an Id +04:39:01.130 (1974329312)|USER_DEBUG|[35]|DEBUG| +04:39:01.130 (1986673238)|EXCEPTION_THROWN|[38]|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuwQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] +04:39:01.130 (1988620794)|USER_DEBUG|[184]|ERROR|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuwQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] + +Row details: +0 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuwQAH - invalid cross reference id +1 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuxQAH - invalid cross reference id +2 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuyQAH - invalid cross reference id + +Stack Trace: +AnonymousBlock: line 38, column 1 +04:39:01.130 (1988665722)|USER_DEBUG|[49]|DEBUG| +04:39:01.130 (1988685295)|USER_DEBUG|[50]|DEBUG|Log of DML Exception without an Id +04:39:01.130 (1988695577)|USER_DEBUG|[51]|DEBUG| +04:39:01.130 (2015631061)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector +04:39:01.130 (2070367888)|CODE_UNIT_FINISHED|DuplicateDetector +04:39:01.130 (2072487811)|EXCEPTION_THROWN|[54]|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] +04:39:01.130 (2075225183)|USER_DEBUG|[184]|ERROR|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] + +Row details: +0 - REQUIRED_FIELD_MISSING: Required fields are missing: [LastName] +1 - REQUIRED_FIELD_MISSING: Required fields are missing: [LastName] +2 - REQUIRED_FIELD_MISSING: Required fields are missing: [LastName] + +Stack Trace: +AnonymousBlock: line 54, column 1 +04:39:01.130 (2075273315)|USER_DEBUG|[65]|DEBUG| +04:39:01.130 (2075290167)|USER_DEBUG|[66]|DEBUG|Log of DML Exception as Exception without an Id +04:39:01.130 (2075300459)|USER_DEBUG|[67]|DEBUG| +04:39:01.130 (2077385052)|CODE_UNIT_STARTED|[EXTERNAL]|DuplicateDetector +04:39:01.130 (2094112824)|CODE_UNIT_FINISHED|DuplicateDetector +04:39:01.130 (2095659348)|EXCEPTION_THROWN|[70]|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] +04:39:01.130 (2098181779)|USER_DEBUG|[184]|ERROR|System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [LastName]: [LastName] + +Row details: +0 - REQUIRED_FIELD_MISSING: Required fields are missing: [LastName] + +Stack Trace: +AnonymousBlock: line 70, column 1 +04:39:01.130 (2098233105)|USER_DEBUG|[77]|DEBUG| +04:39:01.130 (2098251043)|USER_DEBUG|[78]|DEBUG|Log of System Exception without an Id +04:39:01.130 (2098261706)|USER_DEBUG|[79]|DEBUG| +04:39:01.130 (2099651235)|USER_DEBUG|[184]|ERROR|System.ListException: List index out of bounds: 1 + +Stack Trace: +AnonymousBlock: line 82, column 1 +04:39:01.130 (2099685902)|USER_DEBUG|[89]|DEBUG| +04:39:01.130 (2099700888)|USER_DEBUG|[90]|DEBUG|Log of System Exception with an Id +04:39:01.130 (2099711076)|USER_DEBUG|[91]|DEBUG| +04:39:01.130 (2100758938)|USER_DEBUG|[184]|ERROR|System.ListException: List index out of bounds: 1 +Against Id: 0032D00000WOOuwQAH + +Stack Trace: AnonymousBlock: line 94, column 1 -AnonymousBlock: line 94, column 1 -02:51:01.935 (2271249740)|USER_DEBUG|[101]|DEBUG| -02:51:01.935 (2271263621)|USER_DEBUG|[102]|DEBUG|Log of Ortoo Exception as Exception -02:51:01.935 (2271274825)|USER_DEBUG|[103]|DEBUG| -02:51:01.935 (2272311191)|EXCEPTION_THROWN|[118]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception -02:51:01.935 (2272333244)|EXCEPTION_THROWN|[107]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception -02:51:01.935 (2272678717)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2272712012)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type ortoo_qra.Exceptions.DeveloperException to Datetime -02:51:01.935 (2272818147)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345): This is a developer exception -02:51:01.935 (2273056014)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).context: id = 0032D00000WOOuxQAH @ OrtooExceptionThrower.throwException on Line: 120, Column 1 -02:51:01.935 (2273270569)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).context: otherThing = thingvalue @ OrtooExceptionThrower.throwException on Line: 121, Column 1 -02:51:01.935 (2273401941)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).messageDetail: LastName => "The last name went wrong" on Contact:{LastName=thingthatwentwrong} -02:51:01.935 (2273456114)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345).stackTrace: Class.OrtooExceptionThrower.throwException: line 118, column 1 -AnonymousBlock: line 107, column 1 +04:39:01.130 (2100794476)|USER_DEBUG|[101]|DEBUG| +04:39:01.130 (2100810023)|USER_DEBUG|[102]|DEBUG|Log of Ortoo Exception +04:39:01.130 (2100820945)|USER_DEBUG|[103]|DEBUG| +04:39:02.159 (2159616790)|EXCEPTION_THROWN|[165]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception +04:39:02.159 (2159659000)|EXCEPTION_THROWN|[107]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception +04:39:02.159 (2162012382)|USER_DEBUG|[184]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345): This is a developer exception + +Context: +id = 0032D00000WOOuwQAH @ OrtooExceptionThrower.throwException on Line: 167, Column 1 +otherThing = thingvalue @ OrtooExceptionThrower.throwException on Line: 168, Column 1 + +Message Detail: +LastName => "The last name went wrong" on Contact:{LastName=thingthatwentwrong} + + +Stack Trace: +Class.OrtooExceptionThrower.throwException: line 165, column 1 AnonymousBlock: line 107, column 1 -02:51:01.935 (2273656621)|USER_DEBUG|[22]|DEBUG|If "System.TypeException: Invalid conversion ... to DateTime" is seen in the logs, this may be due to an attempt to find the class name of an object -02:51:01.935 (2273688189)|EXCEPTION_THROWN|[23]|System.TypeException: Invalid conversion from runtime type ortoo_qra.Exceptions.DeveloperException to Datetime -02:51:01.935 (2273777899)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException: This is a developer exception -02:51:01.935 (2273827394)|USER_DEBUG|[67]|ERROR|ortoo_qra.Exceptions.DeveloperException.stackTrace: Class.OrtooExceptionThrower.throwException: line 118, column 1 AnonymousBlock: line 107, column 1 -AnonymousBlock: line 107, column 1 \ No newline at end of file +04:39:02.159 (2162077140)|USER_DEBUG|[114]|DEBUG| +04:39:02.159 (2162105301)|USER_DEBUG|[115]|DEBUG|Log of Ortoo Exception as Exception +04:39:02.159 (2162125754)|USER_DEBUG|[116]|DEBUG| +04:39:02.159 (2163391287)|EXCEPTION_THROWN|[165]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception +04:39:02.159 (2163417763)|EXCEPTION_THROWN|[120]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception +04:39:02.159 (2165576653)|USER_DEBUG|[184]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345): This is a developer exception + +Context: +id = 0032D00000WOOuwQAH @ OrtooExceptionThrower.throwException on Line: 167, Column 1 +otherThing = thingvalue @ OrtooExceptionThrower.throwException on Line: 168, Column 1 + +Message Detail: +LastName => "The last name went wrong" on Contact:{LastName=thingthatwentwrong} + + +Stack Trace: +Class.OrtooExceptionThrower.throwException: line 165, column 1 +AnonymousBlock: line 120, column 1 +AnonymousBlock: line 120, column 1 +04:39:02.159 (2165634652)|USER_DEBUG|[128]|DEBUG| +04:39:02.159 (2165662056)|USER_DEBUG|[129]|DEBUG|Log of Ortoo Exception with causedBy +04:39:02.159 (2165682137)|USER_DEBUG|[130]|DEBUG| +04:39:02.159 (2181088613)|EXCEPTION_THROWN|[148]|System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuwQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] +04:39:02.159 (2184099195)|EXCEPTION_THROWN|[176]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception +04:39:02.159 (2184147183)|EXCEPTION_THROWN|[134]|ortoo_qra.Exceptions.DeveloperException: This is a developer exception +04:39:02.159 (2187980535)|USER_DEBUG|[184]|ERROR|ortoo_qra.Exceptions.DeveloperException (DEV-12345): This is a developer exception + +Context: +id = 0032D00000WOOuwQAH @ OrtooExceptionThrower.throwExceptionWithCausedBy on Line: 178, Column 1 +otherThing = thingvalue @ OrtooExceptionThrower.throwExceptionWithCausedBy on Line: 179, Column 1 + +Message Detail: +LastName => "The last name went wrong" on Contact:{LastName=thingthatwentwrong} + + +Stack Trace: +Class.OrtooExceptionThrower.throwExceptionWithCausedBy: line 176, column 1 +AnonymousBlock: line 134, column 1 +AnonymousBlock: line 134, column 1 + +Caused By: +System.DmlException: Update failed. First exception on row 0 with id 0032D00000WOOuwQAH; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross reference id: [] + +Row details: +0 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuwQAH - invalid cross reference id +1 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuxQAH - invalid cross reference id +2 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuyQAH - invalid cross reference id +3 - INVALID_CROSS_REFERENCE_KEY: Id = 0032D00000WOOuzQAH - invalid cross reference id + +Stack Trace: +Class.OrtooExceptionThrower.__sfdc_dmlExceptionThrown: line 148, column 1 +Class.OrtooExceptionThrower.throwExceptionWithCausedBy: line 176, column 1 +AnonymousBlock: line 134, column 1 +AnonymousBlock: line 134, column 1 \ No newline at end of file