From 8c49d369102e1ca962e41430d21a0ed91f874f03 Mon Sep 17 00:00:00 2001 From: Andrii Mikhin Date: Mon, 4 Jan 2021 12:35:32 +0200 Subject: [PATCH 1/2] Implement fastlog --- .../main/java/eu/bolt/kalev/AndroidFastLog.kt | 25 +++++++++++++++++ .../src/main/java/eu/bolt/kalev/PrintPoeg.kt | 24 ++--------------- .../java/eu/bolt/kalev/utils/TagGenerator.kt | 24 +++++++++++++++++ .../src/main/java/eu/bolt/kalev/Kalev.kt | 7 +++++ .../main/java/eu/bolt/kalev/fast/FastLog.kt | 10 +++++++ .../java/eu/bolt/kalev/fast/SystemFastLog.kt | 27 +++++++++++++++++++ .../eu/bolt/kalev/sample/SampleActivity.kt | 4 +++ .../java/eu/bolt/kalev/sample/SampleApp.kt | 3 +++ 8 files changed, 102 insertions(+), 22 deletions(-) create mode 100644 kalev-android/src/main/java/eu/bolt/kalev/AndroidFastLog.kt create mode 100644 kalev-android/src/main/java/eu/bolt/kalev/utils/TagGenerator.kt create mode 100644 kalev-lib/src/main/java/eu/bolt/kalev/fast/FastLog.kt create mode 100644 kalev-lib/src/main/java/eu/bolt/kalev/fast/SystemFastLog.kt diff --git a/kalev-android/src/main/java/eu/bolt/kalev/AndroidFastLog.kt b/kalev-android/src/main/java/eu/bolt/kalev/AndroidFastLog.kt new file mode 100644 index 0000000..4ad6d3c --- /dev/null +++ b/kalev-android/src/main/java/eu/bolt/kalev/AndroidFastLog.kt @@ -0,0 +1,25 @@ +package eu.bolt.kalev + +import android.util.Log +import eu.bolt.kalev.fast.FastLog +import eu.bolt.kalev.utils.generateTag + +class AndroidFastLog : FastLog { + + private val stackDepth = 3 + + override fun v(message: String, tag: String?) { + val finalTag = tag ?: generateTag(stackDepth) + Log.v(finalTag, message) + } + + override fun d(message: String, tag: String?) { + val finalTag = tag ?: generateTag(stackDepth) + Log.d(finalTag, message) + } + + override fun i(message: String, tag: String?) { + val finalTag = tag ?: generateTag(stackDepth) + Log.i(finalTag, message) + } +} diff --git a/kalev-android/src/main/java/eu/bolt/kalev/PrintPoeg.kt b/kalev-android/src/main/java/eu/bolt/kalev/PrintPoeg.kt index 344c599..f30e955 100644 --- a/kalev-android/src/main/java/eu/bolt/kalev/PrintPoeg.kt +++ b/kalev-android/src/main/java/eu/bolt/kalev/PrintPoeg.kt @@ -1,14 +1,11 @@ package eu.bolt.kalev -import android.os.Build import android.util.Log +import eu.bolt.kalev.utils.generateTag import org.json.JSONObject -import java.util.regex.Pattern class PrintPoeg : Kalevipoeg { - private val anonymousClassPattern = Pattern.compile("(\\$\\d+)+$") - private val maxTagLength = 23 private val callStackIndex = 6 override fun log(entry: LogEntry) { @@ -22,24 +19,7 @@ class PrintPoeg : Kalevipoeg { } private fun getTag(entry: LogEntry): String { - return entry.tag ?: createStackElementTag() - } - - private fun createStackElementTag(): String { - val stackTrace = Throwable().stackTrace - check(stackTrace.size > callStackIndex) { "Synthetic stacktrace didn't have enough elements: are you using proguard?" } - val element = stackTrace[callStackIndex] - - var tag = element.className - val matcher = anonymousClassPattern.matcher(tag) - if (matcher.find()) { - tag = matcher.replaceAll("") - } - tag = tag.substring(tag.lastIndexOf('.') + 1) - // Tag length limit was removed in API 24. - return if (tag.length <= maxTagLength || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - tag - } else tag.substring(0, maxTagLength) + return entry.tag ?: generateTag(callStackIndex) } private fun LogEntry.formatString(): String { diff --git a/kalev-android/src/main/java/eu/bolt/kalev/utils/TagGenerator.kt b/kalev-android/src/main/java/eu/bolt/kalev/utils/TagGenerator.kt new file mode 100644 index 0000000..79d41fc --- /dev/null +++ b/kalev-android/src/main/java/eu/bolt/kalev/utils/TagGenerator.kt @@ -0,0 +1,24 @@ +package eu.bolt.kalev.utils + +import android.os.Build +import java.util.regex.Pattern + +private val anonymousClassPattern = Pattern.compile("(\\$\\d+)+$") +private const val maxTagLength = 23 + +internal fun generateTag(stackDepth: Int): String { + val stackTrace = Throwable().stackTrace + check(stackTrace.size > stackDepth) { "Synthetic stacktrace didn't have enough elements: are you using proguard?" } + val element = stackTrace[stackDepth] + + var tag = element.className + val matcher = anonymousClassPattern.matcher(tag) + if (matcher.find()) { + tag = matcher.replaceAll("") + } + tag = tag.substring(tag.lastIndexOf('.') + 1) + // Tag length limit was removed in API 24. + return if (tag.length <= maxTagLength || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + tag + } else tag.substring(0, maxTagLength) +} diff --git a/kalev-lib/src/main/java/eu/bolt/kalev/Kalev.kt b/kalev-lib/src/main/java/eu/bolt/kalev/Kalev.kt index 8aa6206..02098df 100644 --- a/kalev-lib/src/main/java/eu/bolt/kalev/Kalev.kt +++ b/kalev-lib/src/main/java/eu/bolt/kalev/Kalev.kt @@ -1,5 +1,7 @@ package eu.bolt.kalev +import eu.bolt.kalev.fast.FastLog + @Suppress("MemberVisibilityCanBePrivate", "unused") object Kalev { @@ -16,6 +18,11 @@ object Kalev { var nop = false private val nopEntry = NopLogEntry + /** + * FastLog can be used for performance-sensitive logging. Note that FastLog will NOT trigger log consumers + */ + var fastLog: FastLog? = null + private val consumers = mutableListOf() @JvmStatic diff --git a/kalev-lib/src/main/java/eu/bolt/kalev/fast/FastLog.kt b/kalev-lib/src/main/java/eu/bolt/kalev/fast/FastLog.kt new file mode 100644 index 0000000..43d944b --- /dev/null +++ b/kalev-lib/src/main/java/eu/bolt/kalev/fast/FastLog.kt @@ -0,0 +1,10 @@ +package eu.bolt.kalev.fast + +interface FastLog { + + fun v(message: String, tag: String? = null) + + fun d(message: String, tag: String? = null) + + fun i(message: String, tag: String? = null) +} diff --git a/kalev-lib/src/main/java/eu/bolt/kalev/fast/SystemFastLog.kt b/kalev-lib/src/main/java/eu/bolt/kalev/fast/SystemFastLog.kt new file mode 100644 index 0000000..b4d806a --- /dev/null +++ b/kalev-lib/src/main/java/eu/bolt/kalev/fast/SystemFastLog.kt @@ -0,0 +1,27 @@ +package eu.bolt.kalev.fast + +/** + * Default [FastLog] implementation which prints the logs to standard output + */ +class SystemFastLog : FastLog { + + override fun v(message: String, tag: String?) { + print(message, tag) + } + + override fun d(message: String, tag: String?) { + print(message, tag) + } + + override fun i(message: String, tag: String?) { + print(message, tag) + } + + private fun print(message: String, tag: String?) { + if (tag == null) { + println(message) + } else { + println(StringBuilder(tag).append(": ").append(message).toString()) + } + } +} diff --git a/sample/src/main/java/eu/bolt/kalev/sample/SampleActivity.kt b/sample/src/main/java/eu/bolt/kalev/sample/SampleActivity.kt index f4b68a0..a7d5540 100644 --- a/sample/src/main/java/eu/bolt/kalev/sample/SampleActivity.kt +++ b/sample/src/main/java/eu/bolt/kalev/sample/SampleActivity.kt @@ -17,16 +17,20 @@ class SampleActivity : Activity() { findViewById(R.id.click).setOnClickListener { clickCounter += 1 Kalev.with("counter", clickCounter).d("Click") + Kalev.fastLog?.d("Click") } findViewById(R.id.networkGet).setOnClickListener { networkDemo.doGet() + Kalev.fastLog?.d("Started network request") } findViewById(R.id.networkErr).setOnClickListener { networkDemo.doNotFound() + Kalev.fastLog?.d("Started network request") } Kalev.d("On start") + Kalev.fastLog?.v("Activity created") } } diff --git a/sample/src/main/java/eu/bolt/kalev/sample/SampleApp.kt b/sample/src/main/java/eu/bolt/kalev/sample/SampleApp.kt index 51445d1..0f5687b 100644 --- a/sample/src/main/java/eu/bolt/kalev/sample/SampleApp.kt +++ b/sample/src/main/java/eu/bolt/kalev/sample/SampleApp.kt @@ -1,8 +1,10 @@ package eu.bolt.kalev.sample import android.app.Application +import eu.bolt.kalev.AndroidFastLog import eu.bolt.kalev.Kalev import eu.bolt.kalev.PrintPoeg +import eu.bolt.kalev.fast.SystemFastLog class SampleApp : Application() { @@ -11,6 +13,7 @@ class SampleApp : Application() { if (BuildConfig.DEBUG) { Kalev.addPoeg(PrintPoeg()) + Kalev.fastLog = AndroidFastLog() } } } \ No newline at end of file From 4994f85ac5d6cc095609eb55f0dd39dd2147bc6b Mon Sep 17 00:00:00 2001 From: Andrii Mikhin Date: Mon, 4 Jan 2021 13:03:41 +0200 Subject: [PATCH 2/2] Update documentation --- README.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3c73e38..88acc96 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ The idea of `Kalev` is pretty similar to `Timber`. Library provides `Kalevipoeg` ## Packages -`kalev-lib` provides pure JVM implementation. Doesn't cotains any implementation of `Kalevipoeg` -`kalev-android` contains bridge between Kalev and Android's log system. `PrintPoeg` format log entry as JSON string and print it to LogCat +`kalev-lib` provides pure JVM implementation. Doesn't contains any implementation of `Kalevipoeg` +`kalev-android` contains bridge between Kalev and Android's log system. `PrintPoeg` format log entry as JSON string and print it to LogCat. `kalev-okhttp` provide interceptor for `okhttp` to log network requests in Kalev-way @@ -15,7 +15,7 @@ The idea of `Kalev` is pretty similar to `Timber`. Library provides `Kalevipoeg` Two easy steps: -1. Add any `Kalevipoeg` instances you want on application start. In Android application `onCreate` is a mosst suetable place +1. Add any `Kalevipoeg` instances you want on application start. In Android application `onCreate` is a most suitable place 2. Call Kalev's static methods everywhere throughout your app. Check full Android sample at `sample` dir @@ -96,27 +96,39 @@ Examples of network logs: { "message": "network", "method": "GET", - "path": "\/gett", + "path": "\/unknown", "id": "42", "response.code": 404, "response.body": "\n404 Not Found<\/title>\n<h1>Not Found<\/h1>\n<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.<\/p>\n" } ``` +### FastLog +Kalev creates new object for every log entry which may abuse performance in case of stream of entries. You can go around of this issue with FastLog. + +#### FastLog usage +There is `FastLog` interface which describes fast logger. +`kalev-lib` provides `SystemFastLog` implementation which prints messages to standard output stream +`kalev-android` provides `AndroidFastLog` implementation which prints messages to Android's LogCat +##### Initialisation: +`Kalev.fastLog = AndroidFastLog()` +##### Logging +`Kalev.fastLog?.v("Activity created")` + ## Gradle Add this to your dependencies block. ``` -implementation 'eu.bolt:kalev:1.0.1' +implementation 'eu.bolt:kalev:$latest' ``` To use an android extension use this dependency instead: ``` -implementation 'eu.bolt:kalev-android:1.0.1' +implementation 'eu.bolt:kalev-android:$latest' ``` Kalev-okhttp package: ``` -implementation 'eu.bolt:kalev-okhttp:1.0.1' +implementation 'eu.bolt:kalev-okhttp:$latest' ``` ## Naming