Skip to content

sonrohan/ObservabilityToolshopEvaluator

Repository files navigation

Observability Toolshop Evaluator

A sample Android app for evaluating and comparing mobile observability SDKs. This project integrates two major observability platforms through a unified facade, allowing side-by-side comparison of their features, performance, and developer experience.

Integrated SDKs

SDK Version Focus Area
Sentry 8.26.0 Crash reporting, distributed tracing, error monitoring
Embrace 8.1.0 Mobile-focused observability, OpenTelemetry support

Architecture

The app uses a facade pattern that dispatches all observability calls to all registered SDKs simultaneously:

┌─────────────────────────────────────────────────────────────┐
│                     App Code                                 │
│     Logger.logScreenView()  /  ObservabilityManager.log()   │
└─────────────────────────────┬───────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                  ObservabilityManager                        │
│         (Dispatches to all registered providers)            │
└──────────┬──────────┬──────────┬────────────────────────────┘
           │          │          │
           ▼          ▼          ▼
      ┌────────┐ ┌────────┐ ┌────────┐
      │Console │ │Embrace │ │Sentry  │
      │Provider│ │Adapter │ │Adapter │
      └────────┘ └────────┘ └────────┘

Quick Start

1. Clone and Setup

git clone https://github.com/sonrohan/ObservabilityToolshopEvaluator.git
cd ObservabilityToolshopEvaluator

2. Configure SDK Keys

Copy the example files and add your SDK keys:

# Main environment file (for Sentry)
cp .env.example .env

# Embrace requires a separate config file (in app/src/main/)
cp app/src/main/embrace-config.example.json app/src/main/embrace-config.json

Edit .env with your Sentry DSN:

SENTRY_DSN=https://your-key@o123456.ingest.sentry.io/1234567

Edit app/src/main/embrace-config.json:

{
  "app_id": "your-app-id",
  "api_token": "your-api-token",
  "ndk_enabled": false
}

Note: You don't need all keys. SDKs with empty/missing keys are simply skipped during initialization.

3. Build and Run

./gradlew installDebug

Or open in Android Studio and run.

Getting SDK Keys

SDK Where to Get Keys
Sentry sentry.io → Settings → Projects → Client Keys (DSN)
Embrace dash.embrace.io → Settings → App Settings

Usage

Basic Logging

import com.sonrohan.observabilitytoolshipevaluator.observability.ObservabilityManager
import com.sonrohan.observabilitytoolshipevaluator.observability.LogLevel

// Log at different levels
ObservabilityManager.debug("User opened settings")
ObservabilityManager.info("Data loaded", mapOf("count" to 42))
ObservabilityManager.warning("Cache miss", mapOf("key" to "user_prefs"))
ObservabilityManager.error("Failed to save", mapOf("reason" to "disk_full"))

// Custom events
ObservabilityManager.logEvent("purchase_completed", mapOf(
    "product_id" to "sku_123",
    "amount" to 29.99
))

Breadcrumbs

ObservabilityManager.addBreadcrumb(
    message = "User tapped checkout",
    category = "ui",
    type = BreadcrumbType.USER_ACTION,
    attributes = mapOf("screen" to "cart")
)

User Identity

// Set user
ObservabilityManager.setUser(
    id = "user_123",
    email = "user@example.com",
    name = "John Doe",
    attributes = mapOf("plan" to "premium")
)

// Clear on logout
ObservabilityManager.clearUser()

Performance Tracing

// Manual span management
val span = ObservabilityManager.startSpan("loadUserData")
try {
    span.setAttribute("user_id", userId)
    // ... do work ...
    span.addEvent("data_fetched", mapOf("rows" to 100))
    span.end()
} catch (e: Exception) {
    span.endWithError(e)
    throw e
}

// Or use the convenience wrapper
val result = ObservabilityManager.withSpan("fetchProducts") { span ->
    span.addEvent("started")
    api.getProducts()  // automatically ends span on success/error
}

Error Recording

// Record non-fatal exceptions
try {
    riskyOperation()
} catch (e: Exception) {
    ObservabilityManager.recordException(
        throwable = e,
        message = "Failed during checkout",
        attributes = mapOf("cart_id" to cartId)
    )
}

// Record errors without exception
ObservabilityManager.recordError(
    message = "Invalid state detected",
    attributes = mapOf("expected" to "A", "actual" to "B")
)

Using the Logger Utility

The Logger object provides domain-specific convenience methods:

import com.sonrohan.observabilitytoolshipevaluator.util.Logger

// Navigation
Logger.logScreenView("ProductDetail", "ProductDetailActivity")
Logger.logTabChanged("Favorites", previousTab = "Home")

// User Actions
Logger.logButtonTap("checkout", screenName = "Cart")
Logger.logSearchExecuted("shoes", filters = mapOf("size" to "10"), resultCount = 42)

// API Tracking
Logger.logApiRequest("/api/users")
Logger.logApiResponse("/api/users", statusCode = 200, durationMs = 150, resultCount = 25)
Logger.logApiError("/api/users", error = "timeout", statusCode = 504)

// Performance
Logger.logSlowFrame(durationMs = 32, screenName = "Home")

Project Structure

app/src/main/java/com/sonrohan/observabilitytoolshipevaluator/
├── ObservabilityApp.kt          # Application class (SDK initialization)
├── MainActivity.kt              # Main UI
├── observability/
│   ├── ObservabilityProvider.kt # Interface for all adapters
│   ├── ObservabilityManager.kt  # Singleton dispatcher
│   ├── adapters/
│   │   ├── EmbraceAdapter.kt    # Embrace SDK integration
│   │   └── SentryAdapter.kt     # Sentry SDK integration
│   └── providers/
│       └── ConsoleProvider.kt   # Debug/Logcat provider
└── util/
    ├── Logger.kt                # Domain-specific logging utilities
    └── CrashTestService.kt      # Test crash/ANR triggers

Testing Crashes & Performance

The app includes CrashTestService for testing SDK crash reporting:

import com.sonrohan.observabilitytoolshipevaluator.util.CrashTestService

// Crash types
CrashTestService.triggerNullPointerCrash()
CrashTestService.triggerArrayIndexOutOfBounds()
CrashTestService.triggerDivideByZero()
CrashTestService.triggerStackOverflow()
CrashTestService.triggerMemoryPressure()

// Performance issues
CrashTestService.blockMainThread(5)  // ANR trigger
CrashTestService.heavyComputationOnMainThread()
CrashTestService.triggerMemoryLeak()

SDK Feature Comparison

Feature Sentry Embrace
Crash Reporting
Breadcrumbs
User Identity
Custom Events
Performance Tracing ✅ Transactions ✅ OpenTelemetry
Session Attributes ✅ Tags/Context ✅ Session Properties
Network Monitoring ✅ Auto (OkHttp) ✅ Auto (OkHttp)
ANR Detection
Session Replay ⚠️

Requirements

  • Android Studio Ladybug or newer
  • Kotlin 2.2+
  • Java 17+ (for build environment)
  • Min SDK 26, Target SDK 36
  • Gradle 8.x / AGP 8.x

License

This is a demo/evaluation project. Use freely for testing and comparison purposes.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages