簡體   English   中英

Elixir / Phoenix:如何自定義 HTTP 請求日志格式?

[英]Elixir / Phoenix: How to customize HTTP request log format?

默認情況下,我的 Phoenix 應用程序會在大約 5 行日志輸出中記錄有關每個 HTTP 請求的基本信息。 只要我將日志級別設置為:debug ,我就可以看到每個請求的方法、路徑、控制器和操作、參數、響應代碼和持續時間:

2019-06-14 16:05:35.099 [info] GET /manage/projects/7qDjSk
2019-06-14 16:05:35.103 [debug] Processing with RTLWeb.Manage.ProjectController.show/2
  Parameters: %{"project_uuid" => "7qDjSk"}
  Pipelines: [:browser, :require_login]
2019-06-14 16:05:35.116 [info] Sent 200 in 17ms

這是一個很好的起點。 但我想自定義應用程序以在一行上記錄所有這些信息,這很有幫助,例如。 Papertrail 等工具中篩選大量日志輸出時。 特別是我希望每個請求都以這樣的格式顯示:

[PUT /manage/projects/74/prompts/290] params=%{"project_uuid" => "74", "prompt" => %{"html" => "<div>Test question 3</div>"}, "prompt_uuid" => "290"} user=38 (Topher Hunt) status=302 redirected_to=/manage/projects/74 duration=423ms

Phoenix.Controller 文檔中,我看到我可以為 Phoenix 控制器日志配置日志級別,或者完全禁用它,但我沒有看到自定義格式的方法。 我怎樣才能做到這一點?

這不是自定義輸出的問題,而是 1) 禁用與請求相關的默認日志語句(通過分離相關的:telemetry處理程序)然后 2) 添加一個新插件來記錄我想要的格式。

這是我如何做到的:

  • application.exstart/2函數中,分離 Phoenix 默認為您附加的遙測處理程序。 (調用:telemetry.list_handlers([])以查看所有附加的偵聽器。)

     def start(_type, _args) do # ... # vvv ADD THESE vvv :ok = :telemetry.detach({Phoenix.Logger, [:phoenix, :socket_connected]}) :ok = :telemetry.detach({Phoenix.Logger, [:phoenix, :channel_joined]}) :ok = :telemetry.detach({Phoenix.Logger, [:phoenix, :router_dispatch, :start]}) # ... Supervisor.start_link(children, opts)
  • lib/my_app_web/endpoint.ex ,注釋掉Plug.Telemetry插件。

  • lib/my_app_web/endpoint.ex ,在 Plug.Session 之前添加這個自定義插件:

     # One-line request logging. Must come before the session & router plugs. plug MyAppWeb.RequestLogger
  • 最后,添加lib/my_app_web/plugs/request_logger.ex (相應地調整細節;此實現假設登錄用戶結構存儲在conn.assigns.current_user ):

     # One-line full request logging inspired by Plug.Logger. # See https://github.com/elixir-plug/plug/blob/v1.8.0/lib/plug/logger.ex # Need to restart the server after updating this file. defmodule MyAppWeb.RequestLogger do require Logger @behaviour Plug def init(opts), do: opts def call(conn, _opts) do start_time = System.monotonic_time() Plug.Conn.register_before_send(conn, fn(conn) -> # We don't want passwords etc. being logged params = inspect(Phoenix.Logger.filter_values(conn.params)) # Log any important session data eg. logged-in user user = conn.assigns[:current_user] user_string = if user, do: "#{user.id} (#{user.name})", else: "(none)" # Note redirect, if any redirect = Plug.Conn.get_resp_header(conn, "location") redirect_string = if redirect != [], do: " redirected_to=#{redirect}", else: "" # Calculate time taken (in ms for consistency) stop_time = System.monotonic_time() time_us = System.convert_time_unit(stop_time - start_time, :native, :microsecond) time_ms = div(time_us, 100) / 10 Logger.log(:info, "■ method=#{conn.method} path=#{conn.request_path} params=#{params} "<> "user=#{user_string} status=#{conn.status}#{redirect_string} duration=#{time_ms}ms" ) conn end) end end
  • 重新啟動您的服務器,您現在應該看到每個請求只有一個日志行,格式如下:

2019-06-09 18:18:51.410 [info] ■ [PUT /manage/projects/7qDjSk/prompts/3tUrF9] params=%{"project_uuid" => "7qDjSk", "prompt" => %{"html" => "<div>Test question 3</div>"}, "prompt_uuid" => "3tUrF9"} user=1 (Topher Hunt) status=302 redirected_to=/manage/projects/7qDjSk duration=21ms

(注意:另一種更佳實踐的方法是:telemetry.attach到 Phoenix 已經發出的[:phoenix, :router_dispatch, :stop]事件。這提供了我們需要的所有數據;參見Phoenix。有關更多詳細信息,請參閱端點文檔。)

有用的參考:

還有這個,如果你想要 JSON 輸出: https : //github.com/Nebo15/logger_json/tree/master/lib/logger_json

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM