Has Log Fields
Interface to allow you to attach log fields to exceptions. When passing a cause
exception to one of the methods on Logger, it will check if the given exception implements this interface, and if it does, these fields will be added to the log.
Use the field/rawJsonField functions to construct log fields.
This 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 interface allows you to have the benefits of structured logging for exceptions as well.
If you want to include log fields from withLoggingContext on the exception, you should instead throw or extend the ExceptionWithLogFields base class.
Example
import dev.hermannm.devlog.HasLogFields
import dev.hermannm.devlog.field
import dev.hermannm.devlog.getLogger
private val log = getLogger()
fun example(order: Order) {
try {
updateOrder(order)
} catch (e: Exception) {
log.error(e) { "Failed to update order" }
}
}
fun updateOrder(order: Order) {
if (!order.canBeUpdated()) {
throw OrderUpdateException("Cannot update finalized order", order)
}
}
class OrderUpdateException(
override val message: String,
order: Order,
) : RuntimeException(), HasLogFields {
override val logFields = listOf(field("order", order))
}
The log.error
would then give the following log output (using logstash-logback-encoder
), with the order
log field from OrderUpdateException
attached:
{
"message": "Failed to update order",
"stack_trace": "...OrderUpdateException: Cannot update finalized order...",
"order": { ... },
// ...timestamp etc.
}