mirror of
https://github.com/element-hq/element-android
synced 2024-11-27 11:59:12 +03:00
Merge pull request #2849 from vector-im/feature/bma/fileLogger
Cleanup VectorFileLogger.kt
This commit is contained in:
commit
371251c994
2 changed files with 113 additions and 115 deletions
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.rageshake
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import java.util.logging.Formatter
|
||||
import java.util.logging.LogRecord
|
||||
|
||||
class LogFormatter : Formatter() {
|
||||
|
||||
override fun format(r: LogRecord): String {
|
||||
if (!mIsTimeZoneSet) {
|
||||
DATE_FORMAT.timeZone = TimeZone.getTimeZone("UTC")
|
||||
mIsTimeZoneSet = true
|
||||
}
|
||||
|
||||
val thrown = r.thrown
|
||||
if (thrown != null) {
|
||||
val sw = StringWriter()
|
||||
val pw = PrintWriter(sw)
|
||||
sw.write(r.message)
|
||||
sw.write(LINE_SEPARATOR)
|
||||
thrown.printStackTrace(pw)
|
||||
pw.flush()
|
||||
return sw.toString()
|
||||
} else {
|
||||
val b = StringBuilder()
|
||||
val date = DATE_FORMAT.format(Date(r.millis))
|
||||
b.append(date)
|
||||
b.append("Z ")
|
||||
b.append(r.message)
|
||||
b.append(LINE_SEPARATOR)
|
||||
return b.toString()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LINE_SEPARATOR = System.getProperty("line.separator") ?: "\n"
|
||||
|
||||
// private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
|
||||
private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss*SSSZZZZ", Locale.US)
|
||||
|
||||
private var mIsTimeZoneSet = false
|
||||
}
|
||||
}
|
|
@ -22,45 +22,41 @@ import im.vector.app.features.settings.VectorPreferences
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
import java.util.logging.FileHandler
|
||||
import java.util.logging.Formatter
|
||||
import java.util.logging.Level
|
||||
import java.util.logging.LogRecord
|
||||
import java.util.logging.Logger
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class VectorFileLogger @Inject constructor(
|
||||
context: Context,
|
||||
private val vectorPreferences: VectorPreferences
|
||||
) : Timber.Tree() {
|
||||
|
||||
companion object {
|
||||
private const val SIZE_20MB = 20 * 1024 * 1024
|
||||
private const val SIZE_50MB = 50 * 1024 * 1024
|
||||
}
|
||||
|
||||
@Singleton
|
||||
class VectorFileLogger @Inject constructor(val context: Context, private val vectorPreferences: VectorPreferences) : Timber.Tree() {
|
||||
private val maxLogSizeByte = if (vectorPreferences.labAllowedExtendedLogging()) SIZE_50MB else SIZE_20MB
|
||||
private val logRotationCount = if (vectorPreferences.labAllowedExtendedLogging()) 15 else 7
|
||||
|
||||
private val maxLogSizeByte: Int
|
||||
private val logRotationCount: Int
|
||||
|
||||
init {
|
||||
if (vectorPreferences.labAllowedExtendedLogging()) {
|
||||
maxLogSizeByte = SIZE_50MB
|
||||
logRotationCount = 15
|
||||
} else {
|
||||
maxLogSizeByte = SIZE_20MB
|
||||
logRotationCount = 7
|
||||
private val logger = Logger.getLogger(context.packageName).apply {
|
||||
tryOrNull {
|
||||
useParentHandlers = false
|
||||
level = Level.ALL
|
||||
}
|
||||
}
|
||||
|
||||
private val sLogger = Logger.getLogger("im.vector.app")
|
||||
private var sFileHandler: FileHandler? = null
|
||||
private var sCacheDirectory: File? = null
|
||||
private var sFileName = "elementLogs"
|
||||
private val fileHandler: FileHandler?
|
||||
private val cacheDirectory = File(context.cacheDir, "logs")
|
||||
private var fileNamePrefix = "logs"
|
||||
|
||||
private val prioPrefixes = mapOf(
|
||||
Log.VERBOSE to "V/ ",
|
||||
|
@ -72,24 +68,29 @@ class VectorFileLogger @Inject constructor(val context: Context, private val vec
|
|||
)
|
||||
|
||||
init {
|
||||
val logsDirectoryFile = context.cacheDir.absolutePath + "/logs"
|
||||
setLogDirectory(File(logsDirectoryFile))
|
||||
try {
|
||||
if (sCacheDirectory != null) {
|
||||
sFileHandler = FileHandler(sCacheDirectory!!.absolutePath + "/" + sFileName + ".%g.txt", maxLogSizeByte, logRotationCount)
|
||||
sFileHandler?.formatter = LogFormatter()
|
||||
sLogger.useParentHandlers = false
|
||||
sLogger.level = Level.ALL
|
||||
sFileHandler?.let { sLogger.addHandler(it) }
|
||||
if (!cacheDirectory.exists()) {
|
||||
cacheDirectory.mkdirs()
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.e(e, "Failed to initialize FileLogger")
|
||||
|
||||
for (i in 0..15) {
|
||||
val file = File(cacheDirectory, "elementLogs.$i.txt")
|
||||
tryOrNull { file.delete() }
|
||||
}
|
||||
|
||||
fileHandler = tryOrNull("Failed to initialize FileLogger") {
|
||||
FileHandler(
|
||||
cacheDirectory.absolutePath + "/" + fileNamePrefix + ".%g.txt",
|
||||
maxLogSizeByte,
|
||||
logRotationCount
|
||||
)
|
||||
.also { it.formatter = LogFormatter() }
|
||||
.also { logger.addHandler(it) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
fileHandler ?: return
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
if (sFileHandler == null) return@launch
|
||||
if (skipLog(priority)) return@launch
|
||||
if (t != null) {
|
||||
logToFile(t)
|
||||
|
@ -107,84 +108,22 @@ class VectorFileLogger @Inject constructor(val context: Context, private val vec
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the directory to put log files.
|
||||
*
|
||||
* @param cacheDir The directory, usually [android.content.ContextWrapper.getCacheDir]
|
||||
*/
|
||||
private fun setLogDirectory(cacheDir: File) {
|
||||
if (!cacheDir.exists()) {
|
||||
cacheDir.mkdirs()
|
||||
}
|
||||
sCacheDirectory = cacheDir
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds our own log files to the provided list of files.
|
||||
*
|
||||
* @param files The list of files to add to.
|
||||
* @return The same list with more files added.
|
||||
* @return The list of files with logs.
|
||||
*/
|
||||
fun getLogFiles(): List<File> {
|
||||
val files = ArrayList<File>()
|
||||
|
||||
try {
|
||||
// reported by GA
|
||||
if (null != sFileHandler) {
|
||||
sFileHandler!!.flush()
|
||||
val absPath = sCacheDirectory?.absolutePath ?: return emptyList()
|
||||
|
||||
for (i in 0..logRotationCount) {
|
||||
val filepath = "$absPath/$sFileName.$i.txt"
|
||||
val file = File(filepath)
|
||||
if (file.exists()) {
|
||||
files.add(file)
|
||||
return tryOrNull("## getLogFiles() failed") {
|
||||
fileHandler
|
||||
?.flush()
|
||||
?.let { 0 until logRotationCount }
|
||||
?.mapNotNull { index ->
|
||||
File(cacheDirectory, "$fileNamePrefix.$index.txt")
|
||||
.takeIf { it.exists() }
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "## addLogFiles() failed")
|
||||
}
|
||||
|
||||
return files
|
||||
}
|
||||
|
||||
class LogFormatter : Formatter() {
|
||||
|
||||
override fun format(r: LogRecord): String {
|
||||
if (!mIsTimeZoneSet) {
|
||||
DATE_FORMAT.timeZone = TimeZone.getTimeZone("UTC")
|
||||
mIsTimeZoneSet = true
|
||||
}
|
||||
|
||||
val thrown = r.thrown
|
||||
if (thrown != null) {
|
||||
val sw = StringWriter()
|
||||
val pw = PrintWriter(sw)
|
||||
sw.write(r.message)
|
||||
sw.write(LINE_SEPARATOR)
|
||||
thrown.printStackTrace(pw)
|
||||
pw.flush()
|
||||
return sw.toString()
|
||||
} else {
|
||||
val b = StringBuilder()
|
||||
val date = DATE_FORMAT.format(Date(r.millis))
|
||||
b.append(date)
|
||||
b.append("Z ")
|
||||
b.append(r.message)
|
||||
b.append(LINE_SEPARATOR)
|
||||
return b.toString()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val LINE_SEPARATOR = System.getProperty("line.separator") ?: "\n"
|
||||
|
||||
// private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
|
||||
private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss*SSSZZZZ", Locale.US)
|
||||
|
||||
private var mIsTimeZoneSet = false
|
||||
}
|
||||
.orEmpty()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -193,20 +132,15 @@ class VectorFileLogger @Inject constructor(val context: Context, private val vec
|
|||
* @param throwable the throwable to log
|
||||
*/
|
||||
private fun logToFile(throwable: Throwable?) {
|
||||
if (null == sCacheDirectory || throwable == null) {
|
||||
return
|
||||
}
|
||||
throwable ?: return
|
||||
|
||||
val errors = StringWriter()
|
||||
throwable.printStackTrace(PrintWriter(errors))
|
||||
|
||||
sLogger.info(errors.toString())
|
||||
logger.info(errors.toString())
|
||||
}
|
||||
|
||||
private fun logToFile(level: String, tag: String, content: String) {
|
||||
if (null == sCacheDirectory) {
|
||||
return
|
||||
}
|
||||
val b = StringBuilder()
|
||||
b.append(Thread.currentThread().id)
|
||||
b.append(" ")
|
||||
|
@ -215,6 +149,6 @@ class VectorFileLogger @Inject constructor(val context: Context, private val vec
|
|||
b.append(tag)
|
||||
b.append(": ")
|
||||
b.append(content)
|
||||
sLogger.info(b.toString())
|
||||
logger.info(b.toString())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue