diff --git a/neurow/lib/neurow/ecs_log_formatter.ex b/neurow/lib/neurow/ecs_log_formatter.ex index 0650116..f505de7 100644 --- a/neurow/lib/neurow/ecs_log_formatter.ex +++ b/neurow/lib/neurow/ecs_log_formatter.ex @@ -39,6 +39,8 @@ defmodule Neurow.EcsLogFormatter do |> with_optional_attribute(metadata[:error_code], "error.code") |> with_optional_attribute(metadata[:client_ip], "client.ip") |> with_optional_attribute(metadata[:authorization_header], "http.request.authorization") + |> with_optional_attribute(metadata[:http_method], "http.request.method") + |> with_optional_attribute(metadata[:http_path], "http.request.path") |> with_optional_attribute(metadata[:user_agent_header], "user_agent.original") |> :jiffy.encode() |> newline() diff --git a/neurow/lib/neurow/jwt_auth_plug.ex b/neurow/lib/neurow/jwt_auth_plug.ex index 96b1d78..527473b 100644 --- a/neurow/lib/neurow/jwt_auth_plug.ex +++ b/neurow/lib/neurow/jwt_auth_plug.ex @@ -221,11 +221,13 @@ defmodule Neurow.JwtAuthPlug do defp unauthorized(conn, error_code, error_message, options) do Logger.error( - "JWT authentication error: #{error_code} - #{error_message}, path: '#{conn.request_path}'", + "JWT authentication error: #{error_code} - #{error_message}, method: '#{conn.method}', path: '#{conn.request_path}'", category: "security", error_code: "jwt_authentication.#{error_code}", authorization_header: conn |> get_req_header("authorization") |> List.first(), user_agent_header: conn |> get_req_header("user-agent") |> List.first(), + http_path: conn.request_path, + http_method: conn.method, trace_id: conn |> get_req_header("x-request-id") |> List.first(), client_ip: conn |> get_req_header("x-forwarded-for") |> List.first() ) @@ -241,10 +243,13 @@ defmodule Neurow.JwtAuthPlug do end Logger.error( - "JWT authentication error: #{error_code} - #{error_message}, path: '#{conn.request_path}', audience: '#{options |> Options.audience()}', token: '#{jwt_token}'", + "JWT authentication error: #{error_code} - #{error_message}, method: '#{conn.method}', path: '#{conn.request_path}', audience: '#{options |> Options.audience()}', token: '#{jwt_token}'", category: "security", error_code: "jwt_authentication.#{error_code}", + authorization_header: conn |> get_req_header("authorization") |> List.first(), user_agent_header: conn |> get_req_header("user-agent") |> List.first(), + http_method: conn.method, + http_path: conn.request_path, trace_id: conn |> get_req_header("x-request-id") |> List.first(), client_ip: conn |> get_req_header("x-forwarded-for") |> List.first() ) diff --git a/neurow/test/neurow/ecs_log_formatter_test.exs b/neurow/test/neurow/ecs_log_formatter_test.exs index 9d13e69..709fefb 100644 --- a/neurow/test/neurow/ecs_log_formatter_test.exs +++ b/neurow/test/neurow/ecs_log_formatter_test.exs @@ -169,6 +169,74 @@ defmodule Neurow.EcsLogFormatterTest do } end + test "supports optional http_method metadata" do + metadata = %{ + time: 1_728_556_213_722_376, + mfa: {Neurow.EcsLogFormatterTest, :fake_function, 4}, + file: "test/neurow/ecs_log_formatter_test.exs", + line: 10, + http_method: "POST" + } + + json_log = + Neurow.EcsLogFormatter.format(:info, "Hello, world!", nil, metadata) + |> :jiffy.decode([:return_maps]) + + assert json_log == %{ + "@timestamp" => "2024-10-10T10:30:13.722376Z", + "log.level" => "info", + "log.name" => "Elixir.Neurow.EcsLogFormatterTest.fake_function/4", + "log.source" => %{ + "file" => %{ + "name" => "test/neurow/ecs_log_formatter_test.exs", + "line" => 10 + } + }, + "ecs.version" => "8.11.0", + "message" => "Hello, world!", + "category" => "app", + "service" => %{ + "name" => "neurow", + "version" => "unknown" + }, + "http.request.method" => "POST" + } + end + + test "supports optional http_path metadata" do + metadata = %{ + time: 1_728_556_213_722_376, + mfa: {Neurow.EcsLogFormatterTest, :fake_function, 4}, + file: "test/neurow/ecs_log_formatter_test.exs", + line: 10, + http_path: "/foobar" + } + + json_log = + Neurow.EcsLogFormatter.format(:info, "Hello, world!", nil, metadata) + |> :jiffy.decode([:return_maps]) + + assert json_log == %{ + "@timestamp" => "2024-10-10T10:30:13.722376Z", + "log.level" => "info", + "log.name" => "Elixir.Neurow.EcsLogFormatterTest.fake_function/4", + "log.source" => %{ + "file" => %{ + "name" => "test/neurow/ecs_log_formatter_test.exs", + "line" => 10 + } + }, + "ecs.version" => "8.11.0", + "message" => "Hello, world!", + "category" => "app", + "service" => %{ + "name" => "neurow", + "version" => "unknown" + }, + "http.request.path" => "/foobar" + } + end + test "multiline messages are inlined" do metadata = %{ time: 1_728_556_213_722_376,