Added Timber to Koin and OkHttp, started implementing file logging
This commit is contained in:
parent
7217f2cca8
commit
5de20861ca
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ dependencies {
|
|||
implementation other.kotlinxCoroutines
|
||||
implementation other.koinAndroid
|
||||
implementation other.koinViewModel
|
||||
implementation other.okhttpLogging
|
||||
|
||||
kapt androidSupport.room
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue