Skip to content

Commit

Permalink
Merge pull request #93 from NthPortal/use-preludes/PR
Browse files Browse the repository at this point in the history
Use `{Request,Response}Prelude` in builders
  • Loading branch information
NthPortal committed May 10, 2024
2 parents 25df94b + 23e4565 commit befd623
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ import cats.effect.kernel.Outcome
import cats.syntax.flatMap._
import org.http4s.Headers
import org.http4s.Request
import org.http4s.RequestPrelude
import org.http4s.Response
import org.http4s.ResponsePrelude
import org.http4s.client.Client
import org.http4s.client.RequestKey
import org.http4s.client.middleware.Retry
Expand Down Expand Up @@ -57,33 +59,35 @@ object ClientMiddleware {

/** The default configuration values for a client middleware builder. */
object Defaults {
val allowedRequestHeaders: Set[CIString] = TypedAttributes.Headers.defaultAllowedHeaders
val allowedResponseHeaders: Set[CIString] = TypedAttributes.Headers.defaultAllowedHeaders
def clientSpanName[F[_]]: Request[F] => String =
(req: Request[F]) => s"Http Client - ${req.method}"
def additionalRequestAttributes[F[_]]: Request[F] => immutable.Iterable[Attribute[_]] =
(_: Request[F]) => Nil
def additionalResponseAttributes[F[_]]: Response[F] => immutable.Iterable[Attribute[_]] =
(_: Response[F]) => Nil
val urlRedactor: UriRedactor = UriRedactor.OnlyRedactUserInfo
def allowedRequestHeaders: Set[CIString] =
TypedAttributes.Headers.defaultAllowedHeaders
def allowedResponseHeaders: Set[CIString] =
TypedAttributes.Headers.defaultAllowedHeaders
val clientSpanName: RequestPrelude => String =
req => s"Http Client - ${req.method}"
val additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]] =
_ => Nil
val additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]] =
_ => Nil
def urlRedactor: UriRedactor = UriRedactor.OnlyRedactUserInfo
}

/** A builder for client middlewares. */
final class ClientMiddlewareBuilder[F[_]: Tracer: Concurrent] private[ClientMiddleware] (
private val allowedRequestHeaders: Set[CIString],
private val allowedResponseHeaders: Set[CIString],
private val clientSpanName: Request[F] => String,
private val additionalRequestAttributes: Request[F] => immutable.Iterable[Attribute[_]],
private val additionalResponseAttributes: Response[F] => immutable.Iterable[Attribute[_]],
private val clientSpanName: RequestPrelude => String,
private val additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]],
private val additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]],
private val urlRedactor: UriRedactor,
) {
private def copy(
allowedRequestHeaders: Set[CIString] = this.allowedRequestHeaders,
allowedResponseHeaders: Set[CIString] = this.allowedResponseHeaders,
clientSpanName: Request[F] => String = this.clientSpanName,
additionalRequestAttributes: Request[F] => immutable.Iterable[Attribute[_]] =
clientSpanName: RequestPrelude => String = this.clientSpanName,
additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]] =
this.additionalRequestAttributes,
additionalResponseAttributes: Response[F] => immutable.Iterable[Attribute[_]] =
additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]] =
this.additionalResponseAttributes,
urlRedactor: UriRedactor = this.urlRedactor,
): ClientMiddlewareBuilder[F] =
Expand All @@ -105,22 +109,22 @@ object ClientMiddleware {
copy(allowedResponseHeaders = allowedHeaders)

/** Sets how to derive the name of a client span from a request. */
def withClientSpanName(clientSpanName: Request[F] => String): ClientMiddlewareBuilder[F] =
def withClientSpanName(clientSpanName: RequestPrelude => String): ClientMiddlewareBuilder[F] =
copy(clientSpanName = clientSpanName)

/** Sets how to derive additional `Attribute`s from a request to add to the
* client span.
*/
def withAdditionalRequestAttributes(
additionalRequestAttributes: Request[F] => immutable.Iterable[Attribute[_]]
additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]]
): ClientMiddlewareBuilder[F] =
copy(additionalRequestAttributes = additionalRequestAttributes)

/** Sets how to derive additional `Attribute`s from a response to add to the
* client span.
*/
def withAdditionalResponseAttributes(
additionalResponseAttributes: Response[F] => immutable.Iterable[Attribute[_]]
additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]]
): ClientMiddlewareBuilder[F] =
copy(additionalResponseAttributes = additionalResponseAttributes)

Expand All @@ -131,13 +135,14 @@ object ClientMiddleware {
/** @return the configured middleware */
def build: Client[F] => Client[F] = (client: Client[F]) =>
Client[F] { (req: Request[F]) => // Resource[F, Response[F]]

val reqPrelude = req.requestPrelude
val base =
request(req, allowedRequestHeaders, urlRedactor) ++ additionalRequestAttributes(req)
request(req, allowedRequestHeaders, urlRedactor) ++
additionalRequestAttributes(reqPrelude)
MonadCancelThrow[Resource[F, *]].uncancelable { poll =>
for {
res <- Tracer[F]
.spanBuilder(clientSpanName(req))
.spanBuilder(clientSpanName(reqPrelude))
.withSpanKind(SpanKind.Client)
.addAttributes(base)
.build
Expand All @@ -153,9 +158,8 @@ object ClientMiddleware {
Resource
.eval {
span.addAttributes(
response(resp, allowedResponseHeaders) ++ additionalResponseAttributes(
resp
)
response(resp, allowedResponseHeaders) ++
additionalResponseAttributes(resp.responsePrelude)
)
}
.mapK(trace)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import org.http4s.HttpRoutes
import org.http4s.Request
import org.http4s.RequestPrelude
import org.http4s.Response
import org.http4s.ResponsePrelude
import org.http4s.client.RequestKey
import org.http4s.headers.Host
import org.http4s.headers.`User-Agent`
Expand Down Expand Up @@ -57,40 +58,40 @@ object ServerMiddleware {

/** The default configuration values for a server middleware builder. */
object Defaults {
val allowedRequestHeaders: Set[CIString] = TypedAttributes.Headers.defaultAllowedHeaders
val allowedResponseHeaders: Set[CIString] = TypedAttributes.Headers.defaultAllowedHeaders
def routeClassifier[F[_]]: Request[F] => Option[String] =
(_: Request[F]) => None
def serverSpanName[F[_]]: Request[F] => String =
(req: Request[F]) => s"Http Server - ${req.method}"
def additionalRequestAttributes[F[_]]: Request[F] => immutable.Iterable[Attribute[_]] =
(_: Request[F]) => Nil
def additionalResponseAttributes[F[_]]: Response[F] => immutable.Iterable[Attribute[_]] =
(_: Response[F]) => Nil
val urlRedactor: UriRedactor = UriRedactor.OnlyRedactUserInfo
val shouldTrace: RequestPrelude => ShouldTrace =
(_: RequestPrelude) => ShouldTrace.Trace
def allowedRequestHeaders: Set[CIString] =
TypedAttributes.Headers.defaultAllowedHeaders
def allowedResponseHeaders: Set[CIString] =
TypedAttributes.Headers.defaultAllowedHeaders
val routeClassifier: RequestPrelude => Option[String] = _ => None
val serverSpanName: RequestPrelude => String =
req => s"Http Server - ${req.method}"
val additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]] =
_ => Nil
val additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]] =
_ => Nil
def urlRedactor: UriRedactor = UriRedactor.OnlyRedactUserInfo
val shouldTrace: RequestPrelude => ShouldTrace = _ => ShouldTrace.Trace
}

/** A builder for server middlewares. */
final class ServerMiddlewareBuilder[F[_]: Tracer: MonadCancelThrow] private[ServerMiddleware] (
allowedRequestHeaders: Set[CIString],
allowedResponseHeaders: Set[CIString],
routeClassifier: Request[F] => Option[String],
serverSpanName: Request[F] => String,
additionalRequestAttributes: Request[F] => immutable.Iterable[Attribute[_]],
additionalResponseAttributes: Response[F] => immutable.Iterable[Attribute[_]],
routeClassifier: RequestPrelude => Option[String],
serverSpanName: RequestPrelude => String,
additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]],
additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]],
urlRedactor: UriRedactor,
shouldTrace: RequestPrelude => ShouldTrace,
) {
private def copy(
allowedRequestHeaders: Set[CIString] = this.allowedRequestHeaders,
allowedResponseHeaders: Set[CIString] = this.allowedResponseHeaders,
routeClassifier: Request[F] => Option[String] = this.routeClassifier,
serverSpanName: Request[F] => String = this.serverSpanName,
additionalRequestAttributes: Request[F] => immutable.Iterable[Attribute[_]] =
routeClassifier: RequestPrelude => Option[String] = this.routeClassifier,
serverSpanName: RequestPrelude => String = this.serverSpanName,
additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]] =
this.additionalRequestAttributes,
additionalResponseAttributes: Response[F] => immutable.Iterable[Attribute[_]] =
additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]] =
this.additionalResponseAttributes,
urlRedactor: UriRedactor = this.urlRedactor,
shouldTrace: RequestPrelude => ShouldTrace = this.shouldTrace,
Expand Down Expand Up @@ -119,27 +120,27 @@ object ServerMiddleware {
* route could not be determined.
*/
def withRouteClassifier(
routeClassifier: Request[F] => Option[String]
routeClassifier: RequestPrelude => Option[String]
): ServerMiddlewareBuilder[F] =
copy(routeClassifier = routeClassifier)

/** Sets how to derive the name of a server span from a request. */
def withServerSpanName(serverSpanName: Request[F] => String): ServerMiddlewareBuilder[F] =
def withServerSpanName(serverSpanName: RequestPrelude => String): ServerMiddlewareBuilder[F] =
copy(serverSpanName = serverSpanName)

/** Sets how to derive additional `Attribute`s from a request to add to the
* server span.
*/
def withAdditionalRequestAttributes(
additionalRequestAttributes: Request[F] => immutable.Iterable[Attribute[_]]
additionalRequestAttributes: RequestPrelude => immutable.Iterable[Attribute[_]]
): ServerMiddlewareBuilder[F] =
copy(additionalRequestAttributes = additionalRequestAttributes)

/** Sets how to derive additional `Attribute`s from a response to add to the
* server span.
*/
def withAdditionalResponseAttributes(
additionalResponseAttributes: Response[F] => immutable.Iterable[Attribute[_]]
additionalResponseAttributes: ResponsePrelude => immutable.Iterable[Attribute[_]]
): ServerMiddlewareBuilder[F] =
copy(additionalResponseAttributes = additionalResponseAttributes)

Expand All @@ -163,8 +164,9 @@ object ServerMiddleware {
f: Http[G, F]
)(implicit kt: KindTransformer[F, G]): Http[G, F] =
Kleisli { (req: Request[F]) =>
val reqPrelude = req.requestPrelude
if (
!shouldTrace(req.requestPrelude).shouldTrace ||
!shouldTrace(reqPrelude).shouldTrace ||
!Tracer[F].meta.isEnabled
) {
f(req)
Expand All @@ -175,12 +177,12 @@ object ServerMiddleware {
allowedRequestHeaders,
routeClassifier,
urlRedactor,
) ++ additionalRequestAttributes(req)
) ++ additionalRequestAttributes(reqPrelude)
MonadCancelThrow[G].uncancelable { poll =>
val tracerG = Tracer[F].mapK[G]
tracerG.joinOrRoot(req.headers) {
tracerG
.spanBuilder(serverSpanName(req))
.spanBuilder(serverSpanName(reqPrelude))
.withSpanKind(SpanKind.Server)
.addAttributes(init)
.build
Expand All @@ -194,7 +196,7 @@ object ServerMiddleware {
response(
resp,
allowedResponseHeaders,
) ++ additionalResponseAttributes(resp)
) ++ additionalResponseAttributes(resp.responsePrelude)
span.addAttributes(out)
}
case Outcome.Errored(e) =>
Expand Down Expand Up @@ -227,7 +229,7 @@ object ServerMiddleware {
private def request[F[_]](
request: Request[F],
allowedHeaders: Set[CIString],
routeClassifier: Request[F] => Option[String],
routeClassifier: RequestPrelude => Option[String],
urlRedactor: UriRedactor,
): Attributes = {
val builder = Attributes.newBuilder
Expand All @@ -242,7 +244,9 @@ object ServerMiddleware {
.get[`User-Agent`]
.foreach(ua => builder += TypedAttributes.userAgentOriginal(ua))

routeClassifier(request).foreach(route => builder += TypedAttributes.Server.httpRoute(route))
routeClassifier(request.requestPrelude).foreach(route =>
builder += TypedAttributes.Server.httpRoute(route)
)

request.remote.foreach { socketAddress =>
builder +=
Expand Down

0 comments on commit befd623

Please sign in to comment.