Added Timber to Koin and OkHttp, started implementing file logging

This commit is contained in:
Nite 2020-09-30 18:17:57 +02:00
parent 7217f2cca8
commit 5de20861ca
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
10 changed files with 118 additions and 11 deletions

View File

@ -10,6 +10,7 @@ dependencies {
}
implementation other.kotlinReflect // for jackson kotlin, but to use the same version
implementation other.okhttpLogging
implementation other.timber
testImplementation testing.kotlinJunit
testImplementation testing.mockito

View File

@ -36,6 +36,7 @@ private const val READ_TIMEOUT = 60_000L
*/
class SubsonicAPIClient(
config: SubsonicClientConfiguration,
private val okLogger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT,
baseOkClient: OkHttpClient = OkHttpClient.Builder().build()
) {
private val versionInterceptor = VersionInterceptor(config.minimalProtocolVersion)
@ -176,7 +177,7 @@ class SubsonicAPIClient(
}
private fun OkHttpClient.Builder.addLogging() {
val loggingInterceptor = HttpLoggingInterceptor()
val loggingInterceptor = HttpLoggingInterceptor(okLogger)
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
this.addInterceptor(loggingInterceptor)
}

View File

@ -75,6 +75,7 @@ dependencies {
implementation other.kotlinxCoroutines
implementation other.koinAndroid
implementation other.koinViewModel
implementation other.okhttpLogging
kapt androidSupport.room

View File

@ -1232,11 +1232,14 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
{
file = new File(FileUtil.getUltrasonicDirectory(context), filename);
printWriter = new PrintWriter(file);
printWriter.println("Android API level: " + Build.VERSION.SDK_INT);
printWriter.println("Ultrasonic version name: " + Util.getVersionName(context));
printWriter.println("Ultrasonic version code: " + Util.getVersionCode(context));
printWriter.println();
String logMessage = String.format(
"Android API level: %s\nUltrasonic version name: %s\nUltrasonic version code: %s\n\n",
Build.VERSION.SDK_INT, Util.getVersionName(context), Util.getVersionCode(context));
printWriter.println(logMessage);
throwable.printStackTrace(printWriter);
Timber.e(throwable, "Uncaught Exception! %s", logMessage);
Timber.i("Stack trace written to %s", file);
}
catch (Throwable x)

View File

@ -188,7 +188,7 @@ public class FileUtil
Timber.e(ex, "Exception in BitmapFactory.decodeFile()");
}
Timber.i("getAvatarBitmap %i", String.valueOf(size));
Timber.i("getAvatarBitmap %s", String.valueOf(size));
if (bitmap != null)
{
@ -258,7 +258,7 @@ public class FileUtil
Timber.e(ex, "Exception in BitmapFactory.decodeFile()");
}
Timber.i("getAlbumArtBitmap %i", String.valueOf(size));
Timber.i("getAlbumArtBitmap %s", String.valueOf(size));
if (bitmap != null)
{
@ -294,7 +294,7 @@ public class FileUtil
opt.inJustDecodeBounds = false;
}
Timber.i("getSampledBitmap %i", String.valueOf(size));
Timber.i("getSampledBitmap %s", String.valueOf(size));
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
}

View File

@ -12,6 +12,9 @@ import org.moire.ultrasonic.di.directoriesModule
import org.moire.ultrasonic.di.featureFlagsModule
import org.moire.ultrasonic.di.mediaPlayerModule
import org.moire.ultrasonic.di.musicServiceModule
import org.moire.ultrasonic.log.FileLoggerTree
import org.moire.ultrasonic.log.TimberKoinLogger
import org.moire.ultrasonic.log.timberLogger
import timber.log.Timber
import timber.log.Timber.DebugTree
@ -21,12 +24,12 @@ class UApp : MultiDexApplication() {
if (BuildConfig.DEBUG) {
Timber.plant(DebugTree())
Timber.plant(FileLoggerTree(this))
}
startKoin {
// Use Koin Android Logger
// TODO Current version of Koin has a bug, which forces the usage of Level.ERROR
androidLogger(Level.ERROR)
timberLogger(Level.ERROR)
// declare Android context
androidContext(this@UApp)
// declare modules to use

View File

@ -1,6 +1,7 @@
@file:JvmName("MusicServiceModule")
package org.moire.ultrasonic.di
import okhttp3.logging.HttpLoggingInterceptor
import kotlin.math.abs
import org.koin.android.ext.koin.androidContext
import org.koin.core.qualifier.named
@ -11,6 +12,7 @@ import org.moire.ultrasonic.api.subsonic.SubsonicAPIVersions
import org.moire.ultrasonic.api.subsonic.SubsonicClientConfiguration
import org.moire.ultrasonic.cache.PermanentFileStorage
import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.log.TimberOkHttpLogger
import org.moire.ultrasonic.service.CachedMusicService
import org.moire.ultrasonic.service.MusicService
import org.moire.ultrasonic.service.OfflineMusicService
@ -54,7 +56,8 @@ val musicServiceModule = module {
)
}
single { SubsonicAPIClient(get()) }
single<HttpLoggingInterceptor.Logger> { TimberOkHttpLogger() }
single { SubsonicAPIClient(get(), get()) }
single<MusicService>(named(ONLINE_MUSIC_SERVICE)) {
CachedMusicService(RESTMusicService(get(), get()))

View File

@ -0,0 +1,44 @@
package org.moire.ultrasonic.log
import android.content.Context
import org.moire.ultrasonic.util.FileUtil
import org.moire.ultrasonic.util.Util
import timber.log.Timber
import java.io.File
import java.io.FileWriter
/**
* A Timber Tree which can be used to log to a file
* Subclass of the DebugTree so it inherits the Tag handling
*/
class FileLoggerTree(val context: Context) : Timber.DebugTree() {
private val filename = "ultrasonic.log"
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
var file: File? = null
var writer: FileWriter? = null
try {
file = File(FileUtil.getUltrasonicDirectory(context), filename)
writer = FileWriter(file, true)
val exceptionString = t?.toString() ?: "";
writer.write("${logLevelToString(priority)} $tag $message $exceptionString\n")
writer.flush()
} catch (x: Throwable) {
super.e(x, "Failed to write log to %s", file)
} finally {
if (writer != null) Util.close(writer)
}
}
private fun logLevelToString(logLevel: Int) : String {
return when(logLevel) {
2 -> "V"
3 -> "D"
4 -> "I"
5 -> "W"
6 -> "E"
7 -> "A"
else -> "U"
}
}
}

View File

@ -0,0 +1,38 @@
package org.moire.ultrasonic.log
import org.koin.core.KoinApplication
import org.koin.core.logger.Level
import org.koin.core.logger.Logger
import org.koin.core.logger.MESSAGE
import timber.log.Timber
/**
* KoinApplication Extension to use Timber with Koin
*/
fun KoinApplication.timberLogger(
level: Level = Level.INFO
): KoinApplication {
koin._logger = TimberKoinLogger(level)
return this
}
/**
* Timber Logger implementation for Koin
*/
class TimberKoinLogger (level: Level = Level.INFO) : Logger(level) {
override fun log(level: Level, msg: MESSAGE) {
if (this.level <= level) {
logOnLevel(msg, level)
}
}
private fun logOnLevel(msg: MESSAGE, level: Level) {
when (level) {
Level.DEBUG -> Timber.d(msg)
Level.INFO -> Timber.i(msg)
Level.ERROR -> Timber.e(msg)
else -> Timber.e(msg)
}
}
}

View File

@ -0,0 +1,13 @@
package org.moire.ultrasonic.log
import okhttp3.logging.HttpLoggingInterceptor
import timber.log.Timber
/**
* Timber Logging implementation for HttpLoggingInterceptor
*/
class TimberOkHttpLogger : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Timber.d(message)
}
}