Elastic Mobile APM is a surprisingly effective way to get deep visibility into your mobile app’s performance and user experience, even down to individual user actions.

Let’s see it in action. Imagine you’re tracking a user’s journey through an e-commerce app. They tap a product, add it to their cart, and then proceed to checkout. With Elastic Mobile APM, you’d see this as a series of distinct "transactions" in your Kibana dashboard. Each transaction would have a name like "View Product," "Add to Cart," or "Checkout." For each transaction, you’d get metrics like:

  • Duration: How long did it take from the user’s tap to the screen fully rendering or the action completing?
  • HTTP Requests: What backend calls were made during this transaction, and how long did they take? This is crucial for identifying slow APIs.
  • Errors: Did any exceptions occur during this transaction?
  • Custom Metrics: You can define your own metrics, like the number of items in the cart or the value of the order.

Here’s a snippet of what that might look like in Kibana, showing a slow "Checkout" transaction:

{
  "transaction": {
    "name": "Checkout",
    "type": "view",
    "duration": {
      "us": 4523000
    },
    "timestamp": "2023-10-27T10:30:15.123Z",
    "id": "a1b2c3d4e5f67890",
    "span_count": 5,
    "trace_id": "c1d2e3f4a5b67890"
  },
  "http": [
    {
      "method": "POST",
      "url": "https://api.example.com/v1/orders",
      "status_code": 201,
      "response": {
        "headers": {
          "Content-Length": "150"
        },
        "bytes": 150
      },
      "request": {
        "bytes": 800
      },
      "domain": "api.example.com",
      "peer.service": "orders-api",
      "duration": {
        "us": 3100000
      }
    }
  ],
  "error": {
    "message": "Payment gateway timeout",
    "type": "PaymentError",
    "stacktrace": [...]
  }
}

This data allows you to pinpoint performance bottlenecks. In the example above, the "Checkout" transaction took 4.5 seconds, with a significant portion of that time (3.1 seconds) spent waiting for the POST /v1/orders API call to complete. It also shows a PaymentError occurred.

The core problem Elastic Mobile APM solves is the "black box" nature of mobile applications. Before, you might know your app is slow, or users are complaining about crashes, but you had no granular data to tell you why. Was it a slow network request? A poorly optimized UI rendering? A specific feature causing a crash? Elastic Mobile APM provides the instrumentation to answer these questions by automatically capturing a wealth of performance data.

The agent works by instrumenting your app’s code. For iOS, this typically involves adding the Elastic APM SDK to your project and configuring it. For Android, it’s similar, using the Android SDK. The agent hooks into key lifecycle events and network requests. When a user initiates an action, like tapping a button, the agent starts a new "transaction." As that transaction progresses, the agent records details about what’s happening: network calls made, UI rendering times, and any errors that occur. These details are packaged as "spans," which are then grouped under the parent transaction and sent to your Elastic APM Server.

The configuration is straightforward. You’ll need to:

  1. Add the SDK:
    • iOS (Swift):
      import ElasticAPM
      
      ElasticAPM.configure(withService: "my-ios-app", serviceVersion: "1.0.0", serverURL: "https://your-elastic-apm-server:8200")
      
    • Android (Kotlin):
      import co.elastic.apm.android.ElasticAPM
      
      ElasticAPM.initialize(application, ElasticAPMConfiguration.Builder()
          .withServiceName("my-android-app")
          .withServiceVersion("1.0.0")
          .withServerUrl("https://your-elastic-apm-server:8200")
          .build()
      )
      
  2. Set the serviceName and serviceVersion: These are crucial for identifying your application in Kibana. Use distinct names and versions for each app and build.
  3. Provide the serverURL: This is the endpoint where your Elastic APM Server is listening for data.

You have a lot of levers to pull. You can configure sampling rates to control how much data is sent (e.g., sample 10% of transactions to reduce overhead). You can define custom transaction names to group related user actions more logically, rather than relying solely on default screen names. You can also add custom attributes (key-value pairs) to transactions and spans to enrich the data with business-specific context, like user_id or order_type.

One aspect that often surprises people is how granularly you can capture user interactions without writing extensive custom code. For instance, if your app uses a common networking library like URLSession on iOS or OkHttp on Android, the Elastic APM agent will automatically instrument these requests and report them as spans within your transactions. This means you get visibility into your backend dependencies out-of-the-box for the vast majority of your network traffic, without needing to manually wrap every single HTTP call.

Once the data is flowing, you’ll typically use Kibana’s APM UI to explore your transactions, errors, and services. You can dive into specific slow transactions, see the breakdown of spans, and correlate them with errors and backend performance.

The next step after getting basic instrumentation working is to explore distributed tracing, where you can see requests flow from your mobile app through your backend services, all within a single trace.

Want structured learning?

Take the full Elastic-apm course →