Skip to content

Commit

Permalink
feat: enable access to metrics for HTTP streams (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
ianbotsf committed Jan 5, 2024
1 parent 36f2090 commit 26917f2
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 12 deletions.
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"
]
}
29 changes: 29 additions & 0 deletions aws-crt-kotlin/api/android/aws-crt-kotlin.api
Original file line number Diff line number Diff line change
Expand Up @@ -634,14 +634,43 @@ public abstract interface class aws/sdk/kotlin/crt/http/HttpStream : aws/sdk/kot
public abstract fun writeChunk ([BZ)V
}

public final class aws/sdk/kotlin/crt/http/HttpStreamMetrics {
public fun <init> (JJJJJJI)V
public final fun component1 ()J
public final fun component2 ()J
public final fun component3 ()J
public final fun component4 ()J
public final fun component5 ()J
public final fun component6 ()J
public final fun component7 ()I
public final fun copy (JJJJJJI)Laws/sdk/kotlin/crt/http/HttpStreamMetrics;
public static synthetic fun copy$default (Laws/sdk/kotlin/crt/http/HttpStreamMetrics;JJJJJJIILjava/lang/Object;)Laws/sdk/kotlin/crt/http/HttpStreamMetrics;
public fun equals (Ljava/lang/Object;)Z
public final fun getReceiveEndTimestampNs ()J
public final fun getReceiveStartTimestampNs ()J
public final fun getReceivingDurationNs ()J
public final fun getSendEndTimestampNs ()J
public final fun getSendStartTimestampNs ()J
public final fun getSendingDurationNs ()J
public final fun getStreamId ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/crt/http/HttpStreamMetricsJVMKt {
public static final fun toKotlin (Lsoftware/amazon/awssdk/crt/http/HttpStreamMetrics;)Laws/sdk/kotlin/crt/http/HttpStreamMetrics;
}

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
29 changes: 29 additions & 0 deletions aws-crt-kotlin/api/jvm/aws-crt-kotlin.api
Original file line number Diff line number Diff line change
Expand Up @@ -634,14 +634,43 @@ public abstract interface class aws/sdk/kotlin/crt/http/HttpStream : aws/sdk/kot
public abstract fun writeChunk ([BZ)V
}

public final class aws/sdk/kotlin/crt/http/HttpStreamMetrics {
public fun <init> (JJJJJJI)V
public final fun component1 ()J
public final fun component2 ()J
public final fun component3 ()J
public final fun component4 ()J
public final fun component5 ()J
public final fun component6 ()J
public final fun component7 ()I
public final fun copy (JJJJJJI)Laws/sdk/kotlin/crt/http/HttpStreamMetrics;
public static synthetic fun copy$default (Laws/sdk/kotlin/crt/http/HttpStreamMetrics;JJJJJJIILjava/lang/Object;)Laws/sdk/kotlin/crt/http/HttpStreamMetrics;
public fun equals (Ljava/lang/Object;)Z
public final fun getReceiveEndTimestampNs ()J
public final fun getReceiveStartTimestampNs ()J
public final fun getReceivingDurationNs ()J
public final fun getSendEndTimestampNs ()J
public final fun getSendStartTimestampNs ()J
public final fun getSendingDurationNs ()J
public final fun getStreamId ()I
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class aws/sdk/kotlin/crt/http/HttpStreamMetricsJVMKt {
public static final fun toKotlin (Lsoftware/amazon/awssdk/crt/http/HttpStreamMetrics;)Laws/sdk/kotlin/crt/http/HttpStreamMetrics;
}

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()
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ kotlin-version = "1.9.21"
aws-kotlin-repo-tools-version = "0.3.2"

# libs
crt-java-version = "0.29.1"
crt-java-version = "0.29.6"
coroutines-version = "1.7.3"

# testing
Expand Down

0 comments on commit 26917f2

Please sign in to comment.