11package loggerf .logger .logback
22
3- import cats .effect .unsafe .IOLocals
43import cats .effect .{IOLocal , SyncIO }
54import cats .syntax .all ._
65import ch .qos .logback .classic .LoggerContext
76import logback_scala_interop .JLoggerFMdcAdapter
8- import org .slf4j .{ LoggerFactory , MDC }
7+ import org .slf4j .LoggerFactory
98
109import java .util .{Map => JMap , Set => JSet }
1110import scala .jdk .CollectionConverters ._
12- import scala .util .control .NonFatal
1311
1412/** @author Kevin Lee
1513 * @since 2023-07-07
@@ -18,7 +16,7 @@ class Ce3MdcAdapter extends JLoggerFMdcAdapter {
1816
1917 private [this ] val localContext : IOLocal [Map [String , String ]] =
2018 IOLocal [Map [String , String ]](Map .empty[String , String ])
21- .syncStep(1 )
19+ .syncStep(100 )
2220 .flatMap(
2321 _.leftMap(_ =>
2422 new Error (
@@ -28,58 +26,79 @@ class Ce3MdcAdapter extends JLoggerFMdcAdapter {
2826 )
2927 .unsafeRunSync()
3028
31- override def put (key : String , `val` : String ): Unit =
32- IOLocals .update(localContext)(_ + (key -> `val`))
29+ override def put (key : String , `val` : String ): Unit = {
30+ val unsafeThreadLocal = localContext.unsafeThreadLocal()
31+ unsafeThreadLocal.set(unsafeThreadLocal.get + (key -> `val`))
32+ }
3333
34- @ SuppressWarnings (Array (" org.wartremover.warts.Null" ))
34+ @ SuppressWarnings (Array (" org.wartremover.warts.Null" , " org.wartremover.warts.StringPlusAny " ))
3535 override def get (key : String ): String =
36- IOLocals .get(localContext) .getOrElse(key, null ) // scalafix:ok DisableSyntax.null
36+ localContext.unsafeThreadLocal().get .getOrElse(key, null ) // scalafix:ok DisableSyntax.null
3737
38- override def remove (key : String ): Unit = IOLocals .update(localContext)(_ - key)
38+ override def remove (key : String ): Unit = {
39+ val unsafeThreadLocal = localContext.unsafeThreadLocal()
40+ unsafeThreadLocal.set(unsafeThreadLocal.get - key)
41+ }
3942
40- override def clear (): Unit = IOLocals .reset(localContext )
43+ override def clear (): Unit = localContext.unsafeThreadLocal().set( Map .empty[ String , String ] )
4144
4245 override def getCopyOfContextMap : JMap [String , String ] = getPropertyMap0
4346
4447 override def setContextMap0 (contextMap : JMap [String , String ]): Unit =
45- IOLocals . set(localContext, contextMap.asScala.toMap)
48+ localContext.unsafeThreadLocal(). set(contextMap.asScala.toMap)
4649
47- private def getPropertyMap0 : JMap [String , String ] = IOLocals .get(localContext) .asJava
50+ private def getPropertyMap0 : JMap [String , String ] = localContext.unsafeThreadLocal().get .asJava
4851
4952 override def getPropertyMap : JMap [String , String ] = getPropertyMap0
5053
51- override def getKeys : JSet [String ] = IOLocals .get(localContext) .keySet.asJava
54+ override def getKeys : JSet [String ] = localContext.unsafeThreadLocal().get .keySet.asJava
5255
5356}
54- object Ce3MdcAdapter {
57+ object Ce3MdcAdapter extends Ce3MdcAdapterOps
58+
59+ trait Ce3MdcAdapterOps {
5560
5661 @ SuppressWarnings (Array (" org.wartremover.warts.Null" ))
57- private def initialize0 (): Ce3MdcAdapter = {
58- val field = classOf [MDC ].getDeclaredField(" mdcAdapter" )
59- field.setAccessible(true )
60- val adapter = new Ce3MdcAdapter
61- field.set(null , adapter) // scalafix:ok DisableSyntax.null
62- field.setAccessible(false )
63- adapter
62+ protected def initialize0 (ce3MdcAdapter : Ce3MdcAdapter ): Ce3MdcAdapter = {
63+ org.slf4j.SetMdcAdapter (ce3MdcAdapter)
64+ ce3MdcAdapter
6465 }
6566
6667 @ SuppressWarnings (Array (" org.wartremover.warts.AsInstanceOf" , " scalafix:DisableSyntax.asInstanceOf" ))
67- def initialize (): Ce3MdcAdapter = {
68- val loggerContext =
69- LoggerFactory .getILoggerFactory.asInstanceOf [LoggerContext ]
70- initializeWithLoggerContext(loggerContext)
71- }
68+ protected def getLoggerContext (): LoggerContext =
69+ LoggerFactory .getILoggerFactory.asInstanceOf [LoggerContext ]
7270
73- def initializeWithLoggerContext (loggerContext : LoggerContext ): Ce3MdcAdapter = {
74- val adapter = initialize0()
75- try {
76- val field = classOf [LoggerContext ].getDeclaredField(" mdcAdapter" )
71+ def initialize (): Ce3MdcAdapter =
72+ initializeWithCe3MdcAdapterAndLoggerContext(new Ce3MdcAdapter , getLoggerContext())
73+
74+ def initializeWithCe3MdcAdapter (ce3MdcAdapter : Ce3MdcAdapter ): Ce3MdcAdapter =
75+ initializeWithCe3MdcAdapterAndLoggerContext(ce3MdcAdapter, getLoggerContext())
76+
77+ def initializeWithLoggerContext (loggerContext : LoggerContext ): Ce3MdcAdapter =
78+ initializeWithCe3MdcAdapterAndLoggerContext(new Ce3MdcAdapter , loggerContext)
79+
80+ @ SuppressWarnings (Array (" org.wartremover.warts.Equals" ))
81+ def initializeWithCe3MdcAdapterAndLoggerContext (
82+ ce3MdcAdapter : Ce3MdcAdapter ,
83+ loggerContext : LoggerContext ,
84+ ): Ce3MdcAdapter = {
85+ val adapter = initialize0(ce3MdcAdapter)
86+
87+ loggerContext.setMDCAdapter(adapter)
88+ if (loggerContext.getMDCAdapter == adapter) {
89+ // println("[LoggerContext] It's set by setMDCAdapter.")
90+ adapter
91+ } else {
92+ // println(
93+ // "[LoggerContext] The old setMDCAdapter doesn't replace `mdcAdapter` if it has already been set, " +
94+ // "so it will use reflection to set it in the `mdcAdapter` field."
95+ // )
96+ val loggerContextClass = classOf [LoggerContext ]
97+ val field = loggerContextClass.getDeclaredField(" mdcAdapter" )
7798 field.setAccessible(true )
7899 field.set(loggerContext, adapter)
79100 field.setAccessible(false )
80101 adapter
81- } catch {
82- case NonFatal (_) => adapter
83102 }
84103 }
85104}
0 commit comments