Skip to content

Commit

Permalink
Avoid calling sbt deprecated methods, stop using log4j (#2087)
Browse files Browse the repository at this point in the history
This stops using log4j sbt logger in favor of the global logger, which
should not log warnings around SecurityManager.

This is the log I'm talking about:
```
[#1] 2022-10-25 14:45:57,759 pool-1-thread-2 ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")
[#1]    at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
[#1]    at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:358)
[#1]    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.checkMBeanTrustPermission(DefaultMBeanServerInterceptor.java:1805)
[#1]    at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.registerMBean(DefaultMBeanServerInterceptor.java:318)
[#1]    at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.registerMBean(JmxMBeanServer.java:522)
[#1]    at org.apache.logging.log4j.core.jmx.Server.register(Server.java:400)
[#1]    at org.apache.logging.log4j.core.jmx.Server.reregisterMBeansAfterReconfigure(Server.java:168)
[#1]    at org.apache.logging.log4j.core.jmx.Server.reregisterMBeansAfterReconfigure(Server.java:141)
[#1]    at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:632)
[#1]    at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:285)
[#1]    at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:209)
[#1]    at org.apache.logging.log4j.core.config.Configurator.initialize(Configurator.java:244)
[#1]    at org.apache.logging.log4j.core.config.Configurator.initialize(Configurator.java:220)
[#1]    at sbt.util.LogExchange.init(LogExchange.scala:151)
[#1]    at sbt.util.LogExchange.context$lzycompute(LogExchange.scala:24)
[#1]    at sbt.util.LogExchange.context(LogExchange.scala:24)
[#1]    at sbt.util.LogExchange.dummyLayout$lzycompute(LogExchange.scala:104)
[#1]    at sbt.util.LogExchange.dummyLayout(LogExchange.scala:103)
[#1]    at sbt.internal.util.Log4JConsoleAppender.<init>(ConsoleAppender.scala:566)
[#1]    at sbt.internal.util.ConsoleAppender.toLog4J$lzycompute(ConsoleAppender.scala:347)
[#1]    at sbt.internal.util.ConsoleAppender.toLog4J(ConsoleAppender.scala:342)
[#1]    at sbt.util.LogExchange.$anonfun$bindLoggerAppenders$2(LogExchange.scala:56)
[#1]    at scala.collection.immutable.List.map(List.scala:246)
[#1]    at scala.collection.immutable.List.map(List.scala:79)
[#1]    at sbt.util.LogExchange.bindLoggerAppenders(LogExchange.scala:56)
[#1]    at mill.scalalib.worker.ZincWorkerImpl.compileInternal(ZincWorkerImpl.scala:453)
[#1]    at mill.scalalib.worker.ZincWorkerImpl.$anonfun$compileMixed0$1(ZincWorkerImpl.scala:340)
[#1]    at mill.api.FixSizedCache.withCachedValue(FixSizedCache.scala:66)
[#1]    at mill.scalalib.worker.ZincWorkerImpl.withCompilers(ZincWorkerImpl.scala:422)
[#1]    at mill.scalalib.worker.ZincWorkerImpl.compileMixed0(ZincWorkerImpl.scala:339)
[#1]    at mill.scalalib.worker.ZincWorkerImpl.compileMixed(ZincWorkerImpl.scala:307)
[#1]    at mill.scalalib.ScalaModule.$anonfun$compile$2(ScalaModule.scala:198)
[#1]    at mill.define.Task$TraverseCtx.evaluate(Task.scala:380)
[#1]    at mill.eval.Evaluator.$anonfun$evaluateGroup$13(Evaluator.scala:627)
[#1]    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
[#1]    at scala.Console$.withErr(Console.scala:193)
[#1]    at mill.eval.Evaluator.$anonfun$evaluateGroup$12(Evaluator.scala:627)
[#1]    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
[#1]    at scala.Console$.withOut(Console.scala:164)
[#1]    at mill.eval.Evaluator.$anonfun$evaluateGroup$11(Evaluator.scala:626)
[#1]    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
[#1]    at scala.Console$.withIn(Console.scala:227)
[#1]    at mill.eval.Evaluator.$anonfun$evaluateGroup$8(Evaluator.scala:625)
[#1]    at mill.eval.Evaluator.$anonfun$evaluateGroup$8$adapted(Evaluator.scala:586)
[#1]    at scala.collection.immutable.Vector.foreach(Vector.scala:1856)
[#1]    at mill.eval.Evaluator.evaluateGroup(Evaluator.scala:586)
[#1]    at mill.eval.Evaluator.$anonfun$evaluateGroupCached$21(Evaluator.scala:478)
[#1]    at scala.util.DynamicVariable.withValue(DynamicVariable.scala:59)
[#1]    at mill.eval.Evaluator.evaluateGroupCached(Evaluator.scala:469)
[#1]    at mill.eval.Evaluator.$anonfun$parallelEvaluate$2(Evaluator.scala:298)
[#1]    at scala.concurrent.impl.Promise$Transformation.run(Promise.scala:467)
[#1]    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[#1]    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[#1]    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[#1]    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[#1]    at java.base/java.lang.Thread.run(Thread.java:829)
[#1] 
```

The method we were calling was converting our appender into a log4j
`XAppender` and then wrapping it in a `ConsoleAppender`.
```scala
  @deprecated("Use LoggerContext to bind appenders", "1.4.0")
  def bindLoggerAppenders(
      loggerName: String,
      appenders: List[(XAppender, Level.Value)]
  ): Unit = {
    appenders.foreach {
      case (a, l) =>
        LoggerContext.globalContext
          .addAppender(loggerName, new ConsoleAppenderFromLog4J(loggerName, a) -> l)
    }
  }
  @deprecated("Use LoggerContext to bind appenders", "1.4.0")
  def bindLoggerAppenders(
      loggerName: String,
      appenders: Seq[(Appender, Level.Value)]
  ): Unit = bindLoggerAppenders(loggerName, appenders.map { case (a, l) => a.toLog4J -> l }.toList)
```
Since we already create a `ConsoleAppender` we can avoid all these
conversions and bypass log4j altogether.

Co-authored-by: Tobias Roeser <le.petit.fou@web.de>

Pull request: #2087
  • Loading branch information
lolgab authored Oct 25, 2022
1 parent 524e7c8 commit 200079c
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 11 deletions.
13 changes: 2 additions & 11 deletions scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import mill.scalalib.api.{CompilationResult, ZincWorkerApi, ZincWorkerUtil => Ut
import sbt.internal.inc._
import sbt.internal.inc.classpath.ClasspathUtil
import sbt.internal.util.{ConsoleAppender, ConsoleOut}
import sbt.util.LogExchange
import sbt.mill.SbtLoggerUtils
import xsbti.compile.{CompilerCache => _, FileAnalysisStore => _, ScalaInstance => _, _}
import xsbti.{PathBasedFile, VirtualFile}

import scala.annotation.nowarn
import scala.collection.mutable
import scala.ref.SoftReference
import scala.util.Properties.isWin
Expand Down Expand Up @@ -443,15 +442,7 @@ class ZincWorkerImpl(
_ => None
)
val loggerId = Thread.currentThread().getId.toString
// The following three calls to [[LogExchange]] are deprecated, but the
// suggested alternatives aren't public API, so we can't really do anything
// to avoid calling these deprecated API.
// See issue https://github.com/sbt/sbt/issues/6734
// Also, these are no longer deprecated in newer zinc versions
val logger = LogExchange.logger(loggerId): @nowarn
LogExchange.unbindLoggerAppenders(loggerId): @nowarn
LogExchange.bindLoggerAppenders(loggerId, (consoleAppender -> zincLogLevel) :: Nil): @nowarn

val logger = SbtLoggerUtils.createLogger(loggerId, consoleAppender, zincLogLevel)
val newReporter = reporter match {
case None => new ManagedLoggedReporter(10, logger)
case Some(r) => new ManagedLoggedReporter(10, logger) {
Expand Down
18 changes: 18 additions & 0 deletions scalalib/worker/src/sbt/mill/SbtLoggerUtils.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package sbt.mill

import mill.api.internal
import sbt.internal.util.{Appender, ManagedLogger}
import sbt.util.{Level, LoggerContext}

// We put this in the sbt package so it can access `private[sbt]` methods
@internal
object SbtLoggerUtils {
def createLogger(name: String, appender: Appender, level: Level.Value): ManagedLogger = {
val context = LoggerContext.globalContext
val logger = context.logger(name = name, channelName = None, execId = None)
context.clearAppenders(name)
context.addAppender(name, (appender, level))

logger
}
}

0 comments on commit 200079c

Please sign in to comment.