Skip to content

Commit 8d4aef0

Browse files
committed
fix logging sbt output
1 parent 017d200 commit 8d4aef0

File tree

2 files changed

+74
-73
lines changed

2 files changed

+74
-73
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,96 @@
1-
package com.olegych.scastie.sbtscastie
2-
3-
import java.io.{OutputStream, PrintWriter}
1+
package sbt.internal.util.com.olegych.scastie.sbtscastie
42

53
import com.olegych.scastie.api._
6-
import org.apache.logging.log4j.core.LogEvent
7-
import org.apache.logging.log4j.core.appender.AbstractAppender
8-
import org.apache.logging.log4j.core.layout.PatternLayout
4+
import org.apache.logging.log4j.core.{Appender => XAppender, LogEvent => XLogEvent}
95
import org.apache.logging.log4j.message.ObjectMessage
106
import play.api.libs.json.Json
117
import sbt.Keys._
128
import sbt._
13-
import sbt.internal.LogManager.suppressedMessage
14-
import sbt.internal.util.MainAppender.defaultScreen
15-
import sbt.internal.util.{ObjectEvent, TraceEvent}
9+
import sbt.internal.util.ConsoleAppender.Properties
10+
import sbt.internal.util.{ConsoleAppender, Log4JConsoleAppender, ObjectEvent, TraceEvent}
11+
12+
import java.io.{OutputStream, PrintWriter}
13+
import java.nio.channels.ClosedChannelException
14+
import java.util.concurrent.atomic.AtomicReference
1615

1716
object RuntimeErrorLogger {
18-
private object NoOp {
19-
def apply(): NoOp = {
20-
def out(in: String): Unit = {
21-
println(
22-
Json.stringify(
23-
Json.toJson[ConsoleOutput](
24-
ConsoleOutput.SbtOutput(ProcessOutput(in.trim, ProcessOutputType.StdOut, None))
25-
)
17+
private val scastieOut = new PrintWriter(new OutputStream {
18+
def out(in: String): Unit = {
19+
println(
20+
Json.stringify(
21+
Json.toJson[ConsoleOutput](
22+
ConsoleOutput.SbtOutput(ProcessOutput(in.trim, ProcessOutputType.StdOut, None))
2623
)
2724
)
28-
}
25+
)
26+
}
27+
override def write(b: Int): Unit = ()
28+
override def write(b: Array[Byte]): Unit = out(new String(b))
29+
override def write(b: Array[Byte], off: Int, len: Int): Unit = out(new String(b, off, len))
30+
override def close(): Unit = ()
31+
override def flush(): Unit = ()
32+
})
2933

30-
new NoOp(new OutputStream {
31-
override def close(): Unit = ()
32-
override def flush(): Unit = ()
33-
override def write(b: Array[Byte]): Unit =
34-
out(new String(b))
35-
override def write(b: Array[Byte], off: Int, len: Int): Unit =
36-
out(new String(b, off, len))
37-
override def write(b: Int): Unit = ()
38-
})
34+
private def findThrowable(event: XLogEvent) = {
35+
//daaamn
36+
Option(event.getThrown).orElse {
37+
for {
38+
e <- Option(event.getMessage).collect {
39+
case e: ObjectMessage => e
40+
}
41+
e <- Option(e.getParameter).collect {
42+
case e: ObjectEvent[_] => e
43+
}
44+
e <- Option(e.message).collect {
45+
case e: TraceEvent => e
46+
}
47+
//since worksheet wraps the code in object we unwrap it to display clearer message
48+
e <- Option(e.message).collect {
49+
case e: ExceptionInInitializerError if e.getCause != null && e.getCause.getStackTrace.headOption.exists { e =>
50+
e.getClassName == Instrumentation.instrumentedObject + "$" && e.getMethodName == "<clinit>"
51+
} =>
52+
e.getCause
53+
case e => e
54+
}
55+
} yield e
3956
}
4057
}
41-
private class NoOp(os: OutputStream) extends PrintWriter(os)
42-
4358
private def logThrowable(throwable: Throwable): Unit = {
4459
val error = RuntimeErrorWrap(RuntimeError.fromThrowable(throwable))
4560
println(Json.stringify(Json.toJson(error)))
4661
}
4762

48-
private val clientLogger = new AbstractAppender("sbt-scastie-appender", null, PatternLayout.createDefaultLayout(), true, Array()) {
49-
def append(event: LogEvent): Unit = {
50-
//daaamn
51-
val throwable = Option(event.getThrown).orElse {
52-
for {
53-
e <- Option(event.getMessage).collect {
54-
case e: ObjectMessage => e
55-
}
56-
e <- Option(e.getParameter).collect {
57-
case e: ObjectEvent[_] => e
58-
}
59-
e <- Option(e.message).collect {
60-
case e: TraceEvent => e
61-
}
62-
//since worksheet wraps the code in object we unwrap it to display clearer message
63-
e <- Option(e.message).collect {
64-
case e: ExceptionInInitializerError if e.getCause != null && e.getCause.getStackTrace.headOption.exists { e =>
65-
e.getClassName == Instrumentation.instrumentedObject + "$" && e.getMethodName == "<clinit>"
66-
} =>
67-
e.getCause
68-
case e => e
69-
}
70-
} yield e
71-
}
72-
throwable.foreach(logThrowable)
73-
}
74-
start()
75-
}
76-
77-
private val clientAppender = new sbt.internal.RelayAppender("sbt-scastie-appender") {
78-
override def trace(t: => Throwable, traceLevel: Int): Unit =
79-
logThrowable(t)
80-
81-
override def control(event: sbt.util.ControlEvent.Value, message: => String): Unit =
82-
logThrowable(new Throwable(message))
83-
84-
override def appendLog(level: util.Level.Value, message: => String): Unit =
85-
logThrowable(new Throwable(message))
86-
}
87-
8863
val settings: Seq[sbt.Def.Setting[_]] = Seq(
8964
showSuccess := false,
65+
useLog4J := true,
9066
logManager := sbt.internal.LogManager.withLoggers(
91-
(task, state) => defaultScreen(ConsoleOut.printWriterOut(NoOp()), suppressedMessage(task, state)),
92-
relay = _ => clientAppender
93-
)
67+
(_, _) =>
68+
new ConsoleAppender(ConsoleAppender.generateName, Properties.from(ConsoleOut.printWriterOut(scastieOut), true, false), _ => None) {
69+
override def trace(t: => Throwable, traceLevel: Int): Unit = logThrowable(t)
70+
private[this] val log4j = new AtomicReference[XAppender](null)
71+
private[sbt] override lazy val toLog4J = log4j.get match {
72+
case null =>
73+
log4j.synchronized {
74+
log4j.get match {
75+
case null =>
76+
val l = new Log4JConsoleAppender(
77+
name,
78+
properties,
79+
suppressedMessage, { event =>
80+
val level = ConsoleAppender.toLevel(event.getLevel)
81+
val message = event.getMessage
82+
findThrowable(event).foreach(logThrowable)
83+
try appendMessage(level, message)
84+
catch { case _: ClosedChannelException => }
85+
}
86+
)
87+
log4j.set(l)
88+
l
89+
case l => l
90+
}
91+
}
92+
}
93+
}
94+
),
9495
)
9596
}

sbt-scastie/src/main/scala/com.olegych.scastie.sbtscastie/SbtScastiePlugin.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object SbtScastiePlugin extends AutoPlugin {
1111
override def trigger = allRequirements
1212

1313
override lazy val projectSettings: Seq[sbt.Def.Setting[_]] =
14-
(CompilerReporter.setting +: RuntimeErrorLogger.settings) ++
14+
(CompilerReporter.setting +: sbt.internal.util.com.olegych.scastie.sbtscastie.RuntimeErrorLogger.settings) ++
1515
Seq(
1616
//workaround https://github.com/sbt/sbt/issues/5482
1717
Global / nio.Keys.onChangedBuildSource := nio.Keys.IgnoreSourceChanges,

0 commit comments

Comments
 (0)