mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
17.59.2021 c6e77f6fa462e292db5f693a33e7c483b5a6e19e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package de.micromata.borgbutler.server.logging
 
import ch.qos.logback.classic.spi.ILoggingEvent
import ch.qos.logback.core.AppenderBase
import mu.KotlinLogging
import org.apache.commons.lang3.StringUtils
import java.util.*
 
private val log = KotlinLogging.logger {}
 
class LoggerMemoryAppender : AppenderBase<ILoggingEvent?>() {
    private var lastLogEntryOrderNumber = -1
 
    var queue = FiFoBuffer<LoggingEventData>(QUEUE_SIZE)
 
    override fun append(event: ILoggingEvent?) {
        val eventData = LoggingEventData(event)
        eventData.orderNumber = ++lastLogEntryOrderNumber
        queue.add(eventData)
    }
 
    /**
     * For testing purposes.
     *
     * @param event
     */
    fun append(event: LoggingEventData) {
        queue.add(event)
    }
 
    fun query(filter: LogFilter?, locale: Locale?): List<LoggingEventData> {
        val result: MutableList<LoggingEventData> = ArrayList()
        if (filter == null) {
            return result
        }
        var maxSize = if (filter.maxSize != null) filter.maxSize else MAX_RESULT_SIZE
        if (maxSize > MAX_RESULT_SIZE) {
            maxSize = MAX_RESULT_SIZE
        }
        var counter = 0
        //I18n i18n = CoreI18n.getDefault().get(locale);
        if (filter.isAscendingOrder) {
            for (i in 0 until queue.size) {
                val resultEvent = getResultEvent(filter, queue[i], locale) ?: continue
                result.add(resultEvent)
                if (++counter > maxSize) break
            }
        } else {
            for (i in queue.size downTo 0) {
                val resultEvent = getResultEvent(filter, queue[i], locale) ?: continue
                result.add(resultEvent)
                if (++counter > maxSize) break
            }
        }
        return result
    }
 
    private fun getResultEvent(filter: LogFilter, event: LoggingEventData?, locale: Locale?): LoggingEventData? {
        if (event == null) {
            return null
        }
        if (!event.getLevel().matches(filter.threshold)) {
            return null
        }
        if (filter.lastReceivedLogOrderNumber != null) {
            if (event.getOrderNumber() <= filter.lastReceivedLogOrderNumber) {
                return null
            }
        }
        var logString: String? = null
        val message = event.getMessage()
        val localizedMessage = false
        /*if (message != null && message.startsWith("i18n=")) {
                I18nLogEntry i18nLogEntry = I18nLogEntry.parse(message);
                message = i18n.formatMessage(i18nLogEntry.getI18nKey(), (Object[])i18nLogEntry.getArgs());
                localizedMessage = true;
            }*/if (StringUtils.isNotBlank(filter.search)) {
            val sb = StringBuilder()
            sb.append(event.logDate)
            append(sb, event.getLevel(), true)
            append(sb, message, true)
            append(sb, event.getJavaClass(), true)
            append(sb, event.stackTrace, filter.isShowStackTraces)
            logString = sb.toString()
        }
        if (logString == null || matches(logString, filter.search)) {
            var resultEvent: LoggingEventData = event
            if (localizedMessage) {
                // Need a clone
                resultEvent = event.clone()
                resultEvent.setMessage(message)
            }
            return resultEvent
        }
        return null
    }
 
    private fun append(sb: StringBuilder, value: Any?, append: Boolean) {
        if (!append || value == null) {
            return
        }
        sb.append("|#|").append(value)
    }
 
    private fun matches(str: String, searchString: String): Boolean {
        if (StringUtils.isBlank(str)) {
            return StringUtils.isBlank(searchString)
        }
        return if (StringUtils.isBlank(searchString)) {
            true
        } else str.toLowerCase().contains(searchString.toLowerCase())
    }
 
    companion object {
        private const val MAX_RESULT_SIZE = 1000
        private const val QUEUE_SIZE = 10000
        private var instance: LoggerMemoryAppender? = null
 
        fun getInstance(): LoggerMemoryAppender {
            return instance!!
        }
    }
 
    /**
     * Initialized by logback on start-up (see logback-spring.xml).
     */
    init {
        if (instance != null) {
            log.warn { "*** LoggerMemoryAppender instantiated twice! Shouldn't occur. ***" }
        } else {
            instance = this
        }
    }
}