Add logging with Timber

This commit is contained in:
Kirill Kamakin
2021-11-07 12:13:46 +03:00
parent b0a53b5991
commit daa8006e4e
9 changed files with 59 additions and 10 deletions

View File

@@ -65,6 +65,8 @@ dependencies {
implementation "androidx.preference:preference-ktx:1.1.1" implementation "androidx.preference:preference-ktx:1.1.1"
implementation 'com.jakewharton.timber:timber:5.0.1'
testImplementation "junit:junit:4.13.2" testImplementation "junit:junit:4.13.2"
androidTestImplementation "androidx.test.ext:junit:1.1.3" androidTestImplementation "androidx.test.ext:junit:1.1.3"

View File

@@ -4,11 +4,13 @@ import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealie.databinding.MainActivityBinding import gq.kirmanak.mealie.databinding.MainActivityBinding
import timber.log.Timber
@AndroidEntryPoint @AndroidEntryPoint
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Timber.v("onCreate() called with: savedInstanceState = $savedInstanceState")
val binding = MainActivityBinding.inflate(layoutInflater) val binding = MainActivityBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
} }

View File

@@ -2,6 +2,13 @@ package gq.kirmanak.mealie
import android.app.Application import android.app.Application
import dagger.hilt.android.HiltAndroidApp import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber
@HiltAndroidApp @HiltAndroidApp
class MealieApp : Application() class MealieApp : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
Timber.v("onCreate() called")
}
}

View File

@@ -5,11 +5,13 @@ import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.MediaType import okhttp3.MediaType
import retrofit2.Retrofit import retrofit2.Retrofit
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ExperimentalSerializationApi @ExperimentalSerializationApi
class RetrofitBuilder @Inject constructor() { class RetrofitBuilder @Inject constructor() {
fun buildRetrofit(baseUrl: String): Retrofit { fun buildRetrofit(baseUrl: String): Retrofit {
Timber.v("buildRetrofit() called with: baseUrl = $baseUrl")
val url = if (baseUrl.startsWith("http")) baseUrl else "https://$baseUrl" val url = if (baseUrl.startsWith("http")) baseUrl else "https://$baseUrl"
val contentType = MediaType.get("application/json") val contentType = MediaType.get("application/json")
return Retrofit.Builder() return Retrofit.Builder()

View File

@@ -3,6 +3,7 @@ package gq.kirmanak.mealie.data.auth
import gq.kirmanak.mealie.data.RetrofitBuilder import gq.kirmanak.mealie.data.RetrofitBuilder
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import retrofit2.create import retrofit2.create
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ExperimentalSerializationApi @ExperimentalSerializationApi
@@ -14,12 +15,15 @@ class AuthDataSourceImpl @Inject constructor(
password: String, password: String,
baseUrl: String baseUrl: String
): Result<String> { ): Result<String> {
Timber.v("authenticate() called with: username = $username, password = $password, baseUrl = $baseUrl")
val authService = retrofitBuilder.buildRetrofit(baseUrl).create<AuthService>() val authService = retrofitBuilder.buildRetrofit(baseUrl).create<AuthService>()
val response = try { val response = try {
authService.getToken(username, password) authService.getToken(username, password)
} catch (e: Exception) { } catch (e: Exception) {
Timber.e("Authenticate() exception", e)
return Result.failure(e) return Result.failure(e)
} }
Timber.d("authenticate() response is $response")
return Result.success(response.accessToken) return Result.success(response.accessToken)
} }
} }

View File

@@ -1,19 +1,27 @@
package gq.kirmanak.mealie.data.auth package gq.kirmanak.mealie.data.auth
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
class AuthRepoImpl @Inject constructor( class AuthRepoImpl @Inject constructor(
private val dataSource: AuthDataSource, private val dataSource: AuthDataSource,
private val storage: AuthStorage private val storage: AuthStorage
) : AuthRepo { ) : AuthRepo {
override suspend fun isAuthenticated(): Boolean = storage.isAuthenticated() override suspend fun isAuthenticated(): Boolean {
Timber.v("isAuthenticated")
val authenticated = storage.isAuthenticated()
Timber.d("isAuthenticated() response $authenticated")
return authenticated
}
override suspend fun authenticate( override suspend fun authenticate(
username: String, username: String,
password: String, password: String,
baseUrl: String baseUrl: String
): Throwable? { ): Throwable? {
Timber.v("authenticate() called with: username = $username, password = $password, baseUrl = $baseUrl")
val authResult = dataSource.authenticate(username, password, baseUrl) val authResult = dataSource.authenticate(username, password, baseUrl)
Timber.d("authenticate result is $authResult")
if (authResult.isFailure) return authResult.exceptionOrNull() if (authResult.isFailure) return authResult.exceptionOrNull()
val token = checkNotNull(authResult.getOrNull()) val token = checkNotNull(authResult.getOrNull())
storage.storeToken(token) storage.storeToken(token)

View File

@@ -6,6 +6,7 @@ import androidx.preference.PreferenceManager
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
private const val TOKEN_KEY = "AUTH_TOKEN" private const val TOKEN_KEY = "AUTH_TOKEN"
@@ -15,10 +16,14 @@ class AuthStorageImpl @Inject constructor(@ApplicationContext private val contex
get() = PreferenceManager.getDefaultSharedPreferences(context) get() = PreferenceManager.getDefaultSharedPreferences(context)
override suspend fun isAuthenticated(): Boolean = withContext(Dispatchers.IO) { override suspend fun isAuthenticated(): Boolean = withContext(Dispatchers.IO) {
sharedPreferences.getString(TOKEN_KEY, null) != null Timber.v("isAuthenticated() called")
val token = sharedPreferences.getString(TOKEN_KEY, null)
Timber.d("isAuthenticated: token is $token")
token != null
} }
override suspend fun storeToken(token: String) { override suspend fun storeToken(token: String) {
Timber.d("storeToken() called with: token = $token")
sharedPreferences.edit().putString(TOKEN_KEY, token).apply() sharedPreferences.edit().putString(TOKEN_KEY, token).apply()
} }
} }

View File

@@ -1,7 +1,6 @@
package gq.kirmanak.mealie.ui.auth package gq.kirmanak.mealie.ui.auth
import android.os.Bundle import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@@ -13,6 +12,7 @@ import androidx.lifecycle.lifecycleScope
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import gq.kirmanak.mealie.databinding.FragmentAuthenticationBinding import gq.kirmanak.mealie.databinding.FragmentAuthenticationBinding
import timber.log.Timber
private const val TAG = "AuthenticationFragment" private const val TAG = "AuthenticationFragment"
@@ -25,6 +25,7 @@ class AuthenticationFragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
Timber.v("onCreate() called with: savedInstanceState = $savedInstanceState")
checkIfAuthenticatedAlready() checkIfAuthenticatedAlready()
} }
@@ -33,18 +34,19 @@ class AuthenticationFragment : Fragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View { ): View {
Timber.v("onCreateView() called with: inflater = $inflater, container = $container, savedInstanceState = $savedInstanceState")
_binding = FragmentAuthenticationBinding.inflate(inflater, container, false) _binding = FragmentAuthenticationBinding.inflate(inflater, container, false)
return binding.root return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.button.setOnClickListener { Timber.v("onViewCreated() called with: view = $view, savedInstanceState = $savedInstanceState")
onLoginClicked() binding.button.setOnClickListener { onLoginClicked() }
}
} }
private fun checkIfAuthenticatedAlready() { private fun checkIfAuthenticatedAlready() {
Timber.v("checkIfAuthenticatedAlready() called")
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
@@ -56,6 +58,7 @@ class AuthenticationFragment : Fragment() {
} }
private fun onLoginClicked() { private fun onLoginClicked() {
Timber.v("onLoginClicked() called")
val email: String val email: String
val pass: String val pass: String
val url: String val url: String
@@ -72,7 +75,6 @@ class AuthenticationFragment : Fragment() {
} }
lifecycleScope.launchWhenResumed { lifecycleScope.launchWhenResumed {
val exception = viewModel.authenticate(email, pass, url) val exception = viewModel.authenticate(email, pass, url)
Log.e(TAG, "onLoginClicked: ", exception)
Toast.makeText( Toast.makeText(
requireContext(), requireContext(),
"Exception is ${exception?.message ?: "null"}", "Exception is ${exception?.message ?: "null"}",
@@ -86,7 +88,9 @@ class AuthenticationFragment : Fragment() {
inputLayout: TextInputLayout, inputLayout: TextInputLayout,
errorText: () -> String errorText: () -> String
): String? { ): String? {
Timber.v("checkIfInputIsEmpty() called with: input = " + input + ", inputLayout = " + inputLayout + ", errorText = " + errorText)
val text = input.text?.toString() val text = input.text?.toString()
Timber.d("Input text is \"$text\"")
if (text.isNullOrBlank()) { if (text.isNullOrBlank()) {
inputLayout.error = errorText() inputLayout.error = errorText()
return null return null
@@ -96,6 +100,7 @@ class AuthenticationFragment : Fragment() {
override fun onDestroyView() { override fun onDestroyView() {
super.onDestroyView() super.onDestroyView()
Timber.v("onDestroyView() called")
_binding = null _binding = null
} }
} }

View File

@@ -3,15 +3,29 @@ package gq.kirmanak.mealie.ui.auth
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import gq.kirmanak.mealie.data.auth.AuthRepo import gq.kirmanak.mealie.data.auth.AuthRepo
import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
class AuthenticationViewModel @Inject constructor( class AuthenticationViewModel @Inject constructor(
private val authRepo: AuthRepo private val authRepo: AuthRepo
) : ViewModel() { ) : ViewModel() {
suspend fun isAuthenticated(): Boolean = authRepo.isAuthenticated() init {
Timber.v("constructor called")
}
suspend fun isAuthenticated(): Boolean {
Timber.v("isAuthenticated() called")
val result = authRepo.isAuthenticated()
Timber.d("isAuthenticated() returned: $result")
return result
}
suspend fun authenticate(username: String, password: String, baseUrl: String): Throwable? { suspend fun authenticate(username: String, password: String, baseUrl: String): Throwable? {
return authRepo.authenticate(username, password, baseUrl) Timber.v("authenticate() called with: username = $username, password = $password, baseUrl = $baseUrl")
val result = authRepo.authenticate(username, password, baseUrl)
if (result == null) Timber.d("authenticate() returns null")
else Timber.e("authenticate() returns error", result)
return result
} }
} }