【问题标题】:phoenix telemetry monitoring for upstream api callsphoenix 遥测监控上游 api 调用
【发布时间】:2020-01-29 18:17:27
【问题描述】:

我的 phoenix 应用程序中有以下 api 客户端。

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等

我们正在使用遥测技术来监控传入的请求和 ECTO 查询。虽然 HTTPoison 似乎没有提供开箱即用的遥测事件,但我们如何利用遥测来实现这一点?

【问题讨论】:

  • 看看这个,不久前发布的正是为了这个任务github.com/beam-telemetry/telemetry
  • 感谢@Daniel,在每次使用适当的处理程序调用 api 后都遵循同样的方法来引发事件,但如果我向客户端添加更多 api 调用,这是最干净的方法吗,我必须引发我自己的事件。这可以改善吗?在下面发布我的答案。

标签: elixir phoenix-framework telemetry


【解决方案1】:

现在我正在使用如下响应数据引发遥测事件:

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、状态、持续时间等),并将其记录在处理程序中。

    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 时都需要强制引发事件,而不是非常可扩展。

【讨论】:

    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 1970-01-01
    • 2010-10-17
    • 2023-03-10
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多