All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ovoenergy.natchez.extras.http4s.client.TracedClient.scala Maven / Gradle / Ivy

The newest version!
package com.ovoenergy.natchez.extras.http4s.client

import cats.data.Kleisli
import cats.effect.{Resource, Sync}
import cats.syntax.functor._
import cats.~>
import com.ovoenergy.natchez.extras.http4s.Configuration
import com.ovoenergy.natchez.extras.http4s.server.TraceMiddleware.removeNumericPathSegments
import natchez.{Span, Trace}
import org.http4s.Header.ToRaw.keyValuesToRaw
import org.http4s.Uri
import org.http4s.client.Client

trait TracedClient[F[_]] {
  def named(s: String): Client[F]
}

object TracedClient {

  type Traced[F[_], A] = Kleisli[F, Span[F], A]

  private def dropTracing[F[_]](span: Span[F]): Traced[F, *] ~> F =
    Kleisli.applyK[F, Span[F]](span)

  private def trace[F[_]]: F ~> Traced[F, *] =
    Kleisli.liftK

  def apply[F[_]: Sync](
    client: Client[F],
    config: Configuration[F],
    redactSensitiveData: Uri => String = removeNumericPathSegments
  ): TracedClient[Traced[F, *]] =
    name =>
      Client[Traced[F, *]] { req =>
        Resource(
          Trace[Traced[F, *]].span(s"$name:http.request:${redactSensitiveData(req.uri)}") {
            for {
              span    <- Kleisli.ask[F, Span[F]]
              headers <- trace(span.kernel.map(_.toHeaders.map { case (k, v) => k.toString -> v }.toSeq))
              withHeader = req.putHeaders(headers.map(keyValuesToRaw): _*).mapK(dropTracing(span))
              reqTags  <- trace(config.request.value.run(req.mapK(dropTracing(span))))
              _        <- trace(span.put(reqTags.toSeq: _*))
              resTuple <- client.run(withHeader).mapK(trace[F]).map(_.mapK(trace[F])).allocated
              (resp, rel) = resTuple
              respTags <- trace(config.response.value.run(resp.mapK(dropTracing(span))))
              _        <- trace(span.put(respTags.toSeq: _*))
            } yield resp -> rel
          }
        )
      }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy