appsignal

Boost HTTP Client Monitoring in Elixir with AppSignal and Tesla Templates

Connor James
Noemi Lapresta

Connor James and Noemi Lapresta on

Boost HTTP Client Monitoring in Elixir with AppSignal and Tesla Templates

When relying on data from external services, it's important for the retrieval to be accurate and timely. While we may not control how efficiently an external API responds to our requests, we can control how and when we request data from that API. However, over time as your application and the API that serves it change, once efficient requests may turn into bottlenecks.

In this article, we'll demonstrate how you can leverage AppSignal's new Tesla integration to monitor your Elixir application's HTTP client performance and use this data to positively influence its architecture.

Templating with Tesla

Note: To implement what is covered in the post, you will need AppSignal for Elixir 2.7.3 or higher and Tesla 1.4.3 or higher.

Let's imagine you manage an application that ships stroopwafels around the world. To do this, your application connects with a dedicated Stroopwafels courier, Strooperoo, using its API to create, update, and track deliveries, with requests structured as follows:

Shell
# Create a new delivery POST https://strooperoo.com/deliveries/create/ # Update an existing delivery POST https://strooperoo.com/deliveries/:delivery_id/update # Retrieve the status of a delivery GET https://strooperoo.com/deliveries/:delivery_id/status

Let's say you've noticed some issues in your application's performance, especially when retrieving a delivery status. Luckily, you're using AppSignal, so you can investigate this further by checking the application's slow API requests.

Typically, AppSignal will group slow API requests by their base URL. In our case, all of the following requests would be grouped under the base URL https://strooperoo.com/:

Shell
https://strooperoo.com/deliveries/create/ https://strooperoo.com/deliveries/1971/update https://strooperoo.com/deliveries/1971/status

This is useful in deducing that the HTTP client is slow but doesn't help us immediately pinpoint which requests are problematic.

However, with Tesla, AppSignal can group your requests beyond their base URL. This is because Tesla allows you to use URL templates enabling AppSignal to understand how a request was built:

Elixir
defmodule StrooperooAPI do use Tesla plug(Tesla.Middleware.Telemetry) plug(Tesla.Middleware.PathParams) def delivery_status(id) do params = [delivery_id: id] get( "https://strooperoo.com/deliveries/:delivery_id/status", opts: [path_params: params] ) end end

So, in the above example, we know you're making a request to the status endpoint, and can apply the appropriate grouping.

Which means that in AppSignal, instead of seeing slow API requests grouped like this:

Slow API requests sorted by impact

You'll see requests grouped accurately like this:

Slow API requests sorted by impact, showing URL template

Tesla makes your HTTP client monitoring data way more valuable as you can now quickly deduce how your application's HTTP client is performing on a request level.

Wait a Minute, Why Canโ€™t You Do This with Other HTTP Clients!?

Good question. That's because Tesla's templating lets us understand how your request is built. With other HTTP clients, we get a URL string such as:

Shell
https://api.wow.com/api/versions/4/users/14383/comments/page/1

It's very tricky to understand, just from a string, what this request is doing and which elements of the request are parameters. Tesla's templating removes that guesswork for us and allows us to accurately group requests by telling us exactly what parameters are in the request URL. Neat, right?

Solving Slow Requests

Looking at our slow API requests, we can now see that requests to /status perform poorly. So let's investigate the application's delivery_status logic.

Elixir
def delivery_status do deliveries = Repo.all(Delivery) Enum.each(deliveries, fn delivery -> StrooperooAPI.delivery_status(delivery.id) end) conn |> put_flash(:info, "Delivery status updated") |> redirect(to: "/deliveries") end

Here, we are making many requests synchronously. When we first created the application, we were only managing a small number of deliveries, so we didn't experience any issues. But now, we're managing thousands of deliveries. This means that thousands of synchronous requests are being made every single time someone presses the "sync" button in the application.

One way we can better handle this is by running the code asynchronously in a scheduled background job using Oban:

Elixir
defmodule DeliveryStatusJob do use Oban.Job @impl true def perform(_job, _) do deliveries = Repo.all(Delivery) Enum.each(deliveries, fn delivery -> StrooperooAPI.delivery_status(delivery.id) end) end end

AppSignal supports Oban monitoring, so we'll be able to monitor the performance of our Oban job too!

More than Just Monitoring

This is just one of many examples of how monitoring your application with AppSignal can help you make data-driven decisions, in this case, thanks to Tesla's unique templating functionality. You can learn more about utilizing your Tesla HTTP client with AppSignal in our Tesla documentation.

AppSignal's slow API request monitoring is just one of our many developer-driven features that help you get the most out of monitoring your application. Developers also enjoy using our monitoring because we have:

  • An intuitive interface that is easy to navigate.
  • Simple and predictable pricing.
  • Developer-to-developer support.

If you experience any issues when using AppSignal for Elixir or Tesla, our support team is on hand to help! And remember, if you're new to AppSignal, we'll welcome you onboard with an exceptionally delicious shipment of stroopwafels ๐Ÿช ๐Ÿ˜‹

Connor James

Connor James

Official technical writer at AppSignal. Podcast addict who loves cannoli so much that he's considering changing his name to Connoli. He thinks there's a `u` in color. You might find him on the mic, on the stage, or lying on the sofa when he's off Documentation Duty.

All articles by Connor James
Noemi Lapresta

Noemi Lapresta

Noemi is a software developer at AppSignal, currently living in Barcelona. At this very moment, she's either fixing a bug, or writing a new one.

All articles by Noemi Lapresta

Become our next author!

Find out more

AppSignal monitors your apps

AppSignal provides insights for Ruby, Rails, Elixir, Phoenix, Node.js, Express and many other frameworks and libraries. We are located in beautiful Amsterdam. We love stroopwafels. If you do too, let us know. We might send you some!

Discover AppSignal
AppSignal monitors your apps