Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OtelJava.autoConfigured() #420

Merged
merged 2 commits into from
Jan 18, 2024
Merged
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
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought these aliases appeared in Scaladoc, but proved to myself that's not the case. I don't mind them as long as they don't add any public aliases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having the type of the function be two lines long was just too much for me

}
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](
iRevive marked this conversation as resolved.
Show resolved Hide resolved
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