In Android app development, efficiently managing the complete lifecycle of your app’s components is key to building and maintaining high-performance applications. However, tracking and optimizing the behavior of each component can become increasingly difficult as your app grows in complexity.
This is where the Kotzilla SDK steps in. It automatically captures detailed insights into the lifecycle of every component and dependency in your app, with a focus on performance metrics, memory consumption, and thread management. The SDK works in both development and production environments, without requiring any additional code instrumentation.
By tracking how components behave over time, the Kotzilla SDK helps you identify issues and bottlenecks that may affect your app's performance. Once the data is captured, it is securely transmitted to the Kotzilla Platform, where it is analyzed and presented through the Kotzilla Console.
This article will explore the data captured by the Kotzilla SDK, how it integrates with existing Koin logging capabilities, and how the platform’s insights will help you identify, diagnose, and resolve issues in your app.
Before diving into the details of the Kotzilla SDK, let's first review the existing native logging capabilities within Koin, which may be a good start to get initial data about your app's behavior
Koin provides a simple and extensible logging API to track dependency injection activities such as allocation, lookups, and resolution. The logging behavior can be adjusted based on the platform being used. Below are the available loggers in Koin:
Let’s walk through a concrete example of configuring AndroidLogger in a Koin-based app. We’ll use the NowInAndroid app to demonstrate how Koin’s logging capabilities work in practice.
During the startKoin initialization, we set the log level to DEBUG using the androidLogger.
override fun onCreate() {
super.onCreate()
startKoin {
androidContext(this@NiaApplication)
androidLogger(DEBUG) // Log level set to DEBUG
modules(appModule)
workManagerFactory()
}
}
Let’s build the project and run the app in Android Studio using the default emulator. Let’s also interact with the app, and then check the logs in the Logcat view. Below is an example of the Koin logs you might see, showing various operations such as component lookups, dependency resolution, and component creation:
|- 'com.google.samples.apps.nowinandroid.MainActivityViewModel' in 18.439 ms
D |- 'android.content.Context'...
D |- 'android.content.Context' in 0.216 ms
D |- 'androidx.metrics.performance.JankStats'...
D | >> parameters DefinitionParameters[com.google.samples.apps.nowinandroid.MainActivity@4016cd3]
D |- ? t:'androidx.metrics.performance.JankStats' - q:'null' look in injected parameters
D | (+) '[Factory: 'androidx.metrics.performance.JankStats']'
D |- 'androidx.metrics.performance.JankStats' in 4.9 ms
D |- 'com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor'...
D | (+) '[Singleton: 'com.google.samples.apps.nowinandroid.core.data.util.ConnectivityManagerNetworkMonitor',
binds:com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor]'
D |- 'android.content.Context'...
D |- 'android.content.Context' in 0.09 ms
D |- 'kotlinx.coroutines.CoroutineDispatcher'...
D |- 'kotlinx.coroutines.CoroutineDispatcher' in 0.063 ms
D |- 'com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor' in 7.669 ms
...
From analyzing these logs, we can learn:
android.content.Context
or kotlinx.coroutines.CoroutineDispatcher
are already available in memory.androidx.metrics.performance.JankStats
and com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
, are being created as factories or singletons.MainActivityViewModel
created in 18.439 ms and NetworkMonitor
created in 7.669 ms.This level of detail helps you track down which components are being created, their dependencies, and the performance of each operation.
Each log entry in Koin follows a consistent format, offering you a structured view of the dependency resolution process. Here's an example:
|- 'com.google.samples.apps.nowinandroid.MainActivityViewModel' in 18.439 ms
D
for Debug, I
for Info, E
for Error).Koin's native logging capabilities are useful for tracking and confirming specific events or actions during development. They provide visibility into component creation and dependency resolutions. However, this level of detail falls short when dealing with more complex applications, debugging intricate performance issues, or optimizing resource usage; especially in production environments. Manually analyzing these logs can quickly become overwhelming, and extracting actionable insights is both time-consuming and error-prone.
The Kotzilla SDK is designed to extend Koin’s logging capabilities, offering a more comprehensive set of data capture and performance analytics. The SDK operates with minimal overhead and leverages Koin's container directly to collect detailed metrics, allowing you to get a clearer picture of your app's behavior without impacting performance.
The Kotzilla SDK captures data that provides deeper insights into component lifecycles compared to logs. It tracks not only dependency resolutions but also metrics such as call frequencies, dependency trees, and performance over time. This session-based data helps identify inefficiencies and bottlenecks that are difficult to detect with logs, such as long-running operations blocking threads, which are required for diagnosing issues like ANRs or slow startup times.
Let’s now look at an updated example of how the NowInAndroid app is configured to use the Kotzilla SDK.
class NiaApplication : Application(), ImageLoaderFactory {
val imageLoader: ImageLoader by inject()
val profileVerifierLogger: ProfileVerifierLogger by inject()
override fun onCreate() {
super.onCreate()
// Initialize Kotzilla SDK
KotzillaSDK.setup(this)
// Start Koin with Kotzilla Analytics Logger
startKoin {
androidContext(this@NiaApplication)
analyticsLogger()
modules(appModule)
workManagerFactory()
}
...
}
In this updated example, the KotzillaSDK.setup(this)
method call initializes the Kotzilla SDK for the application. After this, Koin is configured with the analyticsLogger()
, which enables the logging of additional analytics and performance metrics, including dependency resolution times, thread usage, and more detailed lifecycle tracking.
Here’s a breakdown of the data captured by the Kotzilla SDK
While the SDK automatically collects essential data, a dedicated API provides a way to track additional events, manage sessions, and configure the SDK to meet specific needs:
KotzillaSDK.log("User clicked the submit button")
KotzillaSDK.log("an error occurred", exception)
KotzillaSDK.trace("my_code_block") { myComponent.MyHeavyCall() }
KotzillaSDK.setProperties("theme" to "dark", "loggedIn" to true)
KotzillaSDK.setUserId("user_123")
For more details about the Kotzilla SDK API visit the Kotzilla SDK API documentation.
The Kotzilla SDK ensures robust security and privacy for your app by using authentication and encryption protocols
Note: The Kotzilla SDK is RGPD-compliant and does not collect personal or user-specific data. It focuses solely on technical data required for debugging and optimization, ensuring the privacy of your users.
To ensure your app’s code privacy, all class and method names are obfuscated in release builds. This means that the names of your classes, methods, and variables will be transformed into unreadable strings.
To enable accurate debugging with the Kotzilla SDK, you need to upload the corresponding mapping file for the release builds. These mapping files are used to map the obfuscated names back to their original, readable versions. The mapping files must be properly configured and uploaded, as described in the Mapping Files documentation.
Once the data is captured, it is securely transmitted to the Kotzilla Platform, where it undergoes analysis and aggregation. This allows you to view the data in an intuitive and actionable format through the Kotzilla Console. The Console provides several views to help you explore and interpret the data, pinpointing areas for optimization and potential issues.
All your app issues, automatically detected and categorized
The Issues view identifies detected problems, including slow component initialization, dependency resolution delays, crashes, and displays impacted sessions and versions. Users can also update the status of each issue for better tracking
Explore impacted sessions, uncover the root cause, and resolve issues
Visualizes app component lifecycles, thread activity, and event correlations during user sessions to help identify the root causes of issues. It also provides a chronological sequence of events, allowing you to track how a specific issue unfolds during a user session and apply targeted fixes.
I hope this article give you a clearer understanding of the data captured by the Kotzilla SDK and how it extends beyond standard Koin logging to provide deeper insights into your app's performance and lifecycle.
If you want to start using the Kotzilla SDK and begin debugging your app's performance and lifecycle, follow the setup steps described in the getting started guide.
* Note: While this article used an Android app for illustration, the Kotzilla SDK also works natively in your Kotlin Multiplatform (KMP) apps, and can be used to debug or monitor your SDK libraries during development.