Exception
    Exception that carries log fields, to provide structured logging context when the exception is logged. When passing a cause exception to one of the methods on Logger, it will check if the given exception is an instance of this class, and if it is, these fields will be added to the log.
Use the field/rawJsonField functions to construct log fields.
This class is useful when you are throwing an exception from somewhere down in the stack, but do logging further up the stack, and you have structured data that you want to attach to the exception log. In this case, one may typically resort to string concatenation, but this class allows you to have the benefits of structured logging for exceptions as well.
You can extend this class for your own custom exception types. If you'd rather implement an interface than extend a class, use HasLoggingContext.
Example
import dev.hermannm.devlog.ExceptionWithLoggingContext
import dev.hermannm.devlog.field
import dev.hermannm.devlog.getLogger
private val log = getLogger()
fun example(event: OrderUpdateEvent) {
  try {
    processOrderUpdate(event)
  } catch (e: Exception) {
    log.error(e) { "Failed to process order update event" }
  }
}
fun processOrderUpdate(event: OrderUpdateEvent) {
  withLoggingContext(field("event", event)) {
    val order = getOrder(event.orderId)
    if (!order.canBeUpdated()) {
      throw ExceptionWithLoggingContext(
          "Received update event for finalized order",
          field("order", order),
      )
    }
  }
}The log.error would then give the following log output (using logstash-logback-encoder), with both the order field from the exception and the event field from the logging context:
{
  "message": "Failed to process order update event",
  "stack_trace": "...ExceptionWithLoggingContext: Received update event for finalized order...",
  "order": { ... },
  "event": { ... },
  // ...timestamp etc.
}Constructors
ExceptionWithLoggingContext provides 4 constructor overloads:
- (message: String?, logFields: Collection<LogField>, cause: Throwable?)
- Primary constructor taking an exception message, a collection of log fields and an optional cause exception 
- (message: String?, vararg logFields: LogField, cause: Throwable?)
- Takes log fields as varargs, so you don't have to wrap them in a list 
- To pass - cause, use a named argument
- (logFields: Collection<LogField>, cause: Throwable?)
- Defaults - messageto- cause.message. This lets you:
- Wrap a cause exception with log fields, and use the cause exception's message 
- Extend - ExceptionWithLoggingContextand override- message, without having to pass it through the constructor
- (vararg logFields: LogField, cause: Throwable?)
- Combines the two previous constructors, to let you extend - ExceptionWithLoggingContextand override- messagewhile also passing log fields as varargs