diff --git a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt index e623c4e67..152f8d119 100644 --- a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt +++ b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt @@ -468,16 +468,34 @@ internal class LoggerImpl( internal fun extractFields( fields: Map?, throwable: Throwable?, - ): InternalFieldsMap? = - buildMap { - fields?.let { - putAll(it) - } - throwable?.let { - put("_error", it.javaClass.name.orEmpty()) - put("_error_details", it.message.orEmpty()) + ): InternalFieldsMap { + // Maintainer note: keep initialCapacity in sync with the code adding fields to the map. + val initialCapacity = (fields?.size ?: 0) + (throwable?.let { 2 } ?: 0) + if (initialCapacity == 0) { + // If throwable is null AND fields is either null or empty, no need to create a HashMap. + return emptyMap() + } + // Create a hashmap of the exact target size and with the right final value type, instead + // of creating a temporary map and then converting it with Map.toFields() + val extractedFields = HashMap(initialCapacity) + fields?.let { + for ((key, value) in it) { + // Java interop: clients could have passed in null keys or values. + @Suppress("SENSELESS_COMPARISON") + if (key != null && value != null) { + extractedFields[key] = value.toFieldValue() + } } - }.toFields() + } + throwable?.let { + extractedFields["_error"] = + it.javaClass.name + .orEmpty() + .toFieldValue() + extractedFields["_error_details"] = it.message.orEmpty().toFieldValue() + } + return extractedFields + } internal fun flush(blocking: Boolean) { CaptureJniLibrary.flush(this.loggerId, blocking) diff --git a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/providers/FieldProvider.kt b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/providers/FieldProvider.kt index 701fef62e..9ea10f3b9 100644 --- a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/providers/FieldProvider.kt +++ b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/providers/FieldProvider.kt @@ -119,7 +119,7 @@ internal fun ByteArray.toFieldValue() = */ @Suppress("SENSELESS_COMPARISON") internal fun Map?.toFields(): Map { - if (this == null) return emptyMap() + if (isNullOrEmpty()) return emptyMap() val result = HashMap(size) for ((key, value) in this) {