Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable access to metrics for HTTP streams #86

Merged
merged 2 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changes/cfc58da7-d2c6-47d7-a40e-72893b49bca7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "cfc58da7-d2c6-47d7-a40e-72893b49bca7",
"type": "feature",
"description": "Enable access to metrics for HTTP streams",
"issues": [
"https://github.com/awslabs/smithy-kotlin/issues/893"
]
}
2 changes: 2 additions & 0 deletions aws-crt-kotlin/api/android/aws-crt-kotlin.api
Original file line number Diff line number Diff line change
Expand Up @@ -635,13 +635,15 @@ public abstract interface class aws/sdk/kotlin/crt/http/HttpStream : aws/sdk/kot
}

public abstract interface class aws/sdk/kotlin/crt/http/HttpStreamResponseHandler {
public abstract fun onMetrics (Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/http/HttpStreamMetrics;)V
public abstract fun onResponseBody (Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/io/Buffer;)I
public abstract fun onResponseComplete (Laws/sdk/kotlin/crt/http/HttpStream;I)V
public abstract fun onResponseHeaders (Laws/sdk/kotlin/crt/http/HttpStream;IILjava/util/List;)V
public abstract fun onResponseHeadersDone (Laws/sdk/kotlin/crt/http/HttpStream;I)V
}

public final class aws/sdk/kotlin/crt/http/HttpStreamResponseHandler$DefaultImpls {
public static fun onMetrics (Laws/sdk/kotlin/crt/http/HttpStreamResponseHandler;Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/http/HttpStreamMetrics;)V
public static fun onResponseBody (Laws/sdk/kotlin/crt/http/HttpStreamResponseHandler;Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/io/Buffer;)I
public static fun onResponseHeadersDone (Laws/sdk/kotlin/crt/http/HttpStreamResponseHandler;Laws/sdk/kotlin/crt/http/HttpStream;I)V
}
Expand Down
2 changes: 2 additions & 0 deletions aws-crt-kotlin/api/jvm/aws-crt-kotlin.api
Original file line number Diff line number Diff line change
Expand Up @@ -635,13 +635,15 @@ public abstract interface class aws/sdk/kotlin/crt/http/HttpStream : aws/sdk/kot
}

public abstract interface class aws/sdk/kotlin/crt/http/HttpStreamResponseHandler {
public abstract fun onMetrics (Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/http/HttpStreamMetrics;)V
public abstract fun onResponseBody (Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/io/Buffer;)I
public abstract fun onResponseComplete (Laws/sdk/kotlin/crt/http/HttpStream;I)V
public abstract fun onResponseHeaders (Laws/sdk/kotlin/crt/http/HttpStream;IILjava/util/List;)V
public abstract fun onResponseHeadersDone (Laws/sdk/kotlin/crt/http/HttpStream;I)V
}

public final class aws/sdk/kotlin/crt/http/HttpStreamResponseHandler$DefaultImpls {
public static fun onMetrics (Laws/sdk/kotlin/crt/http/HttpStreamResponseHandler;Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/http/HttpStreamMetrics;)V
public static fun onResponseBody (Laws/sdk/kotlin/crt/http/HttpStreamResponseHandler;Laws/sdk/kotlin/crt/http/HttpStream;Laws/sdk/kotlin/crt/io/Buffer;)I
public static fun onResponseHeadersDone (Laws/sdk/kotlin/crt/http/HttpStreamResponseHandler;Laws/sdk/kotlin/crt/http/HttpStream;I)V
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package aws.sdk.kotlin.crt.http

public data class HttpStreamMetrics(
val sendStartTimestampNs: Long,
val sendEndTimestampNs: Long,
val sendingDurationNs: Long,
val receiveStartTimestampNs: Long,
val receiveEndTimestampNs: Long,
val receivingDurationNs: Long,
val streamId: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,15 @@ public interface HttpStreamResponseHandler {
// window size through `Stream.incrementWindow()`?
bodyBytesIn.len

/**
* Called right before stream is complete, whether successful or unsuccessful.
* @param stream The HTTP stream to which the metrics apply
* @param metrics The [HttpStreamMetrics] containing metrics for the given stream
*/
public fun onMetrics(stream: HttpStream, metrics: HttpStreamMetrics) {
/* Optional callback, nothing to do by default */
}

/**
* Called from Native when the Response has completed.
* @param stream completed stream
Expand Down
29 changes: 18 additions & 11 deletions aws-crt-kotlin/jvm/src/aws/sdk/kotlin/crt/http/HttpRequestUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,63 @@ package aws.sdk.kotlin.crt.http
import aws.sdk.kotlin.crt.io.MutableBuffer
import aws.sdk.kotlin.crt.io.byteArrayBuffer
import java.nio.ByteBuffer
import software.amazon.awssdk.crt.http.HttpHeader as HttpHeaderJni
import software.amazon.awssdk.crt.http.HttpRequest as HttpRequestJni
import software.amazon.awssdk.crt.http.HttpRequestBodyStream as HttpRequestBodyStreamJni
import software.amazon.awssdk.crt.http.HttpStream as HttpStreamJni
import software.amazon.awssdk.crt.http.HttpStreamMetrics as HttpStreamMetricsJni
import software.amazon.awssdk.crt.http.HttpStreamResponseHandler as HttpStreamResponseHandlerJni

/**
* Convert the KMP version of [HttpRequest] into the JNI equivalent
*/
internal fun HttpRequest.into(): HttpRequestJni {
val jniHeaders = headers.entries()
.map { entry ->
entry.value.map {
software.amazon.awssdk.crt.http.HttpHeader(entry.key, it)
}
entry.value.map { HttpHeaderJni(entry.key, it) }
}
.flatten()
.toTypedArray()

val bodyStream = body?.let { JniRequestBodyStream(it) }
return software.amazon.awssdk.crt.http.HttpRequest(method, encodedPath, jniHeaders, bodyStream)
return HttpRequestJni(method, encodedPath, jniHeaders, bodyStream)
}

internal fun HttpStreamResponseHandler.asJniStreamResponseHandler(): software.amazon.awssdk.crt.http.HttpStreamResponseHandler {
internal fun HttpStreamResponseHandler.asJniStreamResponseHandler(): HttpStreamResponseHandlerJni {
val handler = this
return object : software.amazon.awssdk.crt.http.HttpStreamResponseHandler {
return object : HttpStreamResponseHandlerJni {
override fun onResponseHeaders(
stream: software.amazon.awssdk.crt.http.HttpStream,
stream: HttpStreamJni,
statusCode: Int,
blockType: Int,
headers: Array<out software.amazon.awssdk.crt.http.HttpHeader>?,
headers: Array<out HttpHeaderJni>?,
) {
val ktHeaders = headers?.map { HttpHeader(it.name, it.value) }
val ktStream = HttpStreamJVM(stream)
handler.onResponseHeaders(ktStream, statusCode, blockType, ktHeaders)
}

override fun onResponseHeadersDone(stream: software.amazon.awssdk.crt.http.HttpStream, blockType: Int) {
override fun onResponseHeadersDone(stream: HttpStreamJni, blockType: Int) {
val ktStream = HttpStreamJVM(stream)
handler.onResponseHeadersDone(ktStream, blockType)
}

override fun onResponseBody(stream: software.amazon.awssdk.crt.http.HttpStream, bodyBytesIn: ByteArray?): Int {
override fun onResponseBody(stream: HttpStreamJni, bodyBytesIn: ByteArray?): Int {
if (bodyBytesIn == null) return 0
val ktStream = HttpStreamJVM(stream)
val buffer = byteArrayBuffer(bodyBytesIn)
return handler.onResponseBody(ktStream, buffer)
}

override fun onResponseComplete(stream: software.amazon.awssdk.crt.http.HttpStream, errorCode: Int) {
override fun onResponseComplete(stream: HttpStreamJni, errorCode: Int) {
val ktStream = HttpStreamJVM(stream)
handler.onResponseComplete(ktStream, errorCode)
}

override fun onMetrics(stream: HttpStreamJni, metrics: HttpStreamMetricsJni) {
val ktStream = HttpStreamJVM(stream)
handler.onMetrics(ktStream, metrics.toKotlin())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
package aws.sdk.kotlin.crt.http

/**
* Convert a CRT JNI metrics object into a Kotlin-native one
*/
public fun software.amazon.awssdk.crt.http.HttpStreamMetrics.toKotlin(): HttpStreamMetrics =
HttpStreamMetrics(
sendStartTimestampNs = this.sendStartTimestampNs,
sendEndTimestampNs = this.sendEndTimestampNs,
sendingDurationNs = this.sendingDurationNs,
receiveStartTimestampNs = this.receiveStartTimestampNs,
receiveEndTimestampNs = this.receiveEndTimestampNs,
receivingDurationNs = this.receivingDurationNs,
streamId = this.streamId,
)
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
buildscript {
repositories {
mavenCentral()
mavenLocal()
}

dependencies {
Expand Down
Loading