O pacote AppSignal for Elixir instrumenta requisições HTTP realizadas pelo HTTPoison.
HTTPoison é um cliente HTTP popular para Elixir. Diferentemente do Finch e do Tesla, o HTTPoison não emite eventos de telemetria, então o AppSignal não pode instrumentá-lo automaticamente. Em vez disso, o AppSignal fornece módulos wrapper aos quais você opta por aderir: Appsignal.HTTPoison como um cliente drop-in, e Appsignal.HTTPoison.Base para módulos cliente customizados. As structs de response e error (%HTTPoison.Response{}, %HTTPoison.Error{}, …) são os tipos próprios do HTTPoison e são retornados sem alteração.
O AppSignal envolverá as requisições executadas via Appsignal.HTTPoison como eventos request.httpoison na timeline de eventos das suas amostras de desempenho, permitindo que você veja quanto tempo o HTTPoison gasta fazendo requisições a APIs externas. Esses dados podem ajudá-lo a decidir mover as requisições de API para um background job ou introduzir caching para ajudar a acelerar o desempenho e limitar requisições desnecessárias a APIs.
Configuração
A instrumentação do HTTPoison é opt-in. Escolha a abordagem que melhor se adapta à sua aplicação.
Usando Appsignal.HTTPoison diretamente
Chame Appsignal.HTTPoison em vez de HTTPoison para fazer requisições instrumentadas. Faça pattern-match em %HTTPoison.Response{...} e %HTTPoison.Error{...} normalmente — esses são os tipos de struct próprios do HTTPoison, retornados sem alteração:
Não use alias Appsignal.HTTPoison. Isso sombrearia o nome do módulo
HTTPoison, fazendo com que pattern matches em %HTTPoison.Response{} e
%HTTPoison.Error{} falhem.
defmodule MyAppWeb.PageController do
use MyAppWeb, :controller
def index(conn, _params) do
case Appsignal.HTTPoison.get("https://api.example.com/users") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
render(conn, :index, users: body)
{:ok, %HTTPoison.Response{status_code: status}} ->
conn |> put_status(status) |> text("Error")
{:error, %HTTPoison.Error{reason: reason}} ->
conn |> put_status(500) |> text("Error: #{reason}")
end
end
end
Módulos cliente customizados
Se você usa um módulo cliente HTTP customizado baseado em HTTPoison.Base, substitua use HTTPoison.Base por use Appsignal.HTTPoison.Base. Nenhuma alteração adicional é necessária — dentro do módulo, você pode chamar métodos como get/1 e post/3, e fazer match nas structs de response e error do HTTPoison normalmente:
defmodule MyApp.ApiClient do
# substitua `use HTTPoison.Base` por `use Appsignal.HTTPoison.Base`
use Appsignal.HTTPoison.Base
def process_url(url) do
"https://api.example.com" <> url
end
def users do
case get("/users") do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> {:ok, body}
{:ok, %HTTPoison.Response{status_code: status}} -> {:error, status}
{:error, %HTTPoison.Error{reason: reason}} -> {:error, reason}
end
end
end
Todas as requisições feitas através do seu cliente customizado serão então instrumentadas automaticamente. Se seu módulo sobrescreve request/5, certifique-se de chamar super para preservar a instrumentação:
defmodule MyApp.ApiClient do
use Appsignal.HTTPoison.Base
def request(method, url, body, headers, options) do
# ... lógica customizada aqui ...
super(method, url, body, headers, options)
end
end