Skip to content

Commit

Permalink
Rewrite the examples (#409)
Browse files Browse the repository at this point in the history
  • Loading branch information
mvelimir authored Aug 4, 2021
1 parent 79a29f5 commit 548c720
Show file tree
Hide file tree
Showing 36 changed files with 252 additions and 362 deletions.
4 changes: 3 additions & 1 deletion opentelemetry-example/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ backend {
host = "http://localhost:9000"
}

tracer = "localhost:14250"
tracer {
host = "http://localhost:14250"
}

Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
package zio.telemetry.opentelemetry.example

import org.http4s.server.{ Router, _ }
import org.http4s.server.blaze.BlazeServerBuilder
import zio.clock.Clock
import zio.interop.catz._
import zio.console.putStrLn
import zio.magic._
import zio.config.getConfig
import zio.config.typesafe.TypesafeConfig
import zio.config.magnolia.{ descriptor, Descriptor }
import zio.telemetry.opentelemetry.Tracing
import zio.telemetry.opentelemetry.example.config.{ Config, Configuration }
import zio.telemetry.opentelemetry.example.http.{ AppEnv, AppTask, Client, StatusService }
import zio.{ ExitCode, Managed, ZIO, ZLayer }
import org.http4s.syntax.kleisli._
import sttp.client.asynchttpclient.zio.AsyncHttpClientZioBackend
import zio.telemetry.opentelemetry.example.config.AppConfig
import zio.telemetry.opentelemetry.example.http.StatusService
import zio.{ App, ZIO }
import sttp.model.Uri
import zhttp.service.{ EventLoopGroup, Server }
import zhttp.service.server.ServerChannelFactory

object BackendServer extends zio.App {
val router = Router[AppTask]("/" -> StatusService.routes).orNotFound
object BackendServer extends App {
implicit val sttpUriDescriptor: Descriptor[Uri] =
Descriptor[String].transformOrFailLeft(Uri.parse)(_.toString)

val server =
ZIO
.runtime[AppEnv]
.flatMap { implicit runtime =>
implicit val ec = runtime.platform.executor.asEC
BlazeServerBuilder[AppTask](ec)
.bindHttp(
runtime.environment.get[Config].backend.host.port.getOrElse(defaults.HttpPort),
runtime.environment.get[Config].backend.host.host
)
.withHttpApp(router)
.serve
.compile
.drain
}
getConfig[AppConfig].flatMap { conf =>
val port = conf.backend.host.port.getOrElse(9000)
(Server.port(port) ++ Server.app(StatusService.routes)).make.use(_ =>
putStrLn(s"BackendServer started on port $port") *> ZIO.never
)
}

val httpBackend = ZLayer.fromManaged(Managed.make(AsyncHttpClientZioBackend())(_.close().ignore))
val client = Configuration.live ++ httpBackend >>> Client.live
val tracer = Configuration.live >>> JaegerTracer.live
val envLayer = tracer ++ Clock.live >>> Tracing.live ++ Configuration.live ++ client
val configLayer = TypesafeConfig.fromDefaultLoader(descriptor[AppConfig])

override def run(args: List[String]) =
server.provideCustomLayer(envLayer).fold(_ => ExitCode.failure, _ => ExitCode.success)
server
.injectCustom(
configLayer,
JaegerTracer.live,
Tracing.live,
ServerChannelFactory.auto,
EventLoopGroup.auto(0)
)
.exitCode
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ package zio.telemetry.opentelemetry.example
import io.opentelemetry.api.trace.Tracer
import io.opentelemetry.exporter.jaeger.JaegerGrpcSpanExporter
import zio._
import zio.telemetry.opentelemetry.example.config.{ Config, Configuration }
import zio.telemetry.opentelemetry.example.config.AppConfig
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor

object JaegerTracer {

def live: RLayer[Configuration, Has[Tracer]] =
ZLayer.fromServiceM((conf: Config) =>
def live: RLayer[Has[AppConfig], Has[Tracer]] =
ZLayer.fromServiceM((conf: AppConfig) =>
for {
spanExporter <- Task(JaegerGrpcSpanExporter.builder().setEndpoint(conf.tracer.host).build())
spanProcessor <- UIO(SimpleSpanProcessor.create(spanExporter))
tracerProvider <- UIO(SdkTracerProvider.builder().addSpanProcessor(spanProcessor).build())
openTelemetry <- UIO(OpenTelemetrySdk.builder().setTracerProvider(tracerProvider).build())
tracer <- UIO(openTelemetry.getTracer("zio.telemetry.opentelemetry.example.JaegerTracer"))

} yield tracer
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
package zio.telemetry.opentelemetry.example

import org.http4s.server.blaze.BlazeServerBuilder
import org.http4s.server.{ defaults, Router }
import zio.clock.Clock
import zio.interop.catz._
import zio.console.putStrLn
import zio.magic._
import zio.config.getConfig
import zio.config.typesafe.TypesafeConfig
import zio.config.magnolia.{ descriptor, Descriptor }
import zio.telemetry.opentelemetry.Tracing
import zio.telemetry.opentelemetry.example.config.{ Config, Configuration }
import zio.telemetry.opentelemetry.example.http.{ AppEnv, AppTask, Client, StatusesService }
import zio.{ ExitCode, Managed, ZIO, ZLayer }
import org.http4s.syntax.kleisli._
import sttp.client.asynchttpclient.zio.AsyncHttpClientZioBackend
import zio.telemetry.opentelemetry.example.config.AppConfig
import zio.telemetry.opentelemetry.example.http.{ Client, StatusesService }
import zio.{ App, Managed, ZIO, ZLayer }
import sttp.client3.asynchttpclient.zio.AsyncHttpClientZioBackend
import sttp.model.Uri
import zhttp.service.{ EventLoopGroup, Server }
import zhttp.service.server.ServerChannelFactory

object ProxyServer extends zio.App {

val router = Router[AppTask]("/" -> StatusesService.routes).orNotFound
object ProxyServer extends App {
implicit val sttpUriDescriptor: Descriptor[Uri] =
Descriptor[String].transformOrFailLeft(Uri.parse)(_.toString)

val server =
ZIO
.runtime[AppEnv]
.flatMap { implicit runtime =>
implicit val ec = runtime.platform.executor.asEC
BlazeServerBuilder[AppTask](ec)
.bindHttp(
runtime.environment.get[Config].proxy.host.port.getOrElse(defaults.HttpPort),
runtime.environment.get[Config].proxy.host.host
)
.withHttpApp(router)
.serve
.compile
.drain
}
getConfig[AppConfig].flatMap { conf =>
val port = conf.proxy.host.port.getOrElse(8080)
(Server.port(port) ++ Server.app(StatusesService.routes)).make.use(_ =>
putStrLn(s"ProxyServer started on port $port") *> ZIO.never
)
}

val configLayer = TypesafeConfig.fromDefaultLoader(descriptor[AppConfig])
val httpBackend = ZLayer.fromManaged(Managed.make(AsyncHttpClientZioBackend())(_.close().ignore))
val client = Configuration.live ++ httpBackend >>> Client.live
val tracer = Configuration.live >>> JaegerTracer.live
val envLayer = tracer ++ Clock.live >>> Tracing.live ++ Configuration.live ++ client

override def run(args: List[String]) =
server.provideCustomLayer(envLayer).fold(_ => ExitCode.failure, _ => ExitCode.success)
server
.injectCustom(
configLayer,
httpBackend,
Client.live,
JaegerTracer.live,
Tracing.live,
ServerChannelFactory.auto,
EventLoopGroup.auto(0)
)
.exitCode
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package zio.telemetry.opentelemetry.example.config

final case class AppConfig(proxy: ProxyConfig, backend: BackendConfig, tracer: TracerHost)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package zio.telemetry.opentelemetry.example.config

import sttp.model.Uri

final case class BackendConfig(host: Uri)

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package zio.telemetry.opentelemetry.example.config

import sttp.model.Uri

final case class ProxyConfig(host: Uri)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package zio.telemetry.opentelemetry.example.config

final case class TracerHost(host: String) extends AnyVal

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package zio.telemetry.opentelemetry.example.http

import sttp.client._
import sttp.client.asynchttpclient.WebSocketHandler
import sttp.client.circe.asJson
import zio.telemetry.opentelemetry.example.config.Config
import sttp.client3._
import sttp.client3.ziojson._
import sttp.capabilities.zio.ZioStreams
import sttp.capabilities.WebSockets
import zio.telemetry.opentelemetry.example.config.AppConfig
import zio.{ Task, ZIO, ZLayer }
import zio.stream.ZStream

object Client {
type Backend = SttpBackend[Task, ZStream[Any, Throwable, Byte], WebSocketHandler]
type Backend = SttpBackend[Task, ZioStreams with WebSockets]

trait Service {
def status(headers: Map[String, String]): Task[Statuses]
Expand All @@ -19,17 +19,17 @@ object Client {

val up = Status.up("proxy")

val live = ZLayer.fromServices((backend: Backend, conf: Config) =>
val live = ZLayer.fromServices((backend: Backend, conf: AppConfig) =>
new Service {
def status(headers: Map[String, String]): Task[Statuses] =
backend
.send(
basicRequest.get(conf.backend.host.path("status")).headers(headers).response(asJson[Status])
basicRequest.get(conf.backend.host.withPath("status")).headers(headers).response(asJson[Status])
)
.map(_.body match {
case Right(s) => Statuses(List(s, up))
case _ => Statuses(List(Status.down("backend"), up))
})
.map { response =>
val status = response.body.getOrElse(Status.down("backend"))
Statuses(List(status, up))
}
}
)
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package zio.telemetry.opentelemetry.example.http

import io.circe._
import io.circe.generic.semiauto._
import zio.json.{ DeriveJsonCodec, JsonCodec }

final case class Status(name: String, status: String)

object Status {
implicit val decoder: Decoder[Status] = deriveDecoder
implicit val encoder: Encoder[Status] = deriveEncoder
implicit val codec: JsonCodec[Status] = DeriveJsonCodec.gen[Status]

final def up(component: String): Status = Status(component, status = "up")
final def down(component: String): Status = Status(component, status = "down")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,38 @@
package zio.telemetry.opentelemetry.example.http

import io.circe.Encoder
import io.circe.syntax._
import io.opentelemetry.api.trace.SpanKind
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator
import io.opentelemetry.context.propagation.{ TextMapGetter, TextMapPropagator }
import org.http4s._
import org.http4s.circe.jsonEncoderOf
import org.http4s.dsl.Http4sDsl
import org.http4s.util.CaseInsensitiveString
import zio.interop.catz._
import zio.telemetry.opentelemetry.Tracing
import zio.telemetry.opentelemetry.TracingSyntax._
import zio.telemetry.opentelemetry.example.http.{ Status => ServiceStatus }
import zhttp.http.{ ->, /, Header, Http, HttpApp, Method, Response, Root }
import zio.json.EncoderOps
import zio.ZIO

import java.lang
import scala.jdk.CollectionConverters._

object StatusService {

val dsl: Http4sDsl[AppTask] = Http4sDsl[AppTask]
import dsl._
val propagator: TextMapPropagator = W3CTraceContextPropagator.getInstance()
val getter: TextMapGetter[List[Header]] = new TextMapGetter[List[Header]] {
override def keys(carrier: List[Header]): lang.Iterable[String] =
carrier.map(_.name.toString).asJava

implicit def encoder[A: Encoder]: EntityEncoder[AppTask, A] = jsonEncoderOf[AppTask, A]

val propagator: TextMapPropagator = W3CTraceContextPropagator.getInstance()
val getter: TextMapGetter[Headers] = new TextMapGetter[Headers] {
override def keys(carrier: Headers): lang.Iterable[String] =
carrier.toList.map(_.name.value).asJava

override def get(carrier: Headers, key: String): String =
carrier.get(CaseInsensitiveString(key)).map(_.value).orNull
override def get(carrier: List[Header], key: String): String =
carrier.find(_.name.toString == key).map(_.value.toString).orNull
}

val routes: HttpRoutes[AppTask] = HttpRoutes.of[AppTask] { case request @ GET -> Root / "status" =>
val response = for {
_ <- Tracing.addEvent("event from backend before response")
response <- Ok(ServiceStatus.up("backend").asJson)
_ <- Tracing.addEvent("event from backend after response")
} yield response
val routes: HttpApp[Tracing, Throwable] =
Http.collectM { case request @ Method.GET -> Root / "status" =>
val response = for {
_ <- Tracing.addEvent("event from backend before response")
response <- ZIO.succeed(Response.jsonString(ServiceStatus.up("backend").toJson))
_ <- Tracing.addEvent("event from backend after response")
} yield response

response.spanFrom(propagator, request.headers, getter, "/status", SpanKind.SERVER)

}
response.spanFrom(propagator, request.headers, getter, "/status", SpanKind.SERVER)
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package zio.telemetry.opentelemetry.example.http

import io.circe._
import io.circe.generic.semiauto._
import zio.json.{ DeriveJsonCodec, JsonCodec }

final case class Statuses(data: List[Status]) extends AnyVal

object Statuses {
implicit val decoder: Decoder[Statuses] = deriveDecoder
implicit val encoder: Encoder[Statuses] = deriveEncoder
implicit val codec: JsonCodec[Statuses] = DeriveJsonCodec.gen[Statuses]
}
Loading

0 comments on commit 548c720

Please sign in to comment.