とある案件でネイティブAndroidアプリを作成しているが、内部でエラーが発生したか、 どう動いたかなど、問い合わせがあった場合にログが無い困るケースがあった

標準のログではLogcatで流れてしまい、また端末をPCへ接続できないと、やはりデバッグとしては辛い

Android でログをファイル出力する方法を模索し、slf4j 使ってファイル保存することにした。 保存したログファイルは別途S3へアップロード ここでは、slf4j でログ出力するところを記載

app/build.gradle

    implementation 'org.slf4j:slf4j-api:1.7.25'
    implementation 'com.github.tony19:logback-android:2.0.0'

app/src/main/assets/logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
  <appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
    <tagEncoder>
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %class{0}.%method:%L</pattern>
    </tagEncoder>
    <encoder>
      <pattern>[%t] %-5level %msg%n</pattern>
    </encoder>
  </appender>

  <property name="LOG_DIR" value="/data/data/${PACKAGE_NAME}/files/logs" />
  <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_DIR}/app.log</file>

    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
      <fileNamePattern>${LOG_DIR}/archives/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
      <!-- each archived file, size max 10MB -->
      <maxFileSize>10MB</maxFileSize>
      <!-- total size of all archive files, if total size > 5GB, it will delete old archived file -->
      <totalSizeCap>5GB</totalSizeCap>
      <maxHistory>60</maxHistory>
    </rollingPolicy>

    <append>true</append>
    <encoder>
      <!-- %-4relative [%-20thread] [%thread] %-5level %logger %logger{35} - %msg%n -->
      <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %class{0}.%method:%L [%t] %-5level %msg%n</pattern>
    </encoder>
  </appender>

  <root level="DEBUG">
    <appender-ref ref="logcat" />
    <appender-ref ref="file" />
  </root>
</configuration>

MainApplication.kt

どこからでも呼べるように、kotlin.Any.logger で定義

package jp.co.sunwise.android.halshare.app

import android.app.Application
import org.slf4j.Logger
import org.slf4j.LoggerFactory

val kotlin.Any.logger: Logger
    get() {
        return LoggerFactory.getLogger(this.javaClass)
    }

class MainApplication : Application() {
}

あとはどこでもいいので、ログ出力してみる

logger.info("Sample log!")

Refs