mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
JS debug logger: add last messages, don't use busy wait
This commit is contained in:
@@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.util.concurrency.AppExecutorUtil
|
||||
import com.intellij.util.io.CharSequenceBackedByChars
|
||||
import com.intellij.util.io.addChannelListener
|
||||
import io.netty.buffer.ByteBuf
|
||||
@@ -28,14 +29,74 @@ import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.nio.CharBuffer
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
internal class LogEntry(val message: Any, val marker: String) {
|
||||
internal val time = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
class MessagingLogger internal constructor(private val queue: ConcurrentLinkedQueue<LogEntry>) {
|
||||
internal @Volatile var closed = false
|
||||
class MessagingLogger internal constructor(debugFile: String) {
|
||||
private val processFuture: Future<*>
|
||||
private val queue = LinkedBlockingQueue<LogEntry>()
|
||||
|
||||
init {
|
||||
processFuture = ApplicationManager.getApplication().executeOnPooledThread {
|
||||
val file = File(FileUtil.expandUserHome(debugFile))
|
||||
FileUtilRt.createParentDirs(file)
|
||||
val out = FileOutputStream(file)
|
||||
val writer = out.writer()
|
||||
writer.write("[\n")
|
||||
writer.flush()
|
||||
val fileChannel = out.channel
|
||||
|
||||
val dateFormatter = SimpleDateFormat("HH.mm.ss,SSS")
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
val entry = queue.take()
|
||||
|
||||
writer.write("""{"timestamp": "${dateFormatter.format(entry.time)}", """)
|
||||
val message = entry.message
|
||||
when (message) {
|
||||
is CharSequence -> {
|
||||
writer.write("\"${entry.marker}\": ")
|
||||
writer.flush()
|
||||
|
||||
if (message is CharSequenceBackedByChars) {
|
||||
fileChannel.write(message.byteBuffer)
|
||||
}
|
||||
else {
|
||||
fileChannel.write(Charsets.UTF_8.encode(CharBuffer.wrap(message)))
|
||||
}
|
||||
|
||||
writer.write("},\n")
|
||||
writer.flush()
|
||||
}
|
||||
is ByteBuf -> {
|
||||
writer.write("\"${entry.marker}\": ")
|
||||
writer.flush()
|
||||
|
||||
message.getBytes(message.readerIndex(), out, message.readableBytes())
|
||||
message.release()
|
||||
|
||||
writer.write("},\n")
|
||||
writer.flush()
|
||||
}
|
||||
else -> throw RuntimeException("Unknown message type")
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e: InterruptedException) {
|
||||
}
|
||||
finally {
|
||||
writer.write("]")
|
||||
writer.flush()
|
||||
out.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun add(inMessage: CharSequence, marker: String = "IN") {
|
||||
queue.add(LogEntry(inMessage, marker))
|
||||
@@ -46,7 +107,9 @@ class MessagingLogger internal constructor(private val queue: ConcurrentLinkedQu
|
||||
}
|
||||
|
||||
fun close() {
|
||||
closed = true
|
||||
AppExecutorUtil.getAppScheduledExecutorService().schedule(fun() {
|
||||
processFuture.cancel(true)
|
||||
}, 1, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
fun closeOnChannelClose(channel: Channel) {
|
||||
@@ -63,71 +126,12 @@ class MessagingLogger internal constructor(private val queue: ConcurrentLinkedQu
|
||||
|
||||
fun createDebugLogger(@PropertyKey(resourceBundle = Registry.REGISTRY_BUNDLE) key: String, suffix: String = ""): MessagingLogger? {
|
||||
var debugFile = Registry.stringValue(key)
|
||||
if (debugFile.isNullOrEmpty()) {
|
||||
if (debugFile.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (!suffix.isNullOrEmpty()) {
|
||||
if (!suffix.isEmpty()) {
|
||||
debugFile = debugFile.replace(".json", suffix + ".json")
|
||||
}
|
||||
return createDebugLoggerWithFile(debugFile)
|
||||
}
|
||||
|
||||
fun createDebugLoggerWithFile(debugFile: String): MessagingLogger? {
|
||||
val queue = ConcurrentLinkedQueue<LogEntry>()
|
||||
val logger = MessagingLogger(queue)
|
||||
ApplicationManager.getApplication().executeOnPooledThread {
|
||||
val file = File(FileUtil.expandUserHome(debugFile))
|
||||
FileUtilRt.createParentDirs(file)
|
||||
val out = FileOutputStream(file)
|
||||
val writer = out.writer()
|
||||
writer.write("[\n")
|
||||
writer.flush()
|
||||
val fileChannel = out.channel
|
||||
|
||||
val dateFormatter = SimpleDateFormat("HH.mm.ss,SSS")
|
||||
|
||||
while (true) {
|
||||
val entry = queue.poll() ?: if (logger.closed) {
|
||||
break
|
||||
}
|
||||
else {
|
||||
continue
|
||||
}
|
||||
|
||||
writer.write("""{"timestamp": "${dateFormatter.format(entry.time)}", """)
|
||||
val message = entry.message
|
||||
when (message) {
|
||||
is CharSequence -> {
|
||||
writer.write("\"${entry.marker}\": ")
|
||||
writer.flush()
|
||||
|
||||
if (message is CharSequenceBackedByChars) {
|
||||
fileChannel.write(message.byteBuffer)
|
||||
}
|
||||
else {
|
||||
fileChannel.write(Charsets.UTF_8.encode(CharBuffer.wrap(message)))
|
||||
}
|
||||
|
||||
writer.write("},\n")
|
||||
writer.flush()
|
||||
}
|
||||
is ByteBuf -> {
|
||||
writer.write("\"${entry.marker}\": ")
|
||||
writer.flush()
|
||||
|
||||
message.getBytes(message.readerIndex(), out, message.readableBytes())
|
||||
message.release()
|
||||
|
||||
writer.write("},\n")
|
||||
writer.flush()
|
||||
}
|
||||
else -> throw RuntimeException("Unknown message type")
|
||||
}
|
||||
}
|
||||
writer.write("]")
|
||||
writer.flush()
|
||||
out.close()
|
||||
}
|
||||
return logger
|
||||
return MessagingLogger(debugFile)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user