From dd6e53aaf8b5b09ecd2d97dc1736d1721b152f28 Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Wed, 28 Aug 2024 17:59:34 -0500 Subject: [PATCH 1/6] allow users to add additional attributes to client spans --- .../natchez/http4s/NatchezMiddleware.scala | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala index 0b0dc19..ed84813 100644 --- a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala +++ b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala @@ -6,12 +6,12 @@ package natchez.http4s import cats.data.{ Kleisli, OptionT } import cats.syntax.all._ -import cats.effect.{MonadCancel, Outcome} +import cats.effect.{MonadCancel, MonadCancelThrow, Outcome} import cats.effect.syntax.all._ import Outcome._ import org.http4s.HttpRoutes import natchez.{Trace, TraceValue, Tags} -import org.http4s.Response +import org.http4s.{Response, Request} import org.http4s.client.Client import java.io.ByteArrayOutputStream import java.io.PrintStream @@ -93,9 +93,42 @@ object NatchezMiddleware { * - "client.http.status_code" -> "200", "403", etc. // why is this a string? * */ - def client[F[_]: Trace](client: Client[F])( - implicit ev: MonadCancel[F, Throwable] - ): Client[F] = + def client[F[_] : Trace : MonadCancelThrow](client: Client[F]): Client[F] = + NatchezMiddleware.client(client, _ => Seq.empty) + + /** + * A middleware that adds the current span's kernel to outgoing requests, performs requests in + * a span called `http4s-client-request`, and adds the following fields to that span. + * + * - "client.http.method" -> "GET", "PUT", etc. + * - "client.http.uri" -> request URI + * - "client.http.status_code" -> "200", "403", etc. // why is this a string? + * + * @param client the `Client[F]` to be enhanced + * @param additionalAttributes additional attributes to be added to the span + * @tparam F An effect with instances of `Trace[F]` and `MonadCancelThrow[F]` + * @return the enhanced `Client[F]` + */ + def client[F[_] : Trace : MonadCancelThrow](client: Client[F], + additionalAttributes: (String, TraceValue) *): Client[F] = + NatchezMiddleware.client(client, (_: Request[F]) => additionalAttributes) + + /** + * A middleware that adds the current span's kernel to outgoing requests, performs requests in + * a span called `http4s-client-request`, and adds the following fields to that span. + * + * - "client.http.method" -> "GET", "PUT", etc. + * - "client.http.uri" -> request URI + * - "client.http.status_code" -> "200", "403", etc. // why is this a string? + * + * @param client the `Client[F]` to be enhanced + * @param additionalAttributes a function that takes the `Request[F]` and returns any additional attributes to be added to the span + * @tparam F An effect with instances of `Trace[F]` and `MonadCancelThrow[F]` + * @return the enhanced `Client[F]` + */ + def client[F[_] : Trace : MonadCancelThrow](client: Client[F], + additionalAttributes: Request[F] => Seq[(String, TraceValue)], + ): Client[F] = Client { req => Resource.applyFull {poll => Trace[F].span("http4s-client-request") { @@ -105,6 +138,7 @@ object NatchezMiddleware { "client.http.uri" -> req.uri.toString(), "client.http.method" -> req.method.toString ) + _ <- Trace[F].put(additionalAttributes(req): _*) reqʹ = req.withHeaders(knl.toHttp4sHeaders ++ req.headers) // prioritize request headers over kernel ones rsrc <- poll(client.run(reqʹ).allocatedCase) _ <- Trace[F].put("client.http.status_code" -> rsrc._1.status.code.toString()) From 3eba62880f76ade1e09aabd983d310d5e291a961 Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Wed, 28 Aug 2024 19:05:42 -0500 Subject: [PATCH 2/6] tweak client interface to make it easier to use varargs --- .../src/main/scala/natchez/http4s/NatchezMiddleware.scala | 4 ++-- .../test/scala/natchez/http4s/NatchezMiddlewareSuite.scala | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala index ed84813..4ad9fe9 100644 --- a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala +++ b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala @@ -109,8 +109,8 @@ object NatchezMiddleware { * @tparam F An effect with instances of `Trace[F]` and `MonadCancelThrow[F]` * @return the enhanced `Client[F]` */ - def client[F[_] : Trace : MonadCancelThrow](client: Client[F], - additionalAttributes: (String, TraceValue) *): Client[F] = + def clientWithAttributes[F[_] : Trace : MonadCancelThrow](client: Client[F]) + (additionalAttributes: (String, TraceValue)*): Client[F] = NatchezMiddleware.client(client, (_: Request[F]) => additionalAttributes) /** diff --git a/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala b/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala index d6275b5..73fc852 100644 --- a/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala +++ b/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala @@ -82,6 +82,10 @@ class NatchezMiddlewareSuite extends InMemorySuite { "client.http.method" -> StringValue("GET") ) + val userSpecifiedTags = List( + "test" -> StringValue("test"), + ) + val clientResponseTags = List( "client.http.status_code" -> StringValue("200") ) @@ -101,6 +105,7 @@ class NatchezMiddlewareSuite extends InMemorySuite { (Lineage.Root / "call-proxy", NatchezCommand.CreateSpan("http4s-client-request", None, Span.Options.Defaults)), (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.AskKernel(requestKernel)), (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientRequestTags)), + (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(userSpecifiedTags)), (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientResponseTags)), (Lineage.Root / "call-proxy", NatchezCommand.ReleaseSpan("http4s-client-request")), (Lineage.Root, NatchezCommand.ReleaseSpan("call-proxy")), @@ -119,7 +124,7 @@ class NatchezMiddlewareSuite extends InMemorySuite { } private def httpRoutes[F[_]: MonadCancelThrow: Trace]: HttpRoutes[F] = { - val client = NatchezMiddleware.client(echoHeadersClient[F]) + val client = NatchezMiddleware.clientWithAttributes(echoHeadersClient[F])("test" -> "test") val server = NatchezMiddleware.server(proxyRoutes(client)) server } From eaa068999839beac9a202c02a94053acff46b6e3 Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Thu, 29 Aug 2024 11:09:34 -0500 Subject: [PATCH 3/6] Let NatchezMiddleware.client accept an effectual function for additional attributes --- .../main/scala/natchez/http4s/NatchezMiddleware.scala | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala index 4ad9fe9..57cf48b 100644 --- a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala +++ b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala @@ -94,7 +94,7 @@ object NatchezMiddleware { * */ def client[F[_] : Trace : MonadCancelThrow](client: Client[F]): Client[F] = - NatchezMiddleware.client(client, _ => Seq.empty) + NatchezMiddleware.client(client, _ => Seq.empty[(String, TraceValue)].pure[F]) /** * A middleware that adds the current span's kernel to outgoing requests, performs requests in @@ -111,7 +111,7 @@ object NatchezMiddleware { */ def clientWithAttributes[F[_] : Trace : MonadCancelThrow](client: Client[F]) (additionalAttributes: (String, TraceValue)*): Client[F] = - NatchezMiddleware.client(client, (_: Request[F]) => additionalAttributes) + NatchezMiddleware.client(client, (_: Request[F]) => additionalAttributes.pure[F]) /** * A middleware that adds the current span's kernel to outgoing requests, performs requests in @@ -122,12 +122,12 @@ object NatchezMiddleware { * - "client.http.status_code" -> "200", "403", etc. // why is this a string? * * @param client the `Client[F]` to be enhanced - * @param additionalAttributes a function that takes the `Request[F]` and returns any additional attributes to be added to the span + * @param additionalAttributesF a function that takes the `Request[F]` and returns any additional attributes to be added to the span * @tparam F An effect with instances of `Trace[F]` and `MonadCancelThrow[F]` * @return the enhanced `Client[F]` */ def client[F[_] : Trace : MonadCancelThrow](client: Client[F], - additionalAttributes: Request[F] => Seq[(String, TraceValue)], + additionalAttributesF: Request[F] => F[Seq[(String, TraceValue)]], ): Client[F] = Client { req => Resource.applyFull {poll => @@ -138,7 +138,8 @@ object NatchezMiddleware { "client.http.uri" -> req.uri.toString(), "client.http.method" -> req.method.toString ) - _ <- Trace[F].put(additionalAttributes(req): _*) + additionalAttributes <- additionalAttributesF(req) + _ <- Trace[F].put(additionalAttributes: _*) reqʹ = req.withHeaders(knl.toHttp4sHeaders ++ req.headers) // prioritize request headers over kernel ones rsrc <- poll(client.run(reqʹ).allocatedCase) _ <- Trace[F].put("client.http.status_code" -> rsrc._1.status.code.toString()) From 731f5b3b4f6abd8a18fce62c11efe00b9d7ccef5 Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Thu, 29 Aug 2024 11:20:51 -0500 Subject: [PATCH 4/6] Use ScalaCheck to generate user specified client attributes --- build.sbt | 21 +-- .../http4s/NatchezMiddlewareSuite.scala | 133 ++++++++++-------- 2 files changed, 87 insertions(+), 67 deletions(-) diff --git a/build.sbt b/build.sbt index ddd8a38..5911636 100644 --- a/build.sbt +++ b/build.sbt @@ -1,12 +1,13 @@ ThisBuild / tlBaseVersion := "0.6" -val http4sVersion = "0.23.17" -val natchezVersion = "0.3.0" -val scala212Version = "2.12.17" -val scala213Version = "2.13.10" -val scala3Version = "3.2.1" -val slf4jVersion = "2.0.4" -val munitCEVersion = "2.0.0-M3" +val http4sVersion = "0.23.17" +val natchezVersion = "0.3.0" +val scala212Version = "2.12.17" +val scala213Version = "2.13.10" +val scala3Version = "3.2.1" +val slf4jVersion = "2.0.4" +val munitCEVersion = "2.0.0-M3" +val scalacheckEffectVersion = "2.0.0-M2" ThisBuild / organization := "org.tpolecat" ThisBuild / tlSonatypeUseLegacyHost := false @@ -29,8 +30,9 @@ lazy val commonSettings = Seq( ), libraryDependencies ++= Seq( - "org.typelevel" %%% "munit-cats-effect" % munitCEVersion % Test, - "org.http4s" %%% "http4s-dsl" % http4sVersion % Test, + "org.typelevel" %%% "munit-cats-effect" % munitCEVersion % Test, + "org.http4s" %%% "http4s-dsl" % http4sVersion % Test, + "org.typelevel" %%% "scalacheck-effect-munit" % scalacheckEffectVersion % Test, ) ) @@ -102,4 +104,3 @@ lazy val docs = project makeSite := makeSite.dependsOn(mdoc.toTask("")).value, mdocExtraArguments := Seq("--no-link-hygiene"), // paradox handles this ) - diff --git a/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala b/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala index 73fc852..10486bb 100644 --- a/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala +++ b/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala @@ -5,9 +5,10 @@ package natchez.http4s import cats.Monad -import cats.data.{ Chain, Kleisli } -import cats.effect.{ IO, MonadCancelThrow, Resource } -import natchez.{Kernel, Span, Trace} +import cats.data.{Chain, Kleisli} +import cats.effect.{IO, MonadCancelThrow, Resource} +import munit.ScalaCheckEffectSuite +import natchez.{Kernel, Span, Trace, TraceValue} import natchez.TraceValue.StringValue import natchez.http4s.syntax.entrypoint._ import org.http4s._ @@ -15,13 +16,33 @@ import org.http4s.headers._ import org.http4s.client.Client import org.http4s.dsl.request._ import org.http4s.syntax.literals._ +import org.scalacheck.{Arbitrary, Gen} +import org.scalacheck.Arbitrary.arbitrary +import org.scalacheck.effect.PropF import org.typelevel.ci._ -class NatchezMiddlewareSuite extends InMemorySuite { +class NatchezMiddlewareSuite + extends InMemorySuite + with ScalaCheckEffectSuite { private val CustomHeaderName = ci"X-Custom-Header" private val CorrelationIdName = ci"X-Correlation-Id" + private implicit val arbTraceValue: Arbitrary[TraceValue] = Arbitrary { + Gen.oneOf( + arbitrary[String].map(TraceValue.StringValue(_)), + arbitrary[Boolean].map(TraceValue.BooleanValue(_)), + arbitrary[Number].map(TraceValue.NumberValue(_)), + ) + } + + private implicit val arbAttribute: Arbitrary[(String, TraceValue)] = Arbitrary { + for { + key <- arbitrary[String] + value <- arbitrary[TraceValue] + } yield key -> value + } + test("do not leak security and payload headers to the client request") { val headers = Headers( // security @@ -54,7 +75,7 @@ class NatchezMiddlewareSuite extends InMemorySuite { for { ref <- IO.ref(Chain.empty[(Lineage, NatchezCommand)]) ep <- IO.pure(new InMemory.EntryPoint(ref)) - routes <- IO.pure(ep.liftT(httpRoutes[Kleisli[IO, natchez.Span[IO], *]])) + routes <- IO.pure(ep.liftT(httpRoutes[Kleisli[IO, natchez.Span[IO], *]]())) response <- routes.orNotFound.run(request) } yield { assertEquals(response.status.code, 200) @@ -63,68 +84,66 @@ class NatchezMiddlewareSuite extends InMemorySuite { } test("generate proper tracing history") { - val request = Request[IO]( - method = Method.GET, - uri = uri"/hello/some-name", - headers = Headers( - Header.Raw(CustomHeaderName, "external"), - Header.Raw(CorrelationIdName, "id-123") - ) - ) - - val expectedHistory = { - val requestKernel = Kernel( - Map(CustomHeaderName -> "external", CorrelationIdName -> "id-123") + PropF.forAllF { (userSpecifiedTags: List[(String, TraceValue)]) => + val request = Request[IO]( + method = Method.GET, + uri = uri"/hello/some-name", + headers = Headers( + Header.Raw(CustomHeaderName, "external"), + Header.Raw(CorrelationIdName, "id-123") + ) ) - val clientRequestTags = List( - "client.http.uri" -> StringValue("/some-name"), - "client.http.method" -> StringValue("GET") - ) + val expectedHistory = { + val requestKernel = Kernel( + Map(CustomHeaderName -> "external", CorrelationIdName -> "id-123") + ) - val userSpecifiedTags = List( - "test" -> StringValue("test"), - ) + val clientRequestTags = List( + "client.http.uri" -> StringValue("/some-name"), + "client.http.method" -> StringValue("GET") + ) - val clientResponseTags = List( - "client.http.status_code" -> StringValue("200") - ) + val clientResponseTags = List( + "client.http.status_code" -> StringValue("200") + ) - val requestTags = List( - "http.method" -> StringValue("GET"), - "http.url" -> StringValue("/hello/some-name") - ) + val requestTags = List( + "http.method" -> StringValue("GET"), + "http.url" -> StringValue("/hello/some-name") + ) - val responseTags = List( - "http.status_code" -> StringValue("200") - ) + val responseTags = List( + "http.status_code" -> StringValue("200") + ) - List( - (Lineage.Root, NatchezCommand.CreateRootSpan("/hello/some-name", requestKernel, Span.Options.Defaults)), - (Lineage.Root, NatchezCommand.CreateSpan("call-proxy", None, Span.Options.Defaults)), - (Lineage.Root / "call-proxy", NatchezCommand.CreateSpan("http4s-client-request", None, Span.Options.Defaults)), - (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.AskKernel(requestKernel)), - (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientRequestTags)), - (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(userSpecifiedTags)), - (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientResponseTags)), - (Lineage.Root / "call-proxy", NatchezCommand.ReleaseSpan("http4s-client-request")), - (Lineage.Root, NatchezCommand.ReleaseSpan("call-proxy")), - (Lineage.Root, NatchezCommand.Put(requestTags)), - (Lineage.Root, NatchezCommand.Put(responseTags)), - (Lineage.Root, NatchezCommand.ReleaseRootSpan("/hello/some-name")) - ) + List( + (Lineage.Root, NatchezCommand.CreateRootSpan("/hello/some-name", requestKernel, Span.Options.Defaults)), + (Lineage.Root, NatchezCommand.CreateSpan("call-proxy", None, Span.Options.Defaults)), + (Lineage.Root / "call-proxy", NatchezCommand.CreateSpan("http4s-client-request", None, Span.Options.Defaults)), + (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.AskKernel(requestKernel)), + (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientRequestTags)), + (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(userSpecifiedTags)), + (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientResponseTags)), + (Lineage.Root / "call-proxy", NatchezCommand.ReleaseSpan("http4s-client-request")), + (Lineage.Root, NatchezCommand.ReleaseSpan("call-proxy")), + (Lineage.Root, NatchezCommand.Put(requestTags)), + (Lineage.Root, NatchezCommand.Put(responseTags)), + (Lineage.Root, NatchezCommand.ReleaseRootSpan("/hello/some-name")) + ) + } + + for { + ep <- InMemory.EntryPoint.create + routes <- IO.pure(ep.liftT(httpRoutes[Kleisli[IO, natchez.Span[IO], *]](userSpecifiedTags: _*))) + _ <- routes.orNotFound.run(request) + history <- ep.ref.get + } yield assertEquals(history.toList, expectedHistory) } - - for { - ep <- InMemory.EntryPoint.create - routes <- IO.pure(ep.liftT(httpRoutes[Kleisli[IO, natchez.Span[IO], *]])) - _ <- routes.orNotFound.run(request) - history <- ep.ref.get - } yield assertEquals(history.toList, expectedHistory) } - private def httpRoutes[F[_]: MonadCancelThrow: Trace]: HttpRoutes[F] = { - val client = NatchezMiddleware.clientWithAttributes(echoHeadersClient[F])("test" -> "test") + private def httpRoutes[F[_]: MonadCancelThrow: Trace](additionalAttributes: (String, TraceValue)*): HttpRoutes[F] = { + val client = NatchezMiddleware.clientWithAttributes(echoHeadersClient[F])(additionalAttributes: _*) val server = NatchezMiddleware.server(proxyRoutes(client)) server } From 720db6fb3f955cc911c79a4760ab89a692688ffb Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Thu, 29 Aug 2024 12:09:33 -0500 Subject: [PATCH 5/6] http4s-client-request span should be a Client span --- .../scala/natchez/http4s/NatchezMiddleware.scala | 16 +++++++++------- .../natchez/http4s/NatchezMiddlewareSuite.scala | 3 ++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala index 57cf48b..03a623b 100644 --- a/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala +++ b/modules/http4s/src/main/scala/natchez/http4s/NatchezMiddleware.scala @@ -4,18 +4,20 @@ package natchez.http4s -import cats.data.{ Kleisli, OptionT } +import cats.data.{Kleisli, OptionT} import cats.syntax.all._ -import cats.effect.{MonadCancel, MonadCancelThrow, Outcome} +import cats.effect.{MonadCancel, MonadCancelThrow, Outcome, Resource} import cats.effect.syntax.all._ import Outcome._ -import org.http4s.HttpRoutes -import natchez.{Trace, TraceValue, Tags} -import org.http4s.{Response, Request} +import natchez.{Tags, Trace, TraceValue} +import natchez.Span.Options.Defaults +import natchez.Span.SpanKind import org.http4s.client.Client +import org.http4s.HttpRoutes +import org.http4s.{Request, Response} + import java.io.ByteArrayOutputStream import java.io.PrintStream -import cats.effect.Resource object NatchezMiddleware { import syntax.kernel._ @@ -131,7 +133,7 @@ object NatchezMiddleware { ): Client[F] = Client { req => Resource.applyFull {poll => - Trace[F].span("http4s-client-request") { + Trace[F].span("http4s-client-request", Defaults.withSpanKind(SpanKind.Client)) { for { knl <- Trace[F].kernel _ <- Trace[F].put( diff --git a/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala b/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala index 10486bb..baee272 100644 --- a/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala +++ b/modules/http4s/src/test/scala/natchez/http4s/NatchezMiddlewareSuite.scala @@ -8,6 +8,7 @@ import cats.Monad import cats.data.{Chain, Kleisli} import cats.effect.{IO, MonadCancelThrow, Resource} import munit.ScalaCheckEffectSuite +import natchez.Span.SpanKind import natchez.{Kernel, Span, Trace, TraceValue} import natchez.TraceValue.StringValue import natchez.http4s.syntax.entrypoint._ @@ -120,7 +121,7 @@ class NatchezMiddlewareSuite List( (Lineage.Root, NatchezCommand.CreateRootSpan("/hello/some-name", requestKernel, Span.Options.Defaults)), (Lineage.Root, NatchezCommand.CreateSpan("call-proxy", None, Span.Options.Defaults)), - (Lineage.Root / "call-proxy", NatchezCommand.CreateSpan("http4s-client-request", None, Span.Options.Defaults)), + (Lineage.Root / "call-proxy", NatchezCommand.CreateSpan("http4s-client-request", None, Span.Options.Defaults.withSpanKind(SpanKind.Client))), (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.AskKernel(requestKernel)), (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(clientRequestTags)), (Lineage.Root / "call-proxy" / "http4s-client-request", NatchezCommand.Put(userSpecifiedTags)), From 934c815a96cc076e7e6185d077a13801c1071537 Mon Sep 17 00:00:00 2001 From: Brian Holt Date: Thu, 29 Aug 2024 12:19:29 -0500 Subject: [PATCH 6/6] fix compiler warnings in examples --- modules/examples/src/main/scala/Example1.scala | 3 ++- modules/examples/src/main/scala/Example2.scala | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/examples/src/main/scala/Example1.scala b/modules/examples/src/main/scala/Example1.scala index bfbb79f..6b25f91 100644 --- a/modules/examples/src/main/scala/Example1.scala +++ b/modules/examples/src/main/scala/Example1.scala @@ -8,6 +8,7 @@ package example import cats.effect._ import cats.syntax.all._ import com.comcast.ip4s.Port +import fs2.io.net.Network import natchez.http4s.implicits._ import org.http4s.ember.server.EmberServerBuilder import org.http4s.server.Server @@ -34,7 +35,7 @@ import natchez.http4s.NatchezMiddleware object Http4sExample extends IOApp with Common { // Our main app resource - def server[F[_]: Async]: Resource[F, Server] = + def server[F[_]: Async : Network]: Resource[F, Server] = for { ep <- entryPoint[F] ap = ep.liftT(NatchezMiddleware.server(routes)).orNotFound // liftT discharges the Trace constraint diff --git a/modules/examples/src/main/scala/Example2.scala b/modules/examples/src/main/scala/Example2.scala index 6a1b0eb..19aad99 100644 --- a/modules/examples/src/main/scala/Example2.scala +++ b/modules/examples/src/main/scala/Example2.scala @@ -12,13 +12,15 @@ import fs2.Stream import org.http4s.ember.server.EmberServerBuilder import org.http4s.implicits._ import org.http4s.server.middleware.Logger + import scala.io.StdIn import com.comcast.ip4s.Host import com.comcast.ip4s.Port +import fs2.io.net.Network object Http4sExampleStreamed extends IOApp with Common { - def stream[F[_]: Async]: Stream[F, Nothing] = { + def stream[F[_]: Async : Network]: Stream[F, Nothing] = { for { ep <- Stream.resource(entryPoint[F]) finalRoutes = ep.liftT(NatchezMiddleware.server(routes))