Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logging updates #130

Merged
merged 6 commits into from
Feb 20, 2024
Merged

Logging updates #130

merged 6 commits into from
Feb 20, 2024

Conversation

evan-masseau
Copy link
Contributor

Description

We intentionally disabled all log output from the SDK in our earlier releases. In order to provide some useful logging, I'm enabling it and merging log implementations. Rather than silence all output, I'm putting in a configurable log level that defaults to less verbose output. Warning+ for debug and Error+ for release.

Check List

  • Are you changing anything with the public API? NO
  • Are your changes backwards compatible with previous SDK Versions? YES
  • Have you tested this change on real device? YES
  • Have you added unit test coverage for your changes? YES
  • Have you verified that your changes are compatible with all Android versions the SDK currently supports? YES

Changelog / Code Overview

  • Enable logging in published SDK
  • Added warning level
  • Added level-aware logging with a configurable threshold
  • Threshold has a default based on debug vs release, and can be configured from code and/or manifest file
  • Adjusted log levels throughout the code
  • Updated tests, removed some old log related-test code from earlier build variants/flavors

Test Plan

  • Unit tests
  • Will test more extensively from android and react native test apps as I work on the wrapped API methods

Related Issues/Tickets

CHNL-5491

- Enable logging in published SDK
- Added level-aware logging with a configurable threshold
- Added warning level
- Threshold has a default based on debug/release, can be configured from code and from manifest
- Updated tests, removed some old log related test code from earlier build variants/flavors
- Adjusted log levels throughout the code
Evan Masseau added 2 commits February 13, 2024 17:04
Copy link
Contributor

@ajaysubra ajaysubra left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NICE!

emptyArray<String>()
}
}?.forEach { uuid ->
Registry.dataStore.fetch(uuid).let { json ->
if (json == null) {
Registry.log.error("Missing request JSON for $uuid")
Registry.log.debug("Missing request JSON for $uuid")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm why go from error to debug?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously, all these levels were only here for us to see, because in a published build there was no logging.
I didn't think this was worth logging in the client's application, so I lowered it so it won't be visible by the default logging level in a release build.

*/
private const val LOG_LEVEL = "com.klaviyo.core.log_level"

private val defaultLogLevel = if (BuildConfig.DEBUG) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you override this with the manifest setting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this is the default based on build config, then the host app can set it from the manifest, or by importing core and changing logLevel at runtime (which I probably won't advertise, but wanted for the test app)


return _logLevel ?: defaultLogLevel
}
set(value) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a public setter, you can also change log level from runtime if you import core from gradle

@@ -152,13 +152,13 @@ internal object KlaviyoApiClient : ApiClient {
} catch (exception: JSONException) {
wasMutated = true
Registry.log.wtf("Invalid persistent queue JSON", exception)
Registry.log.debug(it)
Registry.log.info(it)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting this jumped from debug to info whereas other jumps were maybe not as severe I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. Almost all cases I reduced log level. But there were two cases where we had a wtf error followed by some additional explanatory data. I thought in those cases info made more sense.

@@ -169,8 +169,8 @@ internal object KlaviyoApiClient : ApiClient {
} catch (exception: JSONException) {
wasMutated = true
Registry.log.wtf("Invalid request JSON $uuid", exception)
Registry.log.info(json)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double checking here...you changed the order of operations but this seems consistent with the block above so I think it's fine.

@@ -13,6 +13,8 @@ import org.junit.Test
internal class DevicePropertiesTest : BaseTest() {

private val mockVersionCode = 123

@Suppress("DEPRECATION")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PackageInfo is deprecated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forget which, either versionCode or longVersionCode is deprecated, but we have to use it to support past versions of android so its annoying to have the warning always popping up.

if (_logLevel == null && Registry.isRegistered<Config>()) {
_logLevel = Registry.config.getManifestInt(LOG_LEVEL, defaultLogLevel.ordinal).let {
Level.entries.getOrNull(it) ?: defaultLogLevel.also { default ->
default.log(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a mindbender logging that you can't get the log level! 😂

_logLevel = Registry.config.getManifestInt(LOG_LEVEL, defaultLogLevel.ordinal).let {
Level.entries.getOrNull(it) ?: defaultLogLevel.also { default ->
default.log(
"KlaviyoLog",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth a constant maybe?

Level.Warning -> Log.w(tag, msg, ex)
Level.Error -> Log.e(tag, msg, ex)
Level.Assert -> Log.wtf(tag, msg, ex)
Level.None -> 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does log return a number or just have to return something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah all the android util methods return Int so I just kept it consistent. I could also convert it to return void/Unit i suppose.

private var _logLevel: Level? = null
override var logLevel: Level
get() {
if (_logLevel == null && Registry.isRegistered<Config>()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why check isRegistered here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is checking if applicationContext will be available through Config. Without it, we can't read from the manifest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise, accessing Registry.Config would throw an exception, then we'd try to log the exception... ♾️

*
* To configure from manifest, specify the minimum log level to output:
*
* 0 = Disable logging
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm...is this reversed from the setting we documented?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh crud, yeah good catch, now to remember which one is correct 🤣

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe not reversed is assert in the wrong spot though or doesn't matter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the readme is currently incorrect. I think I went with 0 = disable, 1 = verbose+, 2 = debug+ etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://developer.android.com/reference/android/util/Log it should match stuff in here right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in spirit anyway. For some reason theirs go from 2 to 7. But lower number = lower severity was my intent. I fixed values in the readme

Evan Masseau added 2 commits February 20, 2024 16:01
…ecm/logging

# Conflicts:
#	sdk/analytics/src/main/java/com/klaviyo/analytics/Klaviyo.kt
#	sdk/core/src/test/java/com/klaviyo/core/RegistryTest.kt
@evan-masseau evan-masseau merged commit 1500879 into master Feb 20, 2024
1 of 2 checks passed
@evan-masseau evan-masseau deleted the ecm/logging branch February 20, 2024 21:08
evan-masseau added a commit that referenced this pull request Feb 21, 2024
…ze method (#131)* Internalize the lifecycle listener attachment.* Mark the public property to be deprecated and replace with a no-op implementation to avoid duplicate listeners.* Update readme instructions, migration guide.---------Co-authored-by: Evan Masseau <>" (#136)

* Auto generate documentation PRs (#124)

Automate all the things

Co-authored-by: Evan Masseau <>

* Minor README and Documentation Updates (#121)

* Fixed SDK name in license section
* Fixed appearance of some of the advanced section after seeing it on the dokka html
* Other grammar/spelling fixes

---------

Co-authored-by: Evan Masseau <>

* Add note about anonymous profiles to readme (#127)


---------

Co-authored-by: Evan Masseau <>

* Wrap public methods in try/catch (#129)

Added safety checks around public API methods to prevent throwing exceptions that would otherwise crash the host application

---------

Co-authored-by: Evan Masseau <>

* Logging (#130)

- Enable logging in published SDK
- Added level-aware logging with a configurable threshold from code or manifest file.
- Added warning level
- Threshold has a default based on debug/release, can be configured from code and from manifest
- Updated tests, removed some old log related test code from earlier build variants/flavors
- Adjusted log levels throughout the code

---------

Co-authored-by: Evan Masseau <>

* Attach lifecycle listeners internally in initialize method (#131)

* Internalize the lifecycle listener attachment.
* Mark the public property to be deprecated and replace with a no-op implementation to avoid duplicate listeners.
* Update readme instructions, migration guide.

---------

Co-authored-by: Evan Masseau <>

* Generated docs for e9598b0

---------

Co-authored-by: Evan C Masseau <5167687+evan-masseau@users.noreply.github.com>
Co-authored-by: github-actions <github-actions@github.com>
evan-masseau pushed a commit that referenced this pull request Mar 18, 2024
…ation

* commit 'b12ef65b0d460b343c4d1eb2bac6e227a6f51d62':
  Release Version 2.1.0 (#137)
  Attach lifecycle listeners internally in initialize method (#131)
  Logging (#130)
  Wrap public methods in try/catch (#129)
  Add note about anonymous profiles to readme (#127)
  Minor README and Documentation Updates (#121)
  Auto generate documentation PRs (#124)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants