Skip to content

Commit

Permalink
Merge pull request #420 from NthPortal/OtelJava-autoconfig/PR
Browse files Browse the repository at this point in the history
Add `OtelJava.autoConfigured()`
  • Loading branch information
NthPortal authored Jan 18, 2024
2 parents 0500ffd + 1bc0183 commit 25cafa7
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 126 deletions.
1 change: 1 addition & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ lazy val oteljava = project
name := "otel4s-oteljava",
libraryDependencies ++= Seq(
"io.opentelemetry" % "opentelemetry-sdk" % OpenTelemetryVersion,
"io.opentelemetry" % "opentelemetry-sdk-extension-autoconfigure" % OpenTelemetryVersion,
"io.opentelemetry" % "opentelemetry-sdk-testing" % OpenTelemetryVersion % Test
)
)
Expand Down
54 changes: 24 additions & 30 deletions docs/customization/histogram-custom-buckets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ import cats.effect.std.Random
import cats.syntax.flatMap._
import cats.syntax.functor._
import cats.syntax.parallel._
import io.opentelemetry.sdk.OpenTelemetrySdk
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk
import io.opentelemetry.sdk.metrics.Aggregation
import io.opentelemetry.sdk.metrics.InstrumentSelector
import io.opentelemetry.sdk.metrics.InstrumentType
Expand Down Expand Up @@ -146,9 +144,7 @@ object HistogramBucketsExample extends IOApp.Simple {
} yield ()

def program[F[_] : Async : LiftIO : Parallel : Console]: F[Unit] =
Resource
.eval(configureSdk[F])
.evalMap(OtelJava.forAsync[F])
configureSdk[F]
.evalMap(_.meterProvider.get("histogram-example"))
.use { meter =>
for {
Expand All @@ -161,32 +157,30 @@ object HistogramBucketsExample extends IOApp.Simple {
def run: IO[Unit] =
program[IO]

private def configureSdk[F[_] : Sync]: F[OpenTelemetrySdk] = Sync[F].delay {
AutoConfiguredOpenTelemetrySdk
.builder()
.addMeterProviderCustomizer { (meterProviderBuilder, _) =>
meterProviderBuilder
.registerView(
InstrumentSelector
.builder()
.setName("service.work.duration")
.setType(InstrumentType.HISTOGRAM)
.build(),
View
.builder()
.setName("service.work.duration")
.setAggregation(
Aggregation.explicitBucketHistogram(
java.util.Arrays.asList(.005, .01, .025, .05, .075, .1, .25, .5)
private def configureSdk[F[_] : Async : LiftIO]: Resource[F, OtelJava[F]] =
OtelJava.autoConfigured { sdkBuilder =>
sdkBuilder
.addMeterProviderCustomizer { (meterProviderBuilder, _) =>
meterProviderBuilder
.registerView(
InstrumentSelector
.builder()
.setName("service.work.duration")
.setType(InstrumentType.HISTOGRAM)
.build(),
View
.builder()
.setName("service.work.duration")
.setAggregation(
Aggregation.explicitBucketHistogram(
java.util.Arrays.asList(.005, .01, .025, .05, .075, .1, .25, .5)
)
)
)
.build()
)
}
.setResultAsGlobal
.build()
.getOpenTelemetrySdk
}
.build()
)
}
.setResultAsGlobal
}
}
```

Expand Down
40 changes: 21 additions & 19 deletions docs/examples/grafana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,26 +239,28 @@ object ApiService {

object ExampleService extends IOApp.Simple {
def run: IO[Unit] =
OtelJava.global.flatMap { otel4s =>
(
otel4s.tracerProvider.get("com.service.runtime"),
otel4s.meterProvider.get("com.service.runtime"),
Random.scalaUtilRandom[IO]
).flatMapN { case components =>
implicit val (tracer: Tracer[IO], meter: Meter[IO], random: Random[IO]) =
components

for {
service <- ApiService[IO](
minLatency = 40,
maxLatency = 80,
bananaPercentage = 70
)
data <- service.getDataFromSomeAPI
_ <- IO.println(s"Service data: $data")
} yield ()
OtelJava.autoConfigured()
.evalMap { otel4s =>
(
otel4s.tracerProvider.get("com.service.runtime"),
otel4s.meterProvider.get("com.service.runtime"),
Random.scalaUtilRandom[IO]
).flatMapN { case components =>
implicit val (tracer: Tracer[IO], meter: Meter[IO], random: Random[IO]) =
components

for {
service <- ApiService[IO](
minLatency = 40,
maxLatency = 80,
bananaPercentage = 70
)
data <- service.getDataFromSomeAPI
_ <- IO.println(s"Service data: $data")
} yield ()
}
}
}
.use_
}
```

Expand Down
22 changes: 12 additions & 10 deletions docs/examples/honeycomb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,18 @@ object Work {

object TracingExample extends IOApp.Simple {
def run: IO[Unit] = {
OtelJava.global.flatMap { otel4s =>
otel4s.tracerProvider.get("com.service.runtime")
.flatMap { implicit tracer: Tracer[IO] =>
for {
meter <- otel4s.meterProvider.get("com.service.runtime")
histogram <- meter.histogram("work.execution.duration").create
_ <- Work[IO](histogram).doWork
} yield ()
}
}
OtelJava.autoConfigured()
.evalMap { otel4s =>
otel4s.tracerProvider.get("com.service.runtime")
.flatMap { implicit tracer: Tracer[IO] =>
for {
meter <- otel4s.meterProvider.get("com.service.runtime")
histogram <- meter.histogram("work.execution.duration").create
_ <- Work[IO](histogram).doWork
} yield ()
}
}
.use_
}
}
```
Expand Down
17 changes: 9 additions & 8 deletions docs/examples/jaeger-docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ $ docker run --name jaeger \
### Application example

```scala mdoc:silent
import cats.effect.{Async, IO, IOApp}
import cats.effect.{Async, IO, IOApp, Resource}
import cats.effect.std.Console
import cats.effect.std.Random
import cats.syntax.all._
Expand Down Expand Up @@ -118,14 +118,15 @@ object Work {
}

object TracingExample extends IOApp.Simple {
def tracer: IO[Tracer[IO]] =
OtelJava.global.flatMap(_.tracerProvider.get("Example"))
def tracer: Resource[IO, Tracer[IO]] =
OtelJava.autoConfigured().evalMap(_.tracerProvider.get("Example"))

def run: IO[Unit] = {
tracer.flatMap { implicit tracer: Tracer[IO] =>
Work[IO].doWork
}
}
def run: IO[Unit] =
tracer
.evalMap { implicit tracer: Tracer[IO] =>
Work[IO].doWork
}
.use_
}
```

Expand Down
11 changes: 6 additions & 5 deletions docs/instrumentation/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ import cats.effect.IO
import org.typelevel.otel4s.trace.Tracer
import org.typelevel.otel4s.oteljava.OtelJava

OtelJava.global.flatMap { otel4s =>
otel4s.tracerProvider.get("com.service").flatMap { implicit tracer: Tracer[IO] =>
val _ = tracer // use tracer here
???
OtelJava.autoConfigured[IO]()
.evalMap { otel4s =>
otel4s.tracerProvider.get("com.service").flatMap { implicit tracer: Tracer[IO] =>
val _ = tracer // use tracer here
???
}
}
}
```

### Creating a span
Expand Down
4 changes: 2 additions & 2 deletions examples/src/main/scala/ObservableExample.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ object ObservableExample extends IOApp.Simple {
val mbeanName = new ObjectName("cats.effect.metrics:type=CpuStarvation")

def meterResource: Resource[IO, ObservableCounter] =
Resource
.eval(OtelJava.global)
OtelJava
.autoConfigured()
.evalMap(_.meterProvider.get("observable-example"))
.flatMap(
_.observableCounter("cats-effect-runtime-cpu-starvation-count")
Expand Down
54 changes: 28 additions & 26 deletions examples/src/main/scala/TraceExample.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,31 +124,33 @@ object TraceExample extends IOApp.Simple {
* to acquire and then 100 to shutdown, but in the middle are the child spans
* from our UserIdsAlg.
*/
def run: IO[Unit] = {
OtelJava.global.flatMap { (otel4s: Otel4s[IO]) =>
otel4s.tracerProvider.tracer("TraceExample").get.flatMap {
implicit tracer: Tracer[IO] =>
val userIdAlg = UserIdsAlg.apply[IO](
InstitutionServiceClient.apply[IO],
UserDatabase.apply[IO]
)
tracer
.span("Start up")
.use { span =>
for {
_ <- tracer.span("acquire").surround(IO.sleep(50.millis))
_ <- span.addEvent("event")
_ <- tracer.span("use").surround {
userIdAlg
.getAllUsersForInstitution(
"9902181e-1d8d-4e00-913d-51532b493f1b"
)
.flatMap(IO.println)
}
_ <- tracer.span("release").surround(IO.sleep(100.millis))
} yield ()
}
def run: IO[Unit] =
OtelJava
.autoConfigured()
.evalMap { (otel4s: Otel4s[IO]) =>
otel4s.tracerProvider.tracer("TraceExample").get.flatMap {
implicit tracer: Tracer[IO] =>
val userIdAlg = UserIdsAlg.apply[IO](
InstitutionServiceClient.apply[IO],
UserDatabase.apply[IO]
)
tracer
.span("Start up")
.use { span =>
for {
_ <- tracer.span("acquire").surround(IO.sleep(50.millis))
_ <- span.addEvent("event")
_ <- tracer.span("use").surround {
userIdAlg
.getAllUsersForInstitution(
"9902181e-1d8d-4e00-913d-51532b493f1b"
)
.flatMap(IO.println)
}
_ <- tracer.span("release").surround(IO.sleep(100.millis))
} yield ()
}
}
}
}
}
.use_
}
54 changes: 28 additions & 26 deletions examples/src/main/scala/TracingExample.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,33 +57,35 @@ object Work {
}

object TracingExample extends IOApp.Simple {
def run: IO[Unit] = {
OtelJava.global.flatMap { (otel4s: Otel4s[IO]) =>
otel4s.tracerProvider.tracer("example").get.flatMap {
implicit tracer: Tracer[IO] =>
tracer
.span("resource")
.resource
.use { res =>
res.trace {
for {
_ <- tracer.span("acquire").surround(IO.sleep(50.millis))
_ <- tracer.span("use").surround {
Work[IO].request(
Map(
"X-B3-TraceId" -> "80f198ee56343ba864fe8b2a57d3eff7",
"X-B3-ParentSpanId" -> "05e3ac9a4f6e3b90",
"X-B3-SpanId" -> "e457b5a2e4d86bd1",
"X-B3-Sampled" -> "1"
def run: IO[Unit] =
OtelJava
.autoConfigured()
.evalMap { (otel4s: Otel4s[IO]) =>
otel4s.tracerProvider.tracer("example").get.flatMap {
implicit tracer: Tracer[IO] =>
tracer
.span("resource")
.resource
.use { res =>
res.trace {
for {
_ <- tracer.span("acquire").surround(IO.sleep(50.millis))
_ <- tracer.span("use").surround {
Work[IO].request(
Map(
"X-B3-TraceId" -> "80f198ee56343ba864fe8b2a57d3eff7",
"X-B3-ParentSpanId" -> "05e3ac9a4f6e3b90",
"X-B3-SpanId" -> "e457b5a2e4d86bd1",
"X-B3-Sampled" -> "1"
)
)
)
}
_ <- res.span.addEvent("event")
_ <- tracer.span("release").surround(IO.sleep(100.millis))
} yield ()
}
_ <- res.span.addEvent("event")
_ <- tracer.span("release").surround(IO.sleep(100.millis))
} yield ()
}
}
}
}
}
}
}
.use_
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ import cats.syntax.all._
import io.opentelemetry.api.{OpenTelemetry => JOpenTelemetry}
import io.opentelemetry.api.GlobalOpenTelemetry
import io.opentelemetry.sdk.{OpenTelemetrySdk => JOpenTelemetrySdk}
import io.opentelemetry.sdk.autoconfigure.{
AutoConfiguredOpenTelemetrySdk => AutoConfigOtelSdk
}
import io.opentelemetry.sdk.autoconfigure.{
AutoConfiguredOpenTelemetrySdkBuilder => AutoConfigOtelSdkBuilder
}
import io.opentelemetry.sdk.common.CompletableResultCode
import org.typelevel.otel4s.Otel4s
import org.typelevel.otel4s.context.propagation.ContextPropagators
Expand Down Expand Up @@ -97,8 +103,38 @@ object OtelJava {
)
.evalMap(forAsync[F])

/** Creates a [[cats.effect.Resource `Resource`]] of the automatic
* configuration of a Java `OpenTelemetrySdk` instance.
*
* If you rely on
* [[https://opentelemetry.io/docs/instrumentation/java/automatic/ automatic instrumentation via Java agent]],
* you MUST NOT use this method and MUST use [[global]] instead.
*
* @param customize
* A function for customizing the auto-configured SDK builder. This
* function MUST NOT call `setResultAsGlobal`.
* @return
* An [[org.typelevel.otel4s.Otel4s]] resource.
* @see
* [[global]]
*/
def autoConfigured[F[_]: LiftIO: Async](
customize: AutoConfigOtelSdkBuilder => AutoConfigOtelSdkBuilder = identity
): Resource[F, OtelJava[F]] =
resource {
Sync[F].delay {
customize(AutoConfigOtelSdk.builder())
.disableShutdownHook()
.build()
.getOpenTelemetrySdk
}
}

/** Creates an [[org.typelevel.otel4s.Otel4s]] from the global Java
* OpenTelemetry instance.
*
* @see
* [[autoConfigured]]
*/
def global[F[_]: LiftIO: Async]: F[OtelJava[F]] =
Sync[F].delay(GlobalOpenTelemetry.get).flatMap(forAsync[F])
Expand Down

0 comments on commit 25cafa7

Please sign in to comment.