feat: 当停止记录终端日志的时候立即关闭文件流

This commit is contained in:
hstyi
2025-01-08 11:18:40 +08:00
committed by hstyi
parent 3e5df2161b
commit 5ebea06a95
2 changed files with 58 additions and 20 deletions

View File

@@ -23,6 +23,8 @@ class TerminalLoggerAction : AnAction(I18n.getString("termora.terminal-logger"),
var isRecording = properties.getString("terminal.logger.isRecording")?.toBoolean() ?: false var isRecording = properties.getString("terminal.logger.isRecording")?.toBoolean() ?: false
private set(value) { private set(value) {
field = value field = value
// firePropertyChange
putValue("Recording", value)
properties.putString("terminal.logger.isRecording", value.toString()) properties.putString("terminal.logger.isRecording", value.toString())
} }

View File

@@ -10,11 +10,13 @@ import org.apache.commons.io.IOUtils
import org.apache.commons.lang3.time.DateFormatUtils import org.apache.commons.lang3.time.DateFormatUtils
import org.jdesktop.swingx.action.ActionManager import org.jdesktop.swingx.action.ActionManager
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.beans.PropertyChangeListener
import java.io.BufferedWriter import java.io.BufferedWriter
import java.io.File import java.io.File
import java.io.FileWriter import java.io.FileWriter
import java.nio.file.Paths import java.nio.file.Paths
import java.util.* import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener { class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener {
companion object { companion object {
@@ -26,11 +28,21 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
private val log = LoggerFactory.getLogger(TerminalLoggerDataListener::class.java) private val log = LoggerFactory.getLogger(TerminalLoggerDataListener::class.java)
} }
private val coroutineScope by lazy { CoroutineScope(Dispatchers.IO) } private var coroutineScope: CoroutineScope? = null
private val channel by lazy { Channel<String>(Channel.UNLIMITED) } private var channel: Channel<String>? = null
private var file: File? = null
private var writer: BufferedWriter? = null
private lateinit var file: File private val isRecording = AtomicBoolean(false)
private lateinit var writer: BufferedWriter
// 监听 Recording 变化,如果已经停止录制,那么立即关闭文件
private val terminalLoggerActionPropertyChangeListener = PropertyChangeListener { evt ->
if (evt.propertyName == "Recording") {
if (evt.newValue == false) {
close()
}
}
}
private val host: Host? private val host: Host?
get() { get() {
@@ -65,21 +77,31 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
return return
} }
// 尝试记录 try {// 尝试记录
tryRecord(data as String, host, action) tryRecord(data as String, host, action)
} catch (e: Exception) {
if (log.isErrorEnabled) {
log.error(e.message, e)
}
}
} }
private fun tryRecord(text: String, host: Host, action: TerminalLoggerAction) { private fun tryRecord(text: String, host: Host, action: TerminalLoggerAction) {
if (!::writer.isInitialized) { if (isRecording.compareAndSet(false, true)) {
file = createFile(host, action.getLogDir()) val file = createFile(host, action.getLogDir()).apply { file = this }
val writer = BufferedWriter(FileWriter(file, false)).apply { writer = this }
writer = BufferedWriter(FileWriter(file, false))
if (log.isInfoEnabled) { if (log.isInfoEnabled) {
log.info("Terminal logger file: ${file.absolutePath}") log.info("Terminal logger file: ${file.absolutePath}")
} }
action.removePropertyChangeListener(terminalLoggerActionPropertyChangeListener)
action.addPropertyChangeListener(terminalLoggerActionPropertyChangeListener)
val coroutineScope = this.coroutineScope ?: CoroutineScope(Dispatchers.IO).apply { coroutineScope = this }
val channel = this.channel ?: Channel<String>(Channel.UNLIMITED).apply { channel = this }
coroutineScope.launch { coroutineScope.launch {
while (coroutineScope.isActive) { while (coroutineScope.isActive) {
channel.receiveCatching().onSuccess { channel.receiveCatching().onSuccess {
@@ -97,7 +119,9 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
channel.trySend("${ControlCharacters.LF}${ControlCharacters.CR}").isSuccess channel.trySend("${ControlCharacters.LF}${ControlCharacters.CR}").isSuccess
} }
channel.trySend(text).isSuccess if (isRecording.get()) {
channel?.trySend(text)?.isSuccess
}
} }
private fun createFile(host: Host, dir: File): File { private fun createFile(host: Host, dir: File): File {
@@ -119,29 +143,41 @@ class TerminalLoggerDataListener(private val terminal: Terminal) : DataListener
} }
private fun close() { private fun close() {
if (!::writer.isInitialized) { if (!isRecording.compareAndSet(true, false)) {
return return
} }
channel.close() // 移除监听
coroutineScope.cancel() ActionManager.getInstance().getAction(Actions.TERMINAL_LOGGER)
?.removePropertyChangeListener(terminalLoggerActionPropertyChangeListener)
this.channel?.close()
this.coroutineScope?.cancel()
this.channel = null
this.coroutineScope = null
// write end // write end
runCatching { runCatching {
val date = DateFormatUtils.format(Date(), I18n.getString("termora.date-format")) val date = DateFormatUtils.format(Date(), I18n.getString("termora.date-format"))
writer.write("${ControlCharacters.LF}${ControlCharacters.CR}") this.writer?.write("${ControlCharacters.LF}${ControlCharacters.CR}")
writer.write("[END] ---- $date ----") this.writer?.write("[END] ---- $date ----")
}.onFailure { }.onFailure {
if (log.isErrorEnabled) { if (log.isErrorEnabled) {
log.info(it.message, it) log.error(it.message, it)
} }
} }
IOUtils.closeQuietly(this.writer)
IOUtils.closeQuietly(writer) val file = this.file
if (log.isInfoEnabled && file != null) {
if (log.isInfoEnabled) {
log.info("Terminal logger file: {} saved", file.absolutePath) log.info("Terminal logger file: {} saved", file.absolutePath)
} }
this.writer = null
this.file = null
} }
} }