diff --git a/build.sbt b/build.sbt index 208550fbb..b190eca38 100644 --- a/build.sbt +++ b/build.sbt @@ -76,7 +76,7 @@ ThisBuild / mergifyPrRules ++= Seq( ) val CatsVersion = "2.11.0" -val CatsEffectVersion = "3.6-28f8f29" +val CatsEffectVersion = "3.6-d5f779e-20241219T080448Z-SNAPSHOT" val CatsMtlVersion = "1.4.0" val FS2Version = "3.11.0" val MUnitVersion = "1.0.0" @@ -714,7 +714,7 @@ lazy val `oteljava-context-storage` = project ), Test / javaOptions ++= Seq( "-Dotel.java.global-autoconfigure.enabled=true", - "-Dcats.effect.ioLocalPropagation=true", + "-Dcats.effect.trackFiberContext=true", ), Test / fork := true, ) @@ -868,7 +868,7 @@ lazy val examples = project javaAgents += "io.opentelemetry.javaagent" % "opentelemetry-javaagent" % OpenTelemetryInstrumentationVersion % Runtime, run / fork := true, javaOptions += "-Dotel.java.global-autoconfigure.enabled=true", - javaOptions += "-Dcats.effect.ioLocalPropagation=true", + javaOptions += "-Dcats.effect.trackFiberContext=true", envVars ++= Map( "OTEL_PROPAGATORS" -> "b3multi", "OTEL_SERVICE_NAME" -> "Trace Example" diff --git a/oteljava/context-storage/src/main/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorage.scala b/oteljava/context-storage/src/main/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorage.scala index 493dc26ad..f44af666a 100644 --- a/oteljava/context-storage/src/main/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorage.scala +++ b/oteljava/context-storage/src/main/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorage.scala @@ -19,6 +19,7 @@ package org.typelevel.otel4s.oteljava import cats.effect.IOLocal import cats.effect.LiftIO import cats.effect.MonadCancelThrow +import cats.effect.unsafe.IORuntime import cats.mtl.Local import io.opentelemetry.context.{Context => JContext} import io.opentelemetry.context.ContextStorage @@ -35,7 +36,20 @@ import org.typelevel.otel4s.oteljava.context.LocalContext */ class IOLocalContextStorage(_ioLocal: () => IOLocal[Context]) extends ContextStorage { private[this] implicit lazy val ioLocal: IOLocal[Context] = _ioLocal() - private[this] lazy val unsafeThreadLocal = ioLocal.unsafeThreadLocal() + private[this] lazy val unsafeThreadLocal: ThreadLocal[Context] = { + val fiberLocal = ioLocal.unsafeThreadLocal() + + new ThreadLocal[Context] { + override def initialValue(): Context = + Context.root + + override def get(): Context = + if (IORuntime.isUnderFiberContext()) fiberLocal.get() else super.get() + + override def set(value: Context): Unit = + if (IORuntime.isUnderFiberContext()) fiberLocal.set(value) else super.set(value) + } + } @inline private[this] def unsafeCurrent: Context = unsafeThreadLocal.get() @@ -82,7 +96,7 @@ object IOLocalContextStorage { } else { F.raiseError( new IllegalStateException( - "IOLocal propagation must be enabled with: -Dcats.effect.ioLocalPropagation=true" + "IOLocal propagation must be enabled with: -Dcats.effect.trackFiberContext=true" ) ) } diff --git a/oteljava/context-storage/src/test/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorageSuite.scala b/oteljava/context-storage/src/test/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorageSuite.scala index 550d6b1fb..a6f6a913f 100644 --- a/oteljava/context-storage/src/test/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorageSuite.scala +++ b/oteljava/context-storage/src/test/scala/org/typelevel/otel4s/oteljava/IOLocalContextStorageSuite.scala @@ -78,8 +78,7 @@ class IOLocalContextStorageSuite extends CatsEffectSuite { } } - // see https://discord.com/channels/632277896739946517/839263556754472990/1317163027451088926 - test("works as a Java-only ContextStorage".ignore) { + test("works as a Java-only ContextStorage") { usingModifiedCtx(_.`with`(key1, "1")) { assertEquals(Option(jCurrent.get(key1)), Some("1")) assertEquals(Option(jCurrent.get(key2)), None)