телеметрический мониторинг Phoenix для исходящих вызовов API - PullRequest
0 голосов
/ 29 января 2020

У меня есть следующий клиент API в нашем приложении Phoenix.

defmodule SomeService do
  use HTTPoison.Base


  def process_request_url(url) do
    Application.get_env(:my_app, :some_service)[:host] <> url
  end

  def process_response_body(body) do
    if String.trim(body) != "" do
      body
      |> Poison.decode! # this could fail if the response is html
      |> Enum.map(fn({k, v}) -> {String.to_atom(k), v} end)
      |> Enum.into(%{})
    else
      body
    end
  end

  def get_some_data(customer_id, access_token) do
    path = "/customer/#{customer_id}/"
    headers = [{"Authorization", "Bearer #{access_token}"}]

    case get(path, headers) do
      {:ok, %HTTPoison.Response{body: body}} ->
        {:ok, body}
      {:error, error} -> {:error, error}
      _ -> {:error, "unknown error from upstream system"}
    end

  end

end

Каков наилучший способ контроля исходящих вызовов API?

  • т.е. путь запроса, ответ, time_taken et c

мы используем телеметрию для мониторинга входящих запросов и запросов ECTO. HTTPoison, тем не менее, похоже, не предоставляет телеметрические события из коробки, как мы можем использовать телеметрию для достижения этой цели?

1 Ответ

0 голосов
/ 30 января 2020

Сейчас я поднимаю событие телеметрии с данными ответа, как показано ниже:

defmodule SomeService do
  use HTTPoison.Base


  def process_request_url(url) do
    Application.get_env(:my_app, :some_service)[:host] <> url
  end

  def process_response_body(body) do
    if String.trim(body) != "" do
      body
      |> Poison.decode! # this could fail if the response is html
      |> Enum.map(fn({k, v}) -> {String.to_atom(k), v} end)
      |> Enum.into(%{})
    else
      body
    end
  end

  def get_some_data(customer_id, access_token) do
    path = "/customer/#{customer_id}/"
    headers = [{"Authorization", "Bearer #{access_token}"}]

    case get(path, headers) do
      {:ok, %HTTPoison.Response{body: body}} ->


        :telemetry.execute(
          [:my_app, :upstream_endpoint],
          %{request_path: response.request_url, 
            status_code: response.status_code, 
            response_headers: response.headers
           },
          response
        )


        {:ok, body}
      {:error, error} -> {:error, error}
      _ -> {:error, "unknown error from upstream system"}
    end

  end

end

Объект ответа содержит всю необходимую информацию (URL, статус, длительность и т. Д. c) для мониторинга и это вошло в обработчик.

    def handle_event([:my_app, :upstream_endpoint], measurements, metadata, config) do

        summary_event = []
        |> Keyword.put(:route_url, measurements.request_path)
        |> Keyword.put(:status_code, measurements.status_code)
        |> Keyword.put(:response_headers, Enum.into(measurements.response_headers, %{}))

        Logger.info("upstream-call", summary_event)
    end

Событие [: my_app,: upstream_endpoint] присоединяется к обработчику при запуске приложения.

:telemetry.attach("may-app", [:my_app, :upstream_endpoint], &handle_event/4, %{})

Хотя сейчас это работает хорошо, при каждом вызове API событие должно быть вызвано обязательно, а не очень расширяемо.

...