Skip to content

A Kotlin Developer's Guide to the Kotzilla SDK

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.

Understanding Koin logging

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:

  • PrintLogger: log messages are displayed in the console output (koin-core)
  • EmptyLogger: Disables all logging so no log messages will be generated or displayed (koin-core
  • SLF4JLogger: Integrates with SLF4J, used in server-side Kotlin applications (koin-logger-slf4j).
  • AndroidLogger: Logs directly to Android's Logcat (koin-android).

A concrete example using AndroidLogger

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:

  • Component lookups: Koin is checking if components such as android.content.Context or kotlinx.coroutines.CoroutineDispatcher are already available in memory.
  • Component creation: Several components, including androidx.metrics.performance.JankStats and com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor, are being created as factories or singletons.
  • Execution time: The logs show execution times for component creation, such as 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.

Structure of a Koin log entry

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

Key components of a log entry

  • Event date: Timestamp when the log entry was recorded.
  • Log level: Severity of the log (D for Debug, I for Info, E for Error).
  • Origin: The source of the log, such as Koin, the Android app lifecycle, or any third-party libraries.
  • Action: Describes what Koin did, such as creating an instance or resolving a dependency.
  • Execution time: Time taken by Koin to resolve or create the component

Log symbols and their meanings

  • |-: Koin has started looking for or resolved a component. If execution time is present, it means the component was created; if absent, it indicates reuse.
  • (+): Koin is creating a new component.
  • *: Koin failed to find the required component.

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.

Data capture using the Kotzilla SDK

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.

Example using the Kotzilla SDK in the NowInAndroid app

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

  • Application structure data
    • Definition Information: Captures the type, kind, and binding relationships of components, including child dependencies and their respective connections.
    • Component tree view: For each session, the SDK records the entire component tree, allowing you to visualize the relationship between dependencies and how they evolve during the app’s lifecycle.
    • Dynamic parts: Tracks injected parameters, scoped dependencies, and thread usage, giving you a detailed view of how dependencies are resolved across different threads.
    • Version-specific data: Tracks data computation for each app version, enabling you to compare performance over time.
  • Component statistics
    • Creation statistics: Captures the number of times a dependency is created, the number of calls made, and the depth of dependency trees, helping identify excessive object creation or complex dependency chains.
    • Performance metrics: Provides average creation and call times for each dependency, including both initial creation times and the time spent resolving already-created components.
    • Type of definition: Identifies whether dependencies are singletons, factories, or other types, and analyzes their memory stability over time, helping spot inefficient usage.
  • UI timeline: The SDK tracks the lifecycle of Activities, Fragments, and other UI components, providing a timeline of their creation and resolution.
  • Code tracing: the Kotzilla SDK measures execution time for function calls, helping identify performance bottlenecks and optimize resource usage.

The Kotzilla SDK API

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:

Add custom log messages to track important app events

KotzillaSDK.log("User clicked the submit button")

Log exceptions and errors

KotzillaSDK.log("an error occurred", exception)

Measure execution time for specific code blocks

KotzillaSDK.trace("my_code_block") { myComponent.MyHeavyCall() }

Track custom session data like user preferences

KotzillaSDK.setProperties("theme" to "dark", "loggedIn" to true)

Associate session data with a unique user ID

KotzillaSDK.setUserId("user_123")

For more details about the Kotzilla SDK API visit the Kotzilla SDK API documentation.

Authentication and security

The Kotzilla SDK ensures robust security and privacy for your app by using authentication and encryption protocols

  • Authentication tokens and API Keys: Ensures secure, encrypted communication between the SDK and the Kotzilla cloud platform.
  • HTTPS encryption: All data transmitted between your application and the Kotzilla Platform is encrypted via HTTPS, ensuring confidentiality and integrity.

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.

Code privacy

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. 

How is the Kotzilla SDK data used in the Kotzilla Platform?

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.

Key features of the Kotzilla console

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

Screenshot 2024-12-30 at 14.33.03

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.

VISUEL KOTZILLA HOMEPAGE 1 (1) (1)

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.