檢視原始碼 設定指標歷史記錄

如果你希望使用從遙測資料或其他資料來源儲存的歷史記錄來補充指標,請修改資訊控制台設定(在「my_app_web/router.ex」中)以包含 指標_歷史記錄 金鑰,如下

live_dashboard "/dashboard",
  metrics: MyAppWeb.Telemetry,
  metrics_history: {MyApp.MetricsStorage, :metrics_history, []}

其中 指標儲存 是模組,:指標_歷史記錄 是採納單一引數的函數,此範例中為指標。

函數必須傳回一個清單(無資料時為空),或一個由許多具有各個映射中 :標籤:測量:時間 金鑰的映射組成的清單。函數 Phoenix.LiveDashboard.extract_datapoint_for_metric/4 將使用此格式(有選用時間引數,假設要覆寫 System.system_time(:microsecond) 的預設值)傳回映射,或傳回 nil,此時不應儲存資料點。

資料儲存在 ETS 表格、Redis 或資料庫,或任何其他地方,不過此範例中將使用 GenServer,並搭配 環狀緩衝區,在每個客戶端連線時發出最近的遙測資料。

在你的 mix.exs 中,在 deps 中新增下列內容

  {:circular_buffer, "~> 0.4.0"},

接著,新增下列模組「lib/my_app_web/metrics_storage.ex」

  defmodule MyAppWeb.MetricsStorage do
    use GenServer

    @history_buffer_size 50

    def metrics_history(metric) do
      GenServer.call(__MODULE__, {:data, metric})
    end

    def start_link(args) do
      GenServer.start_link(__MODULE__, args, name: __MODULE__)
    end

    @impl true
    def init(metrics) do
      Process.flag(:trap_exit, true)

      metric_histories_map =
        metrics
        |> Enum.map(fn metric ->
          attach_handler(metric)
          {metric, CircularBuffer.new(@history_buffer_size)}
        end)
        |> Map.new()

      {:ok, metric_histories_map}
    end

    @impl true
    def terminate(_, metrics) do
      for metric <- metrics do
        :telemetry.detach({__MODULE__, metric, self()})
      end

      :ok
    end

    defp attach_handler(%{event_name: name_list} = metric) do
      :telemetry.attach(
        {__MODULE__, metric, self()},
        name_list,
        &__MODULE__.handle_event/4,
        metric
      )
    end

    def handle_event(_event_name, data, metadata, metric) do
      if data = Phoenix.LiveDashboard.extract_datapoint_for_metric(metric, data, metadata) do
        GenServer.cast(__MODULE__, {:telemetry_metric, data, metric})
      end
    end

    @impl true
    def handle_cast({:telemetry_metric, data, metric}, state) do
      {:noreply, update_in(state[metric], &CircularBuffer.insert(&1, data))}
    end

    @impl true
    def handle_call({:data, metric}, _from, state) do
      if history = state[metric] do
        {:reply, CircularBuffer.to_list(history), state}
      else
        {:reply, [], state}
      end
    end
  end

最後,在應用程式 child 中新增新的模組,並使用一些或所有指標初始化,例如使用 MyAppWeb.Telemetry.metrics/0

  # Start genserver to store transient metrics
  {MyAppWeb.MetricsStorage, MyAppWeb.Telemetry.metrics()},

現在,當你選取指標資訊控制台的一個標籤時,LiveDashboard 將呼叫你的模組,取得該標籤的指標歷史記錄。