【问题标题】:logback-android FileAppender not creating fileslogback-android FileAppender 不创建文件
【发布时间】:2019-04-04 20:24:16
【问题描述】:

我在 Kotlin 项目中使用 logback-android 在文件中生成日志。我之前在不同的 Android 版本中测试过这个解决方案没有任何问题,但我在 Android 5.1 中发现了一个问题:创建了日志文件的父目录,但没有创建日志文件。我该如何解决这个问题?

build.gradle:

implementation 'io.github.microutils:kotlin-logging:1.6.24'
implementation 'com.github.tony19:logback-android:2.0.0'

logback.xml:

<configuration>
    <property name="LOG_DIR" value="${EXT_DIR:-${DATA_DIR}}/log.log" />
    <timestamp key="datetime" datePattern="yyyy'-'MMdd'-'HH':'mm':'ss"/>
    <appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
        <encoder>
            <pattern>[%d{yyyyMMdd-HH:mm:ss}][%thread][%-5level][%logger{36}][%msg]%n</pattern>
        </encoder>
    </appender>
    <appender name="filelog" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_DIR}/${datetime}.log</file>
        <encoder>
            <pattern>[%d{yyyyMMdd-HH:mm:ss}][%thread][%-5level][%logger{36}][%msg]%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>${LOG_DIR}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxFileSize>100MB</maxFileSize>
            <maxHistory>5</maxHistory>
            <totalSizeCap>500MB</totalSizeCap>
        </rollingPolicy>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="logcat" />
    </root>
    <root level="DEBUG">
        <appender-ref ref="filelog" />
    </root>
</configuration>

【问题讨论】:

  • 您好 Ernesto Garcia,欢迎来到 Stack Overflow!当询问有关由您的代码引起的问题的问题时,如果您提供人们可以用来重现问题的代码,您将获得更好的答案。请参阅:How to create a Minimal, Complete, and Verifiable example。祝你好运!
  • 依赖问题应该在github上发布
  • @ErnestoGarcia 您能否提供一个指向重现该问题的 GitHub 存储库的链接?
  • 谢谢大家,很抱歉这么晚才回复。我认为我在阅读日志时发现了错误,显然使用的模式是问题"yyyy'-'MMdd'-'HH':'mm':'ss" 有字符:,在 5.1 版本的 Android 中,这种模式代表某种问题
  • 我创建了this 示例来重现错误

标签: android logback fileappender


【解决方案1】:

我建议使用logbackdebug(例如&lt;configuration debug="true"&gt; in logback.xml)在logcat 中查看有用的消息以进行故障排除。

安卓 5.1

logcat 消息显示文件名无效。具体来说,Android 5.1 disallows : in filenames(在更高版本的 Android 中不是问题):

<timestamp key="datetime" datePattern="yyyy-MM-dd-HH:mm:ss"/> <!-- DON'T USE COLONS IN ANDROID 5.1 -->
<file>${LOG_DIR}/${datetime}.log</file>

问题将在logcat 中以FileNotFoundException 的形式出现,以result of FileOutputStream failing to create the file 的形式出现:

|-INFO in ch.qos.logback.core.rolling.RollingFileAppender[filelog] - File property is set to [/storage/sdcard/logfolder/2019-09-07-05:22:42.log]
    java.io.FileNotFoundException: /storage/sdcard/logfolder/2019-09-07-05:22:42.log: open failed: EINVAL (Invalid argument)

...

|-ERROR in ch.qos.logback.core.rolling.RollingFileAppender[filelog] - openFile(/storage/sdcard/logfolder/2019-09-07-05:22:42.log,true) failed
    java.io.FileNotFoundException: /storage/sdcard/logfolder/2019-09-07-05:22:42.log: open failed: EINVAL (Invalid argument)

...

|-WARN in ch.qos.logback.core.rolling.RollingFileAppender[filelog] - Attempted to append to non started appender [filelog].

解决方法是从RollingFileAppenderfile 属性中删除冒号,同时注意避免与fileNamePattern 发生任何可能的文件名冲突。例如:

<timestamp key="datetime" datePattern="yyyy-MM-dd--HHmmss"/>
<file>${LOG_DIR}/${datetime}.log</file>
...
<fileNamePattern>${LOG_DIR}/%d{yyyy-MM-dd}.%i.log</fileNamePattern>

Android 6+

由于在 Android 6+ 中允许在文件名中使用 :,因此我们无需担心上述文件名冲突。配置可以保持不变。

另外,请确保request user permission 写入外部存储,否则logback-android 将无法为目标文件创建任何父目录(并且缺少对文件本身的写访问权限)。如果启用了调试,您会看到像这样的logcat 消息:

|-ERROR in ch.qos.logback.core.rolling.RollingFileAppender[filelog] - Failed to create parent directories for [/storage/emulated/0/logfolder/2019-09-07-02:27:04.log]
|-ERROR in ch.qos.logback.core.rolling.RollingFileAppender[filelog] - openFile(/storage/emulated/0/logfolder/2019-09-07-02:27:04.log,true) failed
    java.io.FileNotFoundException: /storage/emulated/0/logfolder/2019-09-07-02:27:04.log: open failed: ENOENT (No such file or directory)

在您的情况下,权限请求代码应该在MainActivity.ktonCreate()记录任何会导致写入外部存储的内容之前:

import android.Manifest
import android.content.pm.PackageManager
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat

...

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 1)
    }

    logger.info { "hello world" }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多