mirror of
https://github.com/ultrasonic/ultrasonic
synced 2025-02-19 21:20:52 +01:00
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.kotlinReflect // for jackson kotlin, but to use the same version
|
||||||
implementation other.okhttpLogging
|
implementation other.okhttpLogging
|
||||||
|
implementation other.timber
|
||||||
|
|
||||||
testImplementation testing.kotlinJunit
|
testImplementation testing.kotlinJunit
|
||||||
testImplementation testing.mockito
|
testImplementation testing.mockito
|
||||||
|
@ -36,6 +36,7 @@ private const val READ_TIMEOUT = 60_000L
|
|||||||
*/
|
*/
|
||||||
class SubsonicAPIClient(
|
class SubsonicAPIClient(
|
||||||
config: SubsonicClientConfiguration,
|
config: SubsonicClientConfiguration,
|
||||||
|
private val okLogger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger.DEFAULT,
|
||||||
baseOkClient: OkHttpClient = OkHttpClient.Builder().build()
|
baseOkClient: OkHttpClient = OkHttpClient.Builder().build()
|
||||||
) {
|
) {
|
||||||
private val versionInterceptor = VersionInterceptor(config.minimalProtocolVersion)
|
private val versionInterceptor = VersionInterceptor(config.minimalProtocolVersion)
|
||||||
@ -176,7 +177,7 @@ class SubsonicAPIClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun OkHttpClient.Builder.addLogging() {
|
private fun OkHttpClient.Builder.addLogging() {
|
||||||
val loggingInterceptor = HttpLoggingInterceptor()
|
val loggingInterceptor = HttpLoggingInterceptor(okLogger)
|
||||||
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
||||||
this.addInterceptor(loggingInterceptor)
|
this.addInterceptor(loggingInterceptor)
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,7 @@ dependencies {
|
|||||||
implementation other.kotlinxCoroutines
|
implementation other.kotlinxCoroutines
|
||||||
implementation other.koinAndroid
|
implementation other.koinAndroid
|
||||||
implementation other.koinViewModel
|
implementation other.koinViewModel
|
||||||
|
implementation other.okhttpLogging
|
||||||
|
|
||||||
kapt androidSupport.room
|
kapt androidSupport.room
|
||||||
|
|
||||||
|
@ -1232,11 +1232,14 @@ public class SubsonicTabActivity extends ResultActivity implements OnClickListen
|
|||||||
{
|
{
|
||||||
file = new File(FileUtil.getUltrasonicDirectory(context), filename);
|
file = new File(FileUtil.getUltrasonicDirectory(context), filename);
|
||||||
printWriter = new PrintWriter(file);
|
printWriter = new PrintWriter(file);
|
||||||
printWriter.println("Android API level: " + Build.VERSION.SDK_INT);
|
|
||||||
printWriter.println("Ultrasonic version name: " + Util.getVersionName(context));
|
String logMessage = String.format(
|
||||||
printWriter.println("Ultrasonic version code: " + Util.getVersionCode(context));
|
"Android API level: %s\nUltrasonic version name: %s\nUltrasonic version code: %s\n\n",
|
||||||
printWriter.println();
|
Build.VERSION.SDK_INT, Util.getVersionName(context), Util.getVersionCode(context));
|
||||||
|
|
||||||
|
printWriter.println(logMessage);
|
||||||
throwable.printStackTrace(printWriter);
|
throwable.printStackTrace(printWriter);
|
||||||
|
Timber.e(throwable, "Uncaught Exception! %s", logMessage);
|
||||||
Timber.i("Stack trace written to %s", file);
|
Timber.i("Stack trace written to %s", file);
|
||||||
}
|
}
|
||||||
catch (Throwable x)
|
catch (Throwable x)
|
||||||
|
@ -188,7 +188,7 @@ public class FileUtil
|
|||||||
Timber.e(ex, "Exception in BitmapFactory.decodeFile()");
|
Timber.e(ex, "Exception in BitmapFactory.decodeFile()");
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.i("getAvatarBitmap %i", String.valueOf(size));
|
Timber.i("getAvatarBitmap %s", String.valueOf(size));
|
||||||
|
|
||||||
if (bitmap != null)
|
if (bitmap != null)
|
||||||
{
|
{
|
||||||
@ -258,7 +258,7 @@ public class FileUtil
|
|||||||
Timber.e(ex, "Exception in BitmapFactory.decodeFile()");
|
Timber.e(ex, "Exception in BitmapFactory.decodeFile()");
|
||||||
}
|
}
|
||||||
|
|
||||||
Timber.i("getAlbumArtBitmap %i", String.valueOf(size));
|
Timber.i("getAlbumArtBitmap %s", String.valueOf(size));
|
||||||
|
|
||||||
if (bitmap != null)
|
if (bitmap != null)
|
||||||
{
|
{
|
||||||
@ -294,7 +294,7 @@ public class FileUtil
|
|||||||
opt.inJustDecodeBounds = false;
|
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);
|
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.featureFlagsModule
|
||||||
import org.moire.ultrasonic.di.mediaPlayerModule
|
import org.moire.ultrasonic.di.mediaPlayerModule
|
||||||
import org.moire.ultrasonic.di.musicServiceModule
|
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
|
||||||
import timber.log.Timber.DebugTree
|
import timber.log.Timber.DebugTree
|
||||||
|
|
||||||
@ -21,12 +24,12 @@ class UApp : MultiDexApplication() {
|
|||||||
|
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG) {
|
||||||
Timber.plant(DebugTree())
|
Timber.plant(DebugTree())
|
||||||
|
Timber.plant(FileLoggerTree(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
startKoin {
|
startKoin {
|
||||||
// Use Koin Android Logger
|
|
||||||
// TODO Current version of Koin has a bug, which forces the usage of Level.ERROR
|
// TODO Current version of Koin has a bug, which forces the usage of Level.ERROR
|
||||||
androidLogger(Level.ERROR)
|
timberLogger(Level.ERROR)
|
||||||
// declare Android context
|
// declare Android context
|
||||||
androidContext(this@UApp)
|
androidContext(this@UApp)
|
||||||
// declare modules to use
|
// declare modules to use
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
@file:JvmName("MusicServiceModule")
|
@file:JvmName("MusicServiceModule")
|
||||||
package org.moire.ultrasonic.di
|
package org.moire.ultrasonic.di
|
||||||
|
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import org.koin.android.ext.koin.androidContext
|
import org.koin.android.ext.koin.androidContext
|
||||||
import org.koin.core.qualifier.named
|
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.api.subsonic.SubsonicClientConfiguration
|
||||||
import org.moire.ultrasonic.cache.PermanentFileStorage
|
import org.moire.ultrasonic.cache.PermanentFileStorage
|
||||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||||
|
import org.moire.ultrasonic.log.TimberOkHttpLogger
|
||||||
import org.moire.ultrasonic.service.CachedMusicService
|
import org.moire.ultrasonic.service.CachedMusicService
|
||||||
import org.moire.ultrasonic.service.MusicService
|
import org.moire.ultrasonic.service.MusicService
|
||||||
import org.moire.ultrasonic.service.OfflineMusicService
|
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)) {
|
single<MusicService>(named(ONLINE_MUSIC_SERVICE)) {
|
||||||
CachedMusicService(RESTMusicService(get(), get()))
|
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…
x
Reference in New Issue
Block a user