From e6c7c4bdc09a8634836de5431bfbb4f5143368a7 Mon Sep 17 00:00:00 2001 From: Peter Kotula Date: Sun, 19 Nov 2023 18:56:35 +0100 Subject: [PATCH 1/4] slf4j bridge - init lock --- .../zio/logging/slf4j/bridge/Slf4jBridge.scala | 10 +++++++++- .../logging/slf4j/bridge/Slf4jBridgeSpec.scala | 13 +++++++++++++ .../zio/logging/slf4j/bridge/Slf4jBridge.scala | 16 ++++++++++++---- .../logging/slf4j/bridge/Slf4jBridgeSpec.scala | 13 +++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala b/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala index 4c54bd793..0348257cc 100644 --- a/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala +++ b/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala @@ -18,6 +18,8 @@ package zio.logging.slf4j.bridge import org.slf4j.impl.ZioLoggerFactory import zio.{ Runtime, ZIO, ZLayer } +import java.util.concurrent.locks.ReentrantLock + object Slf4jBridge { /** @@ -46,11 +48,17 @@ object Slf4jBridge { def initialize(nameAnnotationKey: String): ZLayer[Any, Nothing, Unit] = Runtime.enableCurrentFiber ++ layer(nameAnnotationKey) + private val initLock: ReentrantLock = new ReentrantLock() + private def layer(nameAnnotationKey: String): ZLayer[Any, Nothing, Unit] = ZLayer { ZIO.runtime[Any].flatMap { runtime => ZIO.succeed { - ZioLoggerFactory.initialize(new ZioLoggerRuntime(runtime, nameAnnotationKey)) + initLock.lock() + try + ZioLoggerFactory.initialize(new ZioLoggerRuntime(runtime, nameAnnotationKey)) + finally + initLock.unlock() } } } diff --git a/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala b/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala index ac71f0609..4d5d2d365 100644 --- a/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala +++ b/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala @@ -5,6 +5,8 @@ import org.slf4j.impl.StaticMarkerBinder import zio.test._ import zio.{ Cause, Chunk, LogLevel, ZIO, ZIOAspect } +import java.util.UUID + object Slf4jBridgeSpec extends ZIOSpecDefault { final case class LogEntry( @@ -17,6 +19,17 @@ object Slf4jBridgeSpec extends ZIOSpecDefault { override def spec = suite("Slf4jBridge")( + test("parallel init") { + val uuids = List.fill(5)(UUID.randomUUID()) + for { + _ <- + ZIO.foreachPar(uuids) { u => + ZIO + .succeed(org.slf4j.LoggerFactory.getLogger("SLF4J-LOGGER").warn("Test {} {}!", "WARNING", u.toString)) + .provide(Slf4jBridge.initialize) + } + } yield assertTrue(true) + }, test("logs through slf4j - legacy logger name annotation key") { val testFailure = new RuntimeException("test error") for { diff --git a/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala b/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala index 51e455425..74ff8897e 100644 --- a/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala +++ b/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala @@ -17,6 +17,8 @@ package zio.logging.slf4j.bridge import zio.{ Runtime, ZIO, ZLayer } +import java.util.concurrent.locks.ReentrantLock + object Slf4jBridge { /** @@ -29,14 +31,20 @@ object Slf4jBridge { */ def initializeWithoutFiberRefPropagation: ZLayer[Any, Nothing, Unit] = layer + private val initLock: ReentrantLock = new ReentrantLock() + private def layer: ZLayer[Any, Nothing, Unit] = ZLayer { ZIO.runtime[Any].flatMap { runtime => ZIO.succeed { - org.slf4j.LoggerFactory - .getILoggerFactory() - .asInstanceOf[LoggerFactory] - .attacheRuntime(new ZioLoggerRuntime(runtime)) + initLock.lock() + try + org.slf4j.LoggerFactory + .getILoggerFactory() + .asInstanceOf[LoggerFactory] + .attacheRuntime(new ZioLoggerRuntime(runtime)) + finally + initLock.unlock() } } } diff --git a/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala b/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala index 34af42417..2bc04eefa 100644 --- a/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala +++ b/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala @@ -3,6 +3,8 @@ package zio.logging.slf4j.bridge import zio.test._ import zio.{ Cause, Chunk, LogLevel, ZIO, ZIOAspect } +import java.util.UUID + object Slf4jBridgeSpec extends ZIOSpecDefault { final case class LogEntry( @@ -15,6 +17,17 @@ object Slf4jBridgeSpec extends ZIOSpecDefault { override def spec = suite("Slf4jBridge")( + test("parallel init") { + val uuids = List.fill(5)(UUID.randomUUID()) + for { + _ <- + ZIO.foreachPar(uuids) { u => + ZIO + .succeed(org.slf4j.LoggerFactory.getLogger("SLF4J-LOGGER").warn("Test {} {}!", "WARNING", u.toString)) + .provide(Slf4jBridge.initialize) + } + } yield assertTrue(true) + }, test("logs through slf4j") { val testFailure = new RuntimeException("test error") for { From 3251d5a2ab2a599064c9c562264d984a944171d4 Mon Sep 17 00:00:00 2001 From: Peter Kotula Date: Sun, 19 Nov 2023 19:19:14 +0100 Subject: [PATCH 2/4] test fix --- .../scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala | 9 +++------ .../scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala | 9 +++------ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala b/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala index 4d5d2d365..86bcb756e 100644 --- a/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala +++ b/slf4j-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala @@ -5,8 +5,6 @@ import org.slf4j.impl.StaticMarkerBinder import zio.test._ import zio.{ Cause, Chunk, LogLevel, ZIO, ZIOAspect } -import java.util.UUID - object Slf4jBridgeSpec extends ZIOSpecDefault { final case class LogEntry( @@ -20,15 +18,14 @@ object Slf4jBridgeSpec extends ZIOSpecDefault { override def spec = suite("Slf4jBridge")( test("parallel init") { - val uuids = List.fill(5)(UUID.randomUUID()) for { _ <- - ZIO.foreachPar(uuids) { u => + ZIO.foreachPar((1 to 5).toList) { _ => ZIO - .succeed(org.slf4j.LoggerFactory.getLogger("SLF4J-LOGGER").warn("Test {} {}!", "WARNING", u.toString)) + .succeed(org.slf4j.LoggerFactory.getLogger("SLF4J-LOGGER").warn("Test {}!", "WARNING")) .provide(Slf4jBridge.initialize) } - } yield assertTrue(true) + } yield assertCompletes }, test("logs through slf4j - legacy logger name annotation key") { val testFailure = new RuntimeException("test error") diff --git a/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala b/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala index 2bc04eefa..c4dd09bbb 100644 --- a/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala +++ b/slf4j2-bridge/src/test/scala/zio/logging/slf4j/bridge/Slf4jBridgeSpec.scala @@ -3,8 +3,6 @@ package zio.logging.slf4j.bridge import zio.test._ import zio.{ Cause, Chunk, LogLevel, ZIO, ZIOAspect } -import java.util.UUID - object Slf4jBridgeSpec extends ZIOSpecDefault { final case class LogEntry( @@ -18,15 +16,14 @@ object Slf4jBridgeSpec extends ZIOSpecDefault { override def spec = suite("Slf4jBridge")( test("parallel init") { - val uuids = List.fill(5)(UUID.randomUUID()) for { _ <- - ZIO.foreachPar(uuids) { u => + ZIO.foreachPar((1 to 5).toList) { _ => ZIO - .succeed(org.slf4j.LoggerFactory.getLogger("SLF4J-LOGGER").warn("Test {} {}!", "WARNING", u.toString)) + .succeed(org.slf4j.LoggerFactory.getLogger("SLF4J-LOGGER").warn("Test {}!", "WARNING")) .provide(Slf4jBridge.initialize) } - } yield assertTrue(true) + } yield assertCompletes }, test("logs through slf4j") { val testFailure = new RuntimeException("test error") From 05a5f715598faa167da55abddfb92b27a9866900 Mon Sep 17 00:00:00 2001 From: Peter Kotula Date: Wed, 22 Nov 2023 13:46:29 +0100 Subject: [PATCH 3/4] slf4j bridge - init lock with Semaphore --- .../logging/slf4j/bridge/Slf4jBridge.scala | 21 +++++--------- .../logging/slf4j/bridge/Slf4jBridge.scala | 29 +++++++++---------- 2 files changed, 21 insertions(+), 29 deletions(-) diff --git a/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala b/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala index 0348257cc..f36e207ad 100644 --- a/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala +++ b/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala @@ -16,9 +16,7 @@ package zio.logging.slf4j.bridge import org.slf4j.impl.ZioLoggerFactory -import zio.{ Runtime, ZIO, ZLayer } - -import java.util.concurrent.locks.ReentrantLock +import zio.{ Runtime, Semaphore, Unsafe, ZIO, ZLayer } object Slf4jBridge { @@ -48,18 +46,15 @@ object Slf4jBridge { def initialize(nameAnnotationKey: String): ZLayer[Any, Nothing, Unit] = Runtime.enableCurrentFiber ++ layer(nameAnnotationKey) - private val initLock: ReentrantLock = new ReentrantLock() + private val initLock = Semaphore.unsafe.make(1)(Unsafe.unsafe) private def layer(nameAnnotationKey: String): ZLayer[Any, Nothing, Unit] = ZLayer { - ZIO.runtime[Any].flatMap { runtime => - ZIO.succeed { - initLock.lock() - try - ZioLoggerFactory.initialize(new ZioLoggerRuntime(runtime, nameAnnotationKey)) - finally - initLock.unlock() - } - } + for { + runtime <- ZIO.runtime[Any] + _ <- initLock.withPermits(1) { + ZIO.succeed(ZioLoggerFactory.initialize(new ZioLoggerRuntime(runtime, nameAnnotationKey))) + } + } yield () } } diff --git a/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala b/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala index 74ff8897e..b3a464044 100644 --- a/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala +++ b/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala @@ -15,9 +15,7 @@ */ package zio.logging.slf4j.bridge -import zio.{ Runtime, ZIO, ZLayer } - -import java.util.concurrent.locks.ReentrantLock +import zio.{ Runtime, Semaphore, Unsafe, ZIO, ZLayer } object Slf4jBridge { @@ -31,21 +29,20 @@ object Slf4jBridge { */ def initializeWithoutFiberRefPropagation: ZLayer[Any, Nothing, Unit] = layer - private val initLock: ReentrantLock = new ReentrantLock() + private val initLock = Semaphore.unsafe.make(1)(Unsafe.unsafe) private def layer: ZLayer[Any, Nothing, Unit] = ZLayer { - ZIO.runtime[Any].flatMap { runtime => - ZIO.succeed { - initLock.lock() - try - org.slf4j.LoggerFactory - .getILoggerFactory() - .asInstanceOf[LoggerFactory] - .attacheRuntime(new ZioLoggerRuntime(runtime)) - finally - initLock.unlock() - } - } + for { + runtime <- ZIO.runtime[Any] + _ <- initLock.withPermits(1) { + ZIO.succeed( + org.slf4j.LoggerFactory + .getILoggerFactory() + .asInstanceOf[LoggerFactory] + .attacheRuntime(new ZioLoggerRuntime(runtime)) + ) + } + } yield () } } From db2e3d3e9472142a33d37a3afb4456a6d2c46e25 Mon Sep 17 00:00:00 2001 From: Peter Kotula Date: Wed, 22 Nov 2023 19:16:20 +0100 Subject: [PATCH 4/4] slf4j bridge - init lock with Semaphore --- .../src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala | 2 +- .../src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala b/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala index f36e207ad..686782578 100644 --- a/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala +++ b/slf4j-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala @@ -52,7 +52,7 @@ object Slf4jBridge { ZLayer { for { runtime <- ZIO.runtime[Any] - _ <- initLock.withPermits(1) { + _ <- initLock.withPermit { ZIO.succeed(ZioLoggerFactory.initialize(new ZioLoggerRuntime(runtime, nameAnnotationKey))) } } yield () diff --git a/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala b/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala index b3a464044..716662978 100644 --- a/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala +++ b/slf4j2-bridge/src/main/scala/zio/logging/slf4j/bridge/Slf4jBridge.scala @@ -35,7 +35,7 @@ object Slf4jBridge { ZLayer { for { runtime <- ZIO.runtime[Any] - _ <- initLock.withPermits(1) { + _ <- initLock.withPermit { ZIO.succeed( org.slf4j.LoggerFactory .getILoggerFactory()