diff --git a/docs/opentelemetry-example.md b/docs/opentelemetry-example.md index 275278a7..9ca85340 100644 --- a/docs/opentelemetry-example.md +++ b/docs/opentelemetry-example.md @@ -20,12 +20,11 @@ docker run --rm -it \ jaegertracing/all-in-one:1.47 ``` -To run Seq, you also need to specify an admin password: +To run Seq, you also need to specify an admin password (user is `admin`): ```bash PH=$(echo 'admin123' | docker run --rm -i datalust/seq config hash) docker run \ - --name seq \ -d \ --restart unless-stopped \ -e ACCEPT_EULA=Y \ diff --git a/docs/opentelemetry-instrumentation-example.md b/docs/opentelemetry-instrumentation-example.md index e7560e0d..8ca7fb02 100644 --- a/docs/opentelemetry-instrumentation-example.md +++ b/docs/opentelemetry-instrumentation-example.md @@ -5,14 +5,12 @@ title: "OpenTelemetry Automatic Instrumentation Example" You can find the source code [here](https://github.com/zio/zio-telemetry/tree/series/2.x/opentelemetry-instrumentation-example). -Firstly, download OpenTelemetry JVM agent JAR: -```bash -OTEL_AGENT_PATH=$(cs fetch --classpath "io.opentelemetry.javaagent:opentelemetry-javaagent:latest.release") - ``` +Firstly, we need to start the observability backends ([Jaeger](https://www.jaegertracing.io/) and [Seq](https://datalust.co/seq)) -Then start Jaeger by running the following command: +Start Jaeger by running the following command: ```bash docker run --rm -it \ + -d \ -e COLLECTOR_OTLP_ENABLED=true \ -p 14250:14250 \ -p 16686:16686 \ @@ -20,12 +18,36 @@ docker run --rm -it \ jaegertracing/all-in-one:1.47 ``` +To run Seq, you also need to specify an admin password (user is `admin`): +```bash +PH=$(echo 'admin123' | docker run --rm -i datalust/seq config hash) + +docker run \ + -d \ + --restart unless-stopped \ + -e ACCEPT_EULA=Y \ + -e SEQ_FIRSTRUN_ADMINPASSWORDHASH="$PH" \ + -p 80:80 \ + -p 5341:5341 \ + datalust/seq +``` + +After this, we can kick off our application to generate some metrics. + +For this, we have to download OpenTelemetry JVM agent JAR: +```bash +OTEL_AGENT_PATH=$(cs fetch --classpath "io.opentelemetry.javaagent:opentelemetry-javaagent:latest.release") + ``` + Then start the server application ```bash sbt -J-javaagent:$OTEL_AGENT_PATH \ -J-Dotel.service.name=example-server \ -J-Dotel.traces.sampler=always_on \ -J-Dotel.traces.exporter=otlp \ + -J-Dotel.logs.exporter=otlp \ + -J-Dotel.exporter.otlp.logs.protocol="http/protobuf" \ + -J-Dotel.exporter.otlp.logs.endpoint="http://localhost:5341/ingest/otlp/v1/logs" \ -J-Dotel.metrics.exporter=none \ "opentelemetryInstrumentationExample/runMain zio.telemetry.opentelemetry.instrumentation.example.ServerApp" ``` @@ -40,4 +62,5 @@ sbt -J-javaagent:$OTEL_AGENT_PATH \ "opentelemetryInstrumentationExample/runMain zio.telemetry.opentelemetry.instrumentation.example.ClientApp" ``` -Head over to [http://localhost:16686/](http://localhost:16686/) to see the result. +Head over to [Jaeger UI](http://localhost:16686/) and [Seq UI](http://localhost:80/) to see the result. + diff --git a/opentelemetry-example/src/main/scala/zio/telemetry/opentelemetry/example/otel/JaegerTracer.scala b/opentelemetry-example/src/main/scala/zio/telemetry/opentelemetry/example/otel/JaegerTracer.scala index 5652bd42..cff1272d 100644 --- a/opentelemetry-example/src/main/scala/zio/telemetry/opentelemetry/example/otel/JaegerTracer.scala +++ b/opentelemetry-example/src/main/scala/zio/telemetry/opentelemetry/example/otel/JaegerTracer.scala @@ -9,14 +9,13 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor import io.opentelemetry.semconv.resource.attributes.ResourceAttributes import zio._ -import zio.telemetry.opentelemetry.example.config.AppConfig /** * https://www.jaegertracing.io/ */ object JaegerTracer { - def live(resourceName: String, instrumentationScopeName: String): RLayer[AppConfig, Tracer] = + def live(resourceName: String, instrumentationScopeName: String): TaskLayer[Tracer] = ZLayer( for { spanExporter <- ZIO.attempt(OtlpGrpcSpanExporter.builder().build()) diff --git a/opentelemetry-instrumentation-example/src/main/resources/logback.xml b/opentelemetry-instrumentation-example/src/main/resources/logback.xml new file mode 100644 index 00000000..f63874cf --- /dev/null +++ b/opentelemetry-instrumentation-example/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + diff --git a/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/ServerApp.scala b/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/ServerApp.scala index e5a65562..abdd50fb 100644 --- a/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/ServerApp.scala +++ b/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/ServerApp.scala @@ -1,7 +1,9 @@ package zio.telemetry.opentelemetry.instrumentation.example -import io.opentelemetry.api.GlobalOpenTelemetry +import io.opentelemetry.api.{GlobalOpenTelemetry, OpenTelemetry} import io.opentelemetry.api.trace.Tracer +import io.opentelemetry.instrumentation.logback.appender.v1_0.OpenTelemetryAppender +import zio.logging.backend.SLF4J import zio._ import zio.config.ReadError import zio.config.typesafe.TypesafeConfig @@ -13,24 +15,36 @@ import zio.telemetry.opentelemetry.tracing.Tracing object ServerApp extends ZIOAppDefault { + override val bootstrap: ZLayer[ZIOAppArgs, Any, Any] = + Runtime.removeDefaultLoggers >>> SLF4J.slf4j + + private val instrumentationScopeName = "zio.telemetry.opentelemetry.instrumentation.example.ServerApp" + private val configLayer: Layer[ReadError[String], AppConfig] = TypesafeConfig.fromResourcePath(descriptor[AppConfig]) private val globalTracerLayer: TaskLayer[Tracer] = ZLayer.fromZIO( - ZIO.attempt(GlobalOpenTelemetry.getTracer("zio.telemetry.opentelemetry.instrumentation.example.ServerApp")) + ZIO.attempt(GlobalOpenTelemetry.getTracer(instrumentationScopeName)) ) + private val globalOpenTelemetry: TaskLayer[OpenTelemetry] = + ZLayer(ZIO.attempt(GlobalOpenTelemetry.get())) + override def run: Task[ExitCode] = - ZIO - .serviceWithZIO[HttpServer](_.start.exitCode) - .provide( - configLayer, - HttpServer.live, - HttpServerApp.live, - Tracing.live, - globalTracerLayer, - ContextStorage.native - ) + (for { + server <- ZIO.service[HttpServer] + openTelemetry <- ZIO.service[OpenTelemetry] + _ <- ZIO.attempt(OpenTelemetryAppender.install(openTelemetry)) + exitCode <- server.start.exitCode + } yield exitCode).provide( + configLayer, + HttpServer.live, + HttpServerApp.live, + Tracing.live, + ContextStorage.native, + globalTracerLayer, + globalOpenTelemetry + ) } diff --git a/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServer.scala b/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServer.scala index 37dce56c..828b53b9 100644 --- a/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServer.scala +++ b/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServer.scala @@ -2,13 +2,12 @@ package zio.telemetry.opentelemetry.instrumentation.example.http import zio._ import zio.http._ -import zio.Console.printLine import zio.telemetry.opentelemetry.instrumentation.example.config.AppConfig case class HttpServer(config: AppConfig, httpServerApp: HttpServerApp) { def start: ZIO[Any, Throwable, Nothing] = - printLine(s"Starting HttpServer on port ${config.server.port}") *> + ZIO.logInfo(s"Starting HttpServer on port ${config.server.port}") *> Server.serve(httpServerApp.routes).provide(Server.defaultWithPort(config.server.port)) } diff --git a/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServerApp.scala b/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServerApp.scala index 5c634dc9..0ac414e4 100644 --- a/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServerApp.scala +++ b/opentelemetry-instrumentation-example/src/main/scala/zio/telemetry/opentelemetry/instrumentation/example/http/HttpServerApp.scala @@ -17,6 +17,7 @@ case class HttpServerApp(tracing: Tracing) { for { _ <- tracing.addEvent("executing health logic") _ <- tracing.setAttribute("zio", "telemetry") + _ <- ZIO.logInfo("health processing finished on the server") response <- ZIO.succeed(Response.ok) } yield response diff --git a/project/Dependencies.scala b/project/Dependencies.scala index ccee23ed..785dce6b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -11,28 +11,32 @@ object Dependencies { } object Orgs { - val zio = "dev.zio" - val opentracing = "io.opentracing" - val opentelemetry = "io.opentelemetry" - val opencensus = "io.opencensus" - val jaegertracing = "io.jaegertracing" - val scalaLangModules = "org.scala-lang.modules" - val typelevel = "org.typelevel" - val softwaremillSttpClient3 = "com.softwaremill.sttp.client3" - val slf4j = "org.slf4j" - val grpc = "io.grpc" + val zio = "dev.zio" + val opentracing = "io.opentracing" + val opentelemetry = "io.opentelemetry" + val opentelemetryInstrumentation = "io.opentelemetry.instrumentation" + val opencensus = "io.opencensus" + val jaegertracing = "io.jaegertracing" + val scalaLangModules = "org.scala-lang.modules" + val typelevel = "org.typelevel" + val softwaremillSttpClient3 = "com.softwaremill.sttp.client3" + val slf4j = "org.slf4j" + val grpc = "io.grpc" + val logback = "ch.qos.logback" } private object ExampleVersions { - val cats = "2.7.0" - val grpcNetty = "1.47.0" - val jaeger = "1.8.0" - val slf4j = "1.7.36" - val sttp3 = "3.7.0" - val zipkin = "2.16.3" - val zioJson = "0.3.0-RC10" - val zioConfig = "3.0.1" - val zioHttp = "3.0.0-RC2" + val cats = "2.7.0" + val grpcNetty = "1.47.0" + val jaeger = "1.8.0" + val slf4j = "1.7.36" + val sttp3 = "3.7.0" + val zipkin = "2.16.3" + val zioJson = "0.3.0-RC10" + val zioConfig = "3.0.1" + val zioHttp = "3.0.0-RC2" + val zioLogging = "2.1.15" + val logback = "1.4.11" } lazy val zio = Seq( @@ -88,7 +92,15 @@ object Dependencies { ) lazy val opentelemetryInstrumentationExample = example ++ Seq( - Orgs.zio %% "zio-http" % ExampleVersions.zioHttp + Orgs.opentelemetry % "opentelemetry-exporter-otlp" % Versions.opentelemetry, + Orgs.opentelemetry % "opentelemetry-sdk" % Versions.opentelemetry, + Orgs.grpc % "grpc-netty-shaded" % ExampleVersions.grpcNetty, + Orgs.opentelemetryInstrumentation % "opentelemetry-logback-appender-1.0" % s"${Versions.opentelemetry}-alpha", + Orgs.zio %% "zio-http" % ExampleVersions.zioHttp, + Orgs.zio %% "zio-logging" % ExampleVersions.zioLogging, + Orgs.zio %% "zio-logging-slf4j2" % ExampleVersions.zioLogging, + Orgs.logback % "logback-classic" % ExampleVersions.logback, + Orgs.logback % "logback-core" % ExampleVersions.logback ) }