Thanks to visit codestin.com
Credit goes to github.com

Skip to content
/ axer Public

Axer is a lightweight Kotlin Multiplatform debugging library that provides real‑time HTTP monitoring (Ktor & OkHttp), crash and exception capturing, live Room database inspection, and built‑in logging —all in one.

License

Notifications You must be signed in to change notification settings

orioneee/axer

Repository files navigation

Axer logo

Axer Library

Maven Central Kotlin Docs Compose Multiplatform Android iOS JVM Kotlin Multiplatform License Build and deploy Axer Kotlin Multiplatform Tests

📑 Summary



Overview

Axer is a modern, multiplatform library for advanced runtime inspection and debugging in Kotlin/Android/JVM/iOS projects. It enables you to:

  • Monitor HTTP requests with deep inspection and redaction capabilities (Ktor/OkHttp supported)
  • Record and inspect exceptions (both fatal and non-fatal), and customize crash handling
  • View and edit Room databases in real time, run custom queries, and manage multiple DBs
  • Capture and display logs, powered by Napier
  • Use all these features locally or remotely via the Remote Debugger app

Axer is inspired by Chucker and KtorMonitor, LensLogger but adds multiplatform support and real-time database inspection, crashes, and logs.


Installation

Add the dependencies to your project (1.2.5 is the latest version; check Releases):

implementation("io.github.orioneee:axer:1.2.5")

For production, use the no-op variant to avoid runtime overhead and source changes:

implementation("io.github.orioneee:axer-no-op:1.2.5")

No-op maintains the same API, so switching in/out is seamless.


🚀 Remote Debugger Support

Axer now features remote debugging! You can run the Axer debugger app on your desktop, discover debuggable apps (JVM or Android) on your local network, and inspect requests, exceptions, logs, databases, and more — all remotely.

⚡️ Download the remote debugger app in the Releases section.
The standalone desktop debugger is distributed there.

⚠️ On MacOS:
If you see a warning about "unsigned" applications when launching the remote debugger, see the Opening Unsigned Applications on macOS Sequoia section below.

 

Enabling Remote Debugging

On your debuggable app (JVM/Android), manually start the Axer server:

// for example, in an Android Activity or ViewModel
// Also you can adjust port
Axer.runServerIfNotRunning(lifecycleScope) // has second parameter for custom port

//if you want stop server from code, you can use
Axer.stopServerIfRunning()
  • Note: Both debugger and debuggable device must be on the same network.
  • Only one server can be runned on one device at same time (Axer uses port 53214 by default), so if you want monitor multiple apps set different ports for each app or ensure only one server is running.

🔌 Port Forwarding via ADB (for Android Devices)

If your Android device is connected via ADB and you want to debug remotely from your PC avoid local network, you can forward a port using ADB:

adb forward tcp:11111 tcp:53214
  • 11111 — port on your PC (you can choose any free port)
  • 53214 — default port used by Axer server on the device

Now, in the Axer remote debugger app, connect to 127.0.0.1 (your local PC) and specify the chosen port (11111).
This will forward all traffic from your PC to the Axer server running on your Android device.

Also this work with emulators so you need just forawrd port, its can be the same port on pc for example

adb forward tcp:53214 tcp:53214

And now you can add in axer remote debugger ip 127.0.0.1, port 53214 and use it.

  • If you run Axer server on a custom port, just forward to that port instead.
  • If you run the server on a custom IP (e.g., on an emulator or in a specific network setup), specify that IP in the debugger app.

Summary table:

Scenario Connect to (host) Port
ADB port forwarding (local PC) 127.0.0.1 11111
Same network (Wi-Fi/LAN) Device's IP 53214
Custom port or IP Custom IP (chosen)

  • Note: Both debugger and debuggable device must be on the same network.
  • Only one server can be runned on one device at same time (Axer uses port 53214) so if you want monitor multiple app enshure only one server runned

Features & Usage

HTTP Request Monitoring

Axer monitors HTTP requests and highlights important data using customizable selectors.
Supports Ktor and OkHttp out of the box.

Ktor Example

val client = HttpClient {
  install(DefaultRequest) {
    contentType(ContentType.Application.Json)
    if (!headers.contains("Authorization")) {
      header("Authorization", "Bearer your_token_here")
    }
  }
  install(Axer.ktorPlugin) {
    requestReducer = { request ->
      val redactedHeaders = request.headers.mapValues { (key, value) ->
        if (key.equals("Authorization", ignoreCase = true)) "Bearer ***" else value
      }
      request.copy(headers = redactedHeaders)
    }
    responseReducer = { response ->
      response.copy(
        headers = response.headers.mapValues { (key, value) ->
          if (key.equals("Content-Type", ignoreCase = true)) "application/json" else value
        }
      )
    }
    requestImportantSelector = { request ->
      listOf("Authorization: ${request.headers["Authorization"] ?: "Not set"}")
    }
    responseImportantSelector = { response ->
      listOf("status: ${response.status}", "content-type: ${response.headers["Content-Type"]}")
    }
    retentionPeriodInSeconds = 60 * 60 * 1
    retentionSizeInBytes = 10 * 1024 * 1024
  }
}

OkHttp Example

val client = OkHttpClient.Builder()
  .addInterceptor(
    AxerOkhttpInterceptor.Builder()
      .setRequestReducer { request ->
        val redactedHeaders = request.headers.mapValues { (key, value) ->
          if (key.equals("Authorization", ignoreCase = true)) "Bearer ***" else value
        }
        request.copy(headers = redactedHeaders)
      }
      .setResponseReducer { response ->
        response.copy(
          headers = response.headers.mapValues { (key, value) ->
            if (key.equals("Content-Type", ignoreCase = true)) "application/json" else value
          }
        )
      }
      .setRequestImportantSelector { request ->
        listOf("Authorization: ${request.headers["Authorization"] ?: "Not set"}")
      }
      .setResponseImportantSelector { response ->
        listOf("status: ${response.status}", "content-type: ${response.headers["Content-Type"]}")
      }
      .setRetentionTime(60 * 60 * 1)
      .setRetentionSize(10 * 1024 * 1024)
      .build()
  )
  .build()

JVM Window

Display the Axer UI in your JVM app:

fun main() = application {
  AxerTrayWindow()
  ...
}

Or manually control the window:

fun main() = application {
  AxerWindows()
  ...
}

Call UI

Programmatically open the Axer UI:

Axer.openAxerUI()

UI Integration

Integrate Axer UI directly:

AxerUIEntryPoint().Screen()

Access the UI also from Android/iOS by clicking the notification (requires notification permissions).


Logger

Axer logging is powered by Napier.

  • Already use Napier?
    Just install the Axer log saver:

    Napier.base(AxerLogSaver())
  • Don't use Napier?
    Use Axer logger directly:

    Axer.d("App", "Test debug log")
    Axer.e("App", "Test error log")
    Axer.i("App", "Test info log")
    Axer.w("App", "Test warning log")
    Axer.v("App", "Test verbose log")
    Axer.wtf("App", "Test assert log")

    You can also log with exceptions and control saving with record = false.

Logs Screenshot
In IDE
IDE Logs Screenshot
In Axer

Exception Handling

Axer captures fatal crashes and manually recorded exceptions.

Fatal Crash Handling

Install the error handler on your main thread:

  • Android:

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Axer.installErrorHandler()
            ...
        }
    }
  • JVM:

    fun main() = application {
        Axer.installErrorHandler()
        ...
    }
  • iOS:

    fun MainViewController(): UIViewController {
        Axer.installErrorHandler()
        ...
    }

Customize crash handling by overriding AxerUncaughtExceptionHandler:

open class AxerUncaughtExceptionHandler : UncaughtExceptionHandler {
  // Custom implementation
}
...
Thread.setDefaultUncaughtExceptionHandler(MyUncaughtExceptionHandler())

Manual Exception Recording

Record exceptions manually:

Axer.recordException(Exception("Test exception"))
Axer.recordAsFatal(Exception("Test fatal exception"))

Room Database Inspection

Axer supports live Room DB inspection and custom queries, with multiple DB support.

Example Configuration

builder
  .setDriver(AxerBundledSQLiteDriver.getInstance())
  .setQueryCoroutineContext(Dispatchers.IO)
  .fallbackToDestructiveMigration(false)
  .build()

Only required setup:

.setDriver(AxerBundledSQLiteDriver.getInstance())

Runtime Configuration

Enable/disable monitoring options at runtime (all enabled by default):

Axer.configure {
  enableRequestMonitor = true
  enableExceptionMonitor = true
  enableLogMonitor = true
  enableDatabaseMonitor = true
}

iOS Limitations

  • Stack traces are not supported.
  • No support for remote debugging on iOS.

Inspiration

Axer is a lightweight, cross-platform HTTP logging library for Kotlin Multiplatform projects.
It’s inspired by Chucker and KtorMonitor, LensLogger with added multiplatform and Room DB inspection support.


📦 Dependency Versions

Dependency Version
Kotlin 2.2.10
Compose 1.9.0-rc01
Ktor 3.2.3
Koin 4.1.0
Room 2.7.2
OkHttp 5.1.0
Napier 2.7.1
kotlinx-coroutines 1.10.2
kotlinx-serialization 1.9.0
kotlinx-datetime 0.7.1
Accompanist 0.37.3
Coil Compose 3.3.0
Navigation Compose 2.9.0-beta04
minSdk 21

💡 Tips & Extras

  • For the latest desktop remote debugger, check Releases.
  • You can mix and match all features or use only what you need.
  • The API is intentionally minimal and consistent across platforms.

License

Apache License 2.0.

About

Axer is a lightweight Kotlin Multiplatform debugging library that provides real‑time HTTP monitoring (Ktor & OkHttp), crash and exception capturing, live Room database inspection, and built‑in logging —all in one.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors 4

  •  
  •  
  •  
  •  

Languages