diff --git a/exporters-otlp/src/commonMain/kotlin/io/opentelemetry/kotlin/export/OtlpClient.kt b/exporters-otlp/src/commonMain/kotlin/io/opentelemetry/kotlin/export/OtlpClient.kt index fb8c1829..e607e267 100644 --- a/exporters-otlp/src/commonMain/kotlin/io/opentelemetry/kotlin/export/OtlpClient.kt +++ b/exporters-otlp/src/commonMain/kotlin/io/opentelemetry/kotlin/export/OtlpClient.kt @@ -6,10 +6,13 @@ import io.ktor.client.plugins.compression.compress import io.ktor.client.request.header import io.ktor.client.request.post import io.ktor.client.request.setBody -import io.ktor.client.statement.bodyAsBytes +import io.ktor.client.statement.HttpResponse +import io.ktor.client.statement.bodyAsChannel import io.ktor.http.ContentType import io.ktor.http.HttpHeaders import io.ktor.http.contentType +import io.ktor.utils.io.readRemaining +import io.opentelemetry.kotlin.export.OtlpClient.Companion.MAX_ERROR_BODY_BYTES import io.opentelemetry.kotlin.export.OtlpResponse.ClientError import io.opentelemetry.kotlin.export.OtlpResponse.ServerError import io.opentelemetry.kotlin.export.OtlpResponse.Success @@ -20,13 +23,14 @@ import io.opentelemetry.kotlin.logging.model.ReadableLogRecord import io.opentelemetry.kotlin.tracing.data.SpanData import io.opentelemetry.kotlin.tracing.export.deserializeTraceRecordErrorMessage import io.opentelemetry.kotlin.tracing.export.toProtobufByteArray +import kotlinx.io.readByteArray internal class OtlpClient( private val baseUrl: String, private val httpClient: HttpClient = defaultHttpClient ) { - private val contentType = ContentType.Companion.parse("application/x-protobuf") + private val contentType = ContentType.parse("application/x-protobuf") private val userAgent = "OTel-OTLP-Exporter-Kotlin/${BuildKonfig.VERSION}" suspend fun exportLogs(telemetry: List): OtlpResponse = exportTelemetry( @@ -56,12 +60,22 @@ internal class OtlpClient( } when (val code = response.status.value) { 200 -> Success - in 400..499 -> ClientError(code, onError(response.bodyAsBytes())) - in 500..599 -> ServerError(code, onError(response.bodyAsBytes())) + in 400..499 -> ClientError(code, onError(response.boundedBodyBytes())) + in 500..599 -> ServerError(code, onError(response.boundedBodyBytes())) else -> Unknown } } catch (ignored: HttpRequestTimeoutException) { Unknown } } + + /** + * Reads at most [MAX_ERROR_BODY_BYTES] from the response body. + */ + private suspend fun HttpResponse.boundedBodyBytes(): ByteArray = + bodyAsChannel().readRemaining(MAX_ERROR_BODY_BYTES).readByteArray() + + private companion object { + const val MAX_ERROR_BODY_BYTES: Long = 4 * 1024 * 1024 + } }