Logging Elixir/Phoenix:如何定制HTTP请求日志格式?

Logging Elixir/Phoenix:如何定制HTTP请求日志格式?,logging,elixir,phoenix-framework,Logging,Elixir,Phoenix Framework,默认情况下,我的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 Par

默认情况下,我的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
这是一个很好的起点。但我想定制应用程序,将所有这些信息记录在一行中,这很有帮助,例如,在像这样的工具中筛选大量日志输出时。我特别希望每个请求以如下格式显示:

[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

[PUT/manage/projects/74/prompts/290]参数=%%{“project\u uuid”=>“74”,“prompt”=>%%{“html”=>“测试问题3”},“prompt\u uuid”=>“290”}用户=38(Topher Hunt)状态=302重定向到=/manage/projects/74持续时间=423ms

在我看来,我可以为Phoenix控制器日志配置日志级别,或者完全禁用它,但我看不到自定义格式的方法。如何做到这一点?

这不是自定义输出的问题,而是1)禁用与请求相关的默认日志语句(通过分离相关的
:遥测
处理程序),然后2)添加新的插件以记录我想要的格式

我是这样做的:

  • application.ex
    中的
    start/2
    功能中,默认情况下分离Phoenix为您连接的遥测处理程序。(调用
    :遥测。列出\u处理程序([])
    以查看所有连接的侦听器。)

    def start(_type,_args)do
    # ...
    #vvv添加这些vvv
    :ok=:telemetry.detach({Phoenix.Logger,[:Phoenix,:socket\u connected]})
    :ok=:telemetry.detach({Phoenix.Logger,[:Phoenix,:channel_joined]})
    :ok=:telemetry.detach({Phoenix.Logger,[:Phoenix,:router_dispatch,:start]})
    # ...
    主管。启动链接(儿童、选项)
    
  • lib/my\u app\u web/endpoint.ex
    中,注释掉
    Plug.Telemetry
    插件

  • lib/my\u app\u web/endpoint.ex
    中,在plug.Session之前添加此自定义插件:

    #单行请求日志记录。必须在会话和路由器插头之前到达。
    插入MyAppWeb.RequestLogger
    
  • 最后,添加
    lib/my\u app\u web/plugs/request\u logger.ex
    。(相应地调整详细信息;此实现假定登录的用户结构存储在
    conn.assigns.current_user
    )中:

    #一行完整请求日志记录源于Plug.Logger。
    #看https://github.com/elixir-plug/plug/blob/v1.8.0/lib/plug/logger.ex
    #更新此文件后需要重新启动服务器。
    defmodule MyAppWeb.RequestLogger do
    需要记录器
    @行为插头
    def初始化(选项),do:opts
    def呼叫(连接,选择)do
    开始时间=系统。单调时间()
    在发送前注册插头连接(连接,fn(连接)->
    #我们不希望记录密码等
    参数=检查(Phoenix.Logger.filter_值(conn.params))
    #记录任何重要的会话数据,例如登录用户
    user=conn.assigns[:当前用户]
    user_string=if user,do:“#{user.id}(#{user.name})”,否则:“(无)”
    #注:如有重定向
    重定向=Plug.Conn.get_resp_头(Conn,“位置”)
    redirect_string=如果redirect!=[],则执行:“redirected_to=#{redirect}”,否则为“
    #计算所用时间(一致性以毫秒为单位)
    停止时间=系统。单调时间()
    时间=系统。转换时间单位(停止时间-开始时间,:本机,:微秒)
    时间=div(时间=100)/10
    Logger.log(:info,
    "■ 方法=#{conn.method}path=#{conn.request_path}params=#{params}”
    “用户=#{user_string}状态=#{conn.status}#{redirect_string}持续时间=#{time_ms}ms”
    )
    康涅狄格州
    (完)
    结束
    结束
    
  • 重新启动服务器,现在每个请求只能看到一行日志,格式如下:

2019-06-0918:18:51.410[信息]■ [PUT/manage/projects/7qDjSk/prompts/3tUrF9]参数=%%{“project_uuid”=>“7qDjSk”,“prompt”=>%%{“html”=>“Test question 3”},“prompt_uuid”=>“3tUrF9”}用户=1(Topher Hunt)状态=302重定向到=/manage/projects/7qDjSk持续时间=21ms

(注意:另一个更好的实践方法是
:遥测。将
附加到phoenix已经发出的
[:phoenix,:router\u dispatch,:stop]
事件。这提供了我们需要的所有数据;有关更多详细信息,请参阅。)

有用的参考资料:


如果您想要JSON输出,还有一个: