Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Versions.zioHttp
import com.softwaremill.Publish.{ossPublishSettings, updateDocs}
import com.softwaremill.SbtSoftwareMillBrowserTestJS._
import com.softwaremill.SbtSoftwareMillCommon.commonSmlBuildSettings
Expand Down Expand Up @@ -192,6 +193,7 @@ lazy val rawAllAggregates = core.projectRefs ++
opentelemetryTracing.projectRefs ++
otel4sMetrics.projectRefs ++
otel4sTracing.projectRefs ++
zioTracing.projectRefs ++
json4s.projectRefs ++
playJson.projectRefs ++
play29Json.projectRefs ++
Expand Down Expand Up @@ -1177,6 +1179,31 @@ lazy val otel4sMetrics: ProjectMatrix = (projectMatrix in file("metrics/otel4s-m
.jvmPlatform(scalaVersions = scala2_13And3Versions, settings = commonJvmSettings)
.dependsOn(serverCore % CompileAndTest, catsEffect % Test)

lazy val zioTracing: ProjectMatrix = (projectMatrix in file("tracing/zio-tracing"))
.dependsOn(zio, zioHttpServer)
.settings(commonSettings)
.settings(
name := "tapir-zio-tracing",
libraryDependencies ++= Seq(
"dev.zio" %% "zio-logging" % Versions.zioLogging,
"dev.zio" %% "zio-logging-slf4j2" % Versions.zioLogging,
"dev.zio" %% "zio-opentelemetry" % Versions.zioOpenTelemetry,
"dev.zio" %% "zio-opentelemetry-zio-logging" % Versions.zioOpenTelemetry,
"io.opentelemetry.semconv" % "opentelemetry-semconv" % Versions.openTelemetrySemconvVersion,
"io.opentelemetry" % "opentelemetry-sdk" % Versions.openTelemetry,
"io.opentelemetry" % "opentelemetry-exporter-otlp" % Versions.openTelemetry,
"io.opentelemetry" % "opentelemetry-exporter-logging-otlp" % Versions.openTelemetry,
"io.opentelemetry.instrumentation" % "opentelemetry-runtime-telemetry-java17" % Versions.openTelemetryRuntime,

"dev.zio" %% "zio-test" % Versions.zio % Test,
"dev.zio" %% "zio-test-sbt" % Versions.zio % Test,

"io.opentelemetry" % "opentelemetry-sdk-testing" % Versions.openTelemetry % Test
)
)
.jvmPlatform(scalaVersions = scala2And3Versions, settings = commonJvmSettings)
.dependsOn(serverCore % CompileAndTest)

// docs

lazy val apispecDocs: ProjectMatrix = (projectMatrix in file("docs/apispec-docs"))
Expand Down
5 changes: 4 additions & 1 deletion project/Versions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ object Versions {
val zioInteropCats = "23.1.0.13"
val zioInteropReactiveStreams = "2.0.2"
val zioJson = "0.7.44"
val zioLogging = "2.5.2"
val zioOpenTelemetry = "3.1.15"
val playClient = "3.0.11"
val playServer = "3.0.10"
val play29Client = "2.2.15"
Expand All @@ -63,7 +65,8 @@ object Versions {
val fs2 = "3.13.0"
val decline = "2.6.2"
val quicklens = "1.9.12"
val openTelemetry = "1.62.0"
val openTelemetry = "1.61.0"
val openTelemetryRuntime = "2.27.0-alpha"
val openTelemetrySemconvVersion = "1.41.0"
val mockServer = "5.15.0"
val dogstatsdClient = "4.4.5"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package sttp.tapir.server.tracing.ziotel

import zio.ZIOApp

/** ZIOpenTelemetry is a trait that provides a ZIO layer for OpenTelemetry.
* @param name
*/
trait ZIOpenTelemetry extends ZIOtelBase {
this: ZIOApp =>

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package sttp.tapir.server.tracing.ziotel

import zio.ZIOApp

/** ZIOpenTelemetry is a trait that provides a ZIO layer for OpenTelemetry.
* @param name
*/
trait ZIOpenTelemetry(val resourceName: String) extends ZIOtelBase {
this: ZIOApp =>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package sttp.tapir.server.tracing.ziotel

import io.opentelemetry.api.common.Attributes

import io.opentelemetry.sdk.logs.SdkLoggerProvider
import io.opentelemetry.sdk.logs.`export`.SimpleLogRecordProcessor
import io.opentelemetry.sdk.resources.Resource
import zio._

import io.opentelemetry.semconv.ServiceAttributes
import io.opentelemetry.exporter.otlp.logs.OtlpGrpcLogRecordExporter

object LoggerProvider extends OltpEndpoint {

/** gRPC exporter that sends logs to the endpoint specified in the environment variable.
*
* If the environment variable is not set, will fallback OTEL_EXPORTER_OTLP_ENDPOINT env var or "http://localhost:4317".
*/
def grpc(resourceName: String, envVar: String): RIO[Scope, SdkLoggerProvider] =
for {
logRecordExporter <-
ZIO.fromAutoCloseable(
ZIO.succeed(
OtlpGrpcLogRecordExporter
.builder()
.setEndpoint(getEndpoint(envVar))
.build()
)
)
logRecordProcessor <-
ZIO.fromAutoCloseable(
ZIO.succeed(SimpleLogRecordProcessor.create(logRecordExporter))
)
loggerProvider <-
ZIO.fromAutoCloseable(
ZIO.succeed(
SdkLoggerProvider
.builder()
.setResource(
Resource.create(
Attributes.of(ServiceAttributes.SERVICE_NAME, resourceName)
)
)
.addLogRecordProcessor(logRecordProcessor)
.build()
)
)
} yield loggerProvider

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package sttp.tapir.server.tracing.ziotel

import zio._
import io.opentelemetry.sdk.metrics.SdkMeterProvider
import io.opentelemetry.sdk.metrics.`export`.PeriodicMetricReader
import io.opentelemetry.sdk.resources.Resource
import io.opentelemetry.api.common.Attributes
import io.opentelemetry.semconv.ServiceAttributes
import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingMetricExporter
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter

object MeterProvider extends OltpEndpoint {

/** Prints to stdout in OTLP Json format
*/
def stdout(resourceName: String): RIO[Scope, SdkMeterProvider] =
for {
metricExporter <- ZIO.fromAutoCloseable(
ZIO.succeed(OtlpJsonLoggingMetricExporter.create())
)
metricReader <-
ZIO.fromAutoCloseable(
ZIO.succeed(
PeriodicMetricReader
.builder(metricExporter)
.setInterval(5.second)
.build()
)
)
meterProvider <-
ZIO.fromAutoCloseable(
ZIO.succeed(
SdkMeterProvider
.builder()
.registerMetricReader(metricReader)
.setResource(
Resource.create(
Attributes.of(ServiceAttributes.SERVICE_NAME, resourceName)
)
)
.build()
)
)
} yield meterProvider

/** gRPC exporter that sends metrics to the endpoint specified in the environment variable.
*
* If the environment variable is not set, will fallback OTEL_EXPORTER_OTLP_ENDPOINT env var or "http://localhost:4317".
*/
def grpc(resourceName: String, envVar: String): RIO[Scope, SdkMeterProvider] =
for {
metricExporter <- ZIO.fromAutoCloseable(
ZIO.succeed(OtlpGrpcMetricExporter.builder().setEndpoint(getEndpoint(envVar)).build())
)
metricReader <-
ZIO.fromAutoCloseable(
ZIO.succeed(
PeriodicMetricReader
.builder(metricExporter)
.setInterval(5.second)
.build()
)
)
meterProvider <-
ZIO.fromAutoCloseable(
ZIO.succeed(
SdkMeterProvider
.builder()
.registerMetricReader(metricReader)
.setResource(
Resource.create(
Attributes.of(ServiceAttributes.SERVICE_NAME, resourceName)
)
)
.build()
)
)
} yield meterProvider

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package sttp.tapir.server.tracing.ziotel

trait OltpEndpoint {

/** OTLP gRPC endpoint to export telemetry data to.
*
* It can be set via:
*
* - environment variable provided as `envVar`
* - environment variable "OTEL_EXPORTER_OTLP_ENDPOINT"
* - defaults to "http://localhost:4317"
*
* See https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#otel_exporter_otlp_endpoint.
*
* @param envVar
* @return
*/
protected def getEndpoint(envVar: String): String =
sys.env
.get(envVar)
.orElse(sys.env.get("OTEL_EXPORTER_OTLP_ENDPOINT"))
.getOrElse(
"http://localhost:4317"
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package sttp.tapir.server.tracing.ziotel

import io.opentelemetry.api.common.Attributes
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter
import io.opentelemetry.sdk.resources.Resource
import io.opentelemetry.sdk.trace.SdkTracerProvider
import io.opentelemetry.sdk.trace.`export`.SimpleSpanProcessor
import io.opentelemetry.semconv.ServiceAttributes
import zio._
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter
import io.opentelemetry.exporter.logging.otlp.OtlpJsonLoggingSpanExporter

object TracerProvider extends OltpEndpoint {

/** Prints to stdout in OTLP Json format
*/
def stdout(resourceName: String): RIO[Scope, SdkTracerProvider] =
for {
spanExporter <-
ZIO.fromAutoCloseable(ZIO.succeed(OtlpJsonLoggingSpanExporter.create()))
spanProcessor <- ZIO.fromAutoCloseable(
ZIO.succeed(SimpleSpanProcessor.create(spanExporter))
)
tracerProvider <-
ZIO.fromAutoCloseable(
ZIO.succeed(
SdkTracerProvider
.builder()
.setResource(
Resource.create(
Attributes.of(ServiceAttributes.SERVICE_NAME, resourceName)
)
)
.addSpanProcessor(spanProcessor)
.build()
)
)
} yield tracerProvider

/** gRPC exporter that sends spans to the endpoint specified in the environment variable.
*
* If the environment variable is not set, will fallback OTEL_EXPORTER_OTLP_ENDPOINT env var or "http://localhost:4317".
*/
def grpc(resourceName: String, envVar: String): RIO[Scope, SdkTracerProvider] =
for {
spanExporter <- ZIO.fromAutoCloseable(
ZIO.succeed(OtlpGrpcSpanExporter.builder().setEndpoint(getEndpoint(envVar)).build())
)
spanProcessor <- ZIO.fromAutoCloseable(
ZIO.succeed(SimpleSpanProcessor.create(spanExporter))
)
tracerProvider <-
ZIO.fromAutoCloseable(
ZIO.succeed(
SdkTracerProvider
.builder()
.setResource(
Resource.create(
Attributes.of(ServiceAttributes.SERVICE_NAME, resourceName)
)
)
.addSpanProcessor(spanProcessor)
.build()
)
)
} yield tracerProvider

/** https://fluentbit.io/
*/
def fluentbit(resourceName: String): RIO[Scope, SdkTracerProvider] =
for {
spanExporter <- ZIO.fromAutoCloseable(
ZIO.succeed(OtlpHttpSpanExporter.builder().build())
)
spanProcessor <- ZIO.fromAutoCloseable(
ZIO.succeed(SimpleSpanProcessor.create(spanExporter))
)
tracerProvider <-
ZIO.fromAutoCloseable(
ZIO.succeed(
SdkTracerProvider
.builder()
.setResource(
Resource.create(
Attributes.of(ServiceAttributes.SERVICE_NAME, resourceName)
)
)
.addSpanProcessor(spanProcessor)
.build()
)
)
} yield tracerProvider

}
Loading
Loading