From 7368ac97f4f202b8a29e10e529ebc35a4be589c9 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Fri, 7 Nov 2025 22:14:03 +0000 Subject: [PATCH 1/7] Add `exception_log_filter` option to server --- lib/grpc/server/adapters/cowboy/handler.ex | 49 +++++++-- lib/grpc/server/supervisor.ex | 12 ++- test/grpc/integration/server_test.exs | 114 +++++++++++++++++++++ 3 files changed, 162 insertions(+), 13 deletions(-) diff --git a/lib/grpc/server/adapters/cowboy/handler.ex b/lib/grpc/server/adapters/cowboy/handler.ex index 7d2ba6cd..1228d719 100644 --- a/lib/grpc/server/adapters/cowboy/handler.ex +++ b/lib/grpc/server/adapters/cowboy/handler.ex @@ -29,7 +29,8 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do pid: server_rpc_pid :: pid, handling_timer: timeout_timer_ref :: reference, pending_reader: nil | pending_reader, - access_mode: GRPC.Server.Stream.access_mode() + access_mode: GRPC.Server.Stream.access_mode(), + exception_log_filter: exception_log_filter() } @type init_result :: {:cowboy_loop, :cowboy_req.req(), stream_state} | {:ok, :cowboy_req.req(), init_state} @@ -40,6 +41,8 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do @type headers :: %{binary() => binary()} + @type exception_log_filter :: {module(), atom()} | (Exception.t() -> boolean()) + @doc """ This function is meant to be called whenever a new request arrives to an existing connection. This handler works mainly with two linked processes. @@ -52,6 +55,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do @spec init(:cowboy_req.req(), state :: init_state) :: init_result def init(req, {endpoint, {_name, server}, route, opts} = state) do http_method = extract_http_method(req) |> String.to_existing_atom() + exception_log_filter = extract_exception_log_filter_opt(opts) with {:ok, access_mode, sub_type, content_type} <- find_content_type_subtype(req), {:ok, codec} <- find_codec(sub_type, content_type, server), @@ -98,7 +102,8 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do pid: server_rpc_pid, handling_timer: timer_ref, pending_reader: nil, - access_mode: access_mode + access_mode: access_mode, + exception_log_filter: exception_log_filter } } else @@ -110,6 +115,20 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do end end + defp extract_exception_log_filter_opt(%{exception_log_filter: func}) + when is_function(func, 1) do + func + end + + defp extract_exception_log_filter_opt(%{exception_log_filter: {module, func_name}}) + when is_atom(module) and is_atom(func_name) do + fn exception -> apply(module, func_name, [exception]) end + end + + defp extract_exception_log_filter_opt(%{}) do + fn _exception -> true end + end + defp find_codec(subtype, content_type, server) do if codec = Enum.find(server.__meta__(:codecs), nil, fn c -> c.name() == subtype end) do {:ok, codec} @@ -466,7 +485,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do [req: req] |> ReportException.new(error) - |> log_error() + |> maybe_log_error(state.exception_log_filter) {:stop, req, state} end @@ -493,7 +512,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do [req: req] |> ReportException.new(error, stacktrace) - |> log_error(stacktrace) + |> maybe_log_error(state.exception_log_filter, stacktrace) {:stop, req, state} end @@ -506,7 +525,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do [req: req] |> ReportException.new(reason, stack, kind) - |> log_error(stack) + |> maybe_log_error(state.exception_log_filter, stack) {:stop, req, state} end @@ -517,7 +536,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do [req: req] |> ReportException.new(reason, stacktrace) - |> log_error(stacktrace) + |> maybe_log_error(state.exception_log_filter, stacktrace) {:stop, req, state} end @@ -705,11 +724,19 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do {:wait, ref} end - defp log_error(%ReportException{kind: kind} = exception, stacktrace \\ []) do - crash_reason = GRPC.Logger.crash_reason(kind, exception, stacktrace) + defp maybe_log_error( + %ReportException{kind: kind, reason: reason} = exception, + filter_fn, + stacktrace \\ [] + ) do + if filter_fn.(reason) do + crash_reason = GRPC.Logger.crash_reason(kind, exception, stacktrace) - kind - |> Exception.format(exception, stacktrace) - |> Logger.error(crash_reason: crash_reason) + kind + |> Exception.format(exception, stacktrace) + |> Logger.error(crash_reason: crash_reason) + else + :ok + end end end diff --git a/lib/grpc/server/supervisor.ex b/lib/grpc/server/supervisor.ex index ea486a1f..e914f5fc 100644 --- a/lib/grpc/server/supervisor.ex +++ b/lib/grpc/server/supervisor.ex @@ -41,6 +41,7 @@ defmodule GRPC.Server.Supervisor do * `:endpoint` - defines the endpoint module that will be started. * `:port` - the HTTP port for the endpoint. * `:servers` - the list of servers that will be be started. + * `:exception_log_filter` - a 1-arity function that returns a boolean, whether or not a given exception should be logged or dropped * `:adapter_opts` - options for the adapter. Either `:endpoint` or `:servers` must be present, but not both. @@ -62,13 +63,20 @@ defmodule GRPC.Server.Supervisor do end opts = - case Keyword.validate(opts, [:endpoint, :servers, :start_server, :port, :adapter_opts]) do + case Keyword.validate(opts, [ + :endpoint, + :servers, + :start_server, + :port, + :adapter_opts, + :exception_log_filter + ]) do {:ok, _opts} -> opts {:error, _} -> raise ArgumentError, - "just [:endpoint, :servers, :start_server, :port, :adapter_opts] are accepted as arguments, and any other keys for adapters should be passed as adapter_opts!" + "just [:endpoint, :servers, :start_server, :port, :adapter_opts, :exception_log_filter] are accepted as arguments, and any other keys for adapters should be passed as adapter_opts!" end case validate_cred(opts) do diff --git a/test/grpc/integration/server_test.exs b/test/grpc/integration/server_test.exs index 36ba357f..86ea2dd7 100644 --- a/test/grpc/integration/server_test.exs +++ b/test/grpc/integration/server_test.exs @@ -277,6 +277,120 @@ defmodule GRPC.Integration.ServerTest do assert logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" end + test "logs error if exception_log_filter returns true" do + logs = + ExUnit.CaptureLog.capture_log(fn -> + run_server( + [HelloErrorServer], + fn port -> + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + req = %Helloworld.HelloRequest{name: "unknown error"} + Helloworld.Greeter.Stub.say_hello(channel, req) + end, + 0, + exception_log_filter: fn _exception -> true end + ) + end) + + assert logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" + end + + test "logs error if exception_log_filter returns true, using MF form" do + defmodule TestTrueFilter do + def filter(_exception) do + true + end + end + + logs = + ExUnit.CaptureLog.capture_log(fn -> + run_server( + [HelloErrorServer], + fn port -> + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + req = %Helloworld.HelloRequest{name: "unknown error"} + Helloworld.Greeter.Stub.say_hello(channel, req) + end, + 0, + exception_log_filter: {TestTrueFilter, :filter} + ) + end) + + assert logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" + end + + test "does not log error if exception_log_filter returns false" do + logs = + ExUnit.CaptureLog.capture_log(fn -> + run_server( + [HelloErrorServer], + fn port -> + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + req = %Helloworld.HelloRequest{name: "unknown error"} + Helloworld.Greeter.Stub.say_hello(channel, req) + end, + 0, + exception_log_filter: fn _exception -> false end + ) + end) + + refute logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" + end + + test "does not log error if exception_log_filter returns false, using MF form" do + defmodule TestFalseFilter do + def filter(_exception) do + false + end + end + + logs = + ExUnit.CaptureLog.capture_log(fn -> + run_server( + [HelloErrorServer], + fn port -> + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + req = %Helloworld.HelloRequest{name: "unknown error"} + Helloworld.Greeter.Stub.say_hello(channel, req) + end, + 0, + exception_log_filter: {TestFalseFilter, :filter} + ) + end) + + refute logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" + end + + test "passes RPCErrors to `exception_log_filter" do + run_server( + [HelloErrorServer], + fn port -> + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + req = %Helloworld.HelloRequest{name: "unknown error"} + Helloworld.Greeter.Stub.say_hello(channel, req) + end, + 0, + exception_log_filter: fn exception -> + assert %GRPC.RPCError{} = exception + end + ) + end + + test "passes thrown exceptions to `exception_log_filter" do + run_server( + [HelloErrorServer], + fn port -> + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + req = %Helloworld.HelloRequest{name: "raise", duration: 0} + Helloworld.Greeter.Stub.say_hello(channel, req) + end, + 0, + exception_log_filter: fn exception -> + assert %ArgumentError{message: "exception raised"} = exception + end + ) + end + test "returns appropriate error for stream requests" do run_server([FeatureErrorServer], fn port -> {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") From ee2b01b3b00f49ebd06cbfc3abb0bcbc3ba76971 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Fri, 7 Nov 2025 23:05:23 +0000 Subject: [PATCH 2/7] Only allow MF form --- lib/grpc/server/adapters/cowboy/handler.ex | 7 +- lib/grpc/server/supervisor.ex | 2 +- test/grpc/integration/server_test.exs | 78 +++++++--------------- 3 files changed, 26 insertions(+), 61 deletions(-) diff --git a/lib/grpc/server/adapters/cowboy/handler.ex b/lib/grpc/server/adapters/cowboy/handler.ex index 1228d719..d9c3eb95 100644 --- a/lib/grpc/server/adapters/cowboy/handler.ex +++ b/lib/grpc/server/adapters/cowboy/handler.ex @@ -41,7 +41,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do @type headers :: %{binary() => binary()} - @type exception_log_filter :: {module(), atom()} | (Exception.t() -> boolean()) + @type exception_log_filter :: {module(), atom()} @doc """ This function is meant to be called whenever a new request arrives to an existing connection. @@ -115,11 +115,6 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do end end - defp extract_exception_log_filter_opt(%{exception_log_filter: func}) - when is_function(func, 1) do - func - end - defp extract_exception_log_filter_opt(%{exception_log_filter: {module, func_name}}) when is_atom(module) and is_atom(func_name) do fn exception -> apply(module, func_name, [exception]) end diff --git a/lib/grpc/server/supervisor.ex b/lib/grpc/server/supervisor.ex index e914f5fc..83b464b8 100644 --- a/lib/grpc/server/supervisor.ex +++ b/lib/grpc/server/supervisor.ex @@ -41,7 +41,7 @@ defmodule GRPC.Server.Supervisor do * `:endpoint` - defines the endpoint module that will be started. * `:port` - the HTTP port for the endpoint. * `:servers` - the list of servers that will be be started. - * `:exception_log_filter` - a 1-arity function that returns a boolean, whether or not a given exception should be logged or dropped + * `:exception_log_filter` - a {Module, function} tuple that refers to a filter function. This must be a 1-arity function that returns a boolean, indicating whether or not a given exception should be logged or dropped. * `:adapter_opts` - options for the adapter. Either `:endpoint` or `:servers` must be present, but not both. diff --git a/test/grpc/integration/server_test.exs b/test/grpc/integration/server_test.exs index 86ea2dd7..ebc5efe8 100644 --- a/test/grpc/integration/server_test.exs +++ b/test/grpc/integration/server_test.exs @@ -208,6 +208,16 @@ defmodule GRPC.Integration.ServerTest do end end + defmodule ExceptionLogFilter do + def always_allow(_exception) do + true + end + + def never_allow(_exception) do + false + end + end + test "multiple servers works" do run_server([FeatureServer, HelloServer], fn port -> {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") @@ -288,31 +298,7 @@ defmodule GRPC.Integration.ServerTest do Helloworld.Greeter.Stub.say_hello(channel, req) end, 0, - exception_log_filter: fn _exception -> true end - ) - end) - - assert logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" - end - - test "logs error if exception_log_filter returns true, using MF form" do - defmodule TestTrueFilter do - def filter(_exception) do - true - end - end - - logs = - ExUnit.CaptureLog.capture_log(fn -> - run_server( - [HelloErrorServer], - fn port -> - {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") - req = %Helloworld.HelloRequest{name: "unknown error"} - Helloworld.Greeter.Stub.say_hello(channel, req) - end, - 0, - exception_log_filter: {TestTrueFilter, :filter} + exception_log_filter: {ExceptionLogFilter, :always_allow} ) end) @@ -330,38 +316,20 @@ defmodule GRPC.Integration.ServerTest do Helloworld.Greeter.Stub.say_hello(channel, req) end, 0, - exception_log_filter: fn _exception -> false end + exception_log_filter: {TestFalseFilter, :never_allow} ) end) refute logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" end - test "does not log error if exception_log_filter returns false, using MF form" do - defmodule TestFalseFilter do - def filter(_exception) do - false + test "passes RPCErrors to `exception_log_filter" do + defmodule ExceptionFilterMustBeRPCError do + def filter(%GRPC.RPCError{}) do + true end end - logs = - ExUnit.CaptureLog.capture_log(fn -> - run_server( - [HelloErrorServer], - fn port -> - {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") - req = %Helloworld.HelloRequest{name: "unknown error"} - Helloworld.Greeter.Stub.say_hello(channel, req) - end, - 0, - exception_log_filter: {TestFalseFilter, :filter} - ) - end) - - refute logs =~ "Exception raised while handling /helloworld.Greeter/SayHello" - end - - test "passes RPCErrors to `exception_log_filter" do run_server( [HelloErrorServer], fn port -> @@ -370,13 +338,17 @@ defmodule GRPC.Integration.ServerTest do Helloworld.Greeter.Stub.say_hello(channel, req) end, 0, - exception_log_filter: fn exception -> - assert %GRPC.RPCError{} = exception - end + exception_log_filter: {ExceptionFilterMustBeRPCError, :filter} ) end test "passes thrown exceptions to `exception_log_filter" do + defmodule ExceptionFilterMustBeRaisedError do + def filter(%ArgumentError{message: "exception raised"}) do + true + end + end + run_server( [HelloErrorServer], fn port -> @@ -385,9 +357,7 @@ defmodule GRPC.Integration.ServerTest do Helloworld.Greeter.Stub.say_hello(channel, req) end, 0, - exception_log_filter: fn exception -> - assert %ArgumentError{message: "exception raised"} = exception - end + exception_log_filter: {ExceptionFilterMustBeRaisedError, :filter} ) end From ef8b30d43aff60bb08a7778202d41c39f59a44b0 Mon Sep 17 00:00:00 2001 From: Paulo Valente <16843419+polvalente@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:20:31 -0300 Subject: [PATCH 3/7] refactor: more flexible filtering --- lib/grpc/server/adapters/cowboy/handler.ex | 49 +++++++++++++++------- lib/grpc/server/supervisor.ex | 4 +- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/grpc/server/adapters/cowboy/handler.ex b/lib/grpc/server/adapters/cowboy/handler.ex index d9c3eb95..3167c158 100644 --- a/lib/grpc/server/adapters/cowboy/handler.ex +++ b/lib/grpc/server/adapters/cowboy/handler.ex @@ -41,7 +41,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do @type headers :: %{binary() => binary()} - @type exception_log_filter :: {module(), atom()} + @type exception_log_filter :: {module(), atom()} | nil @doc """ This function is meant to be called whenever a new request arrives to an existing connection. @@ -115,13 +115,18 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do end end - defp extract_exception_log_filter_opt(%{exception_log_filter: {module, func_name}}) - when is_atom(module) and is_atom(func_name) do - fn exception -> apply(module, func_name, [exception]) end - end + defp extract_exception_log_filter_opt(opts) do + case opts[:exception_log_filter] do + + {module, func_name} when is_atom(module) and is_atom(func_name) -> + {module, func_name} + + nil -> + nil - defp extract_exception_log_filter_opt(%{}) do - fn _exception -> true end + invalid -> + raise ArgumentError, "invalid exception log filter: #{inspect(invalid)}" + end end defp find_codec(subtype, content_type, server) do @@ -719,19 +724,31 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do {:wait, ref} end + defp maybe_log_error(exception, filter, stacktrace \\ []) + defp maybe_log_error( - %ReportException{kind: kind, reason: reason} = exception, - filter_fn, - stacktrace \\ [] + %ReportException{} = exception, + {module, func_name}, + stacktrace ) do - if filter_fn.(reason) do - crash_reason = GRPC.Logger.crash_reason(kind, exception, stacktrace) - - kind - |> Exception.format(exception, stacktrace) - |> Logger.error(crash_reason: crash_reason) + if apply(module, func_name, [exception]) do + log_error(exception, stacktrace) else :ok end end + + defp maybe_log_error(exception, nil, stacktrace) do + log_error(exception, stacktrace) + end + + defp log_error(%ReportException{kind: kind} = exception, stacktrace) do + crash_reason = GRPC.Logger.crash_reason(kind, exception, stacktrace) + + kind + |> Exception.format(exception, stacktrace) + |> Logger.error(crash_reason: crash_reason) + + :ok + end end diff --git a/lib/grpc/server/supervisor.ex b/lib/grpc/server/supervisor.ex index 83b464b8..946d92cc 100644 --- a/lib/grpc/server/supervisor.ex +++ b/lib/grpc/server/supervisor.ex @@ -41,7 +41,9 @@ defmodule GRPC.Server.Supervisor do * `:endpoint` - defines the endpoint module that will be started. * `:port` - the HTTP port for the endpoint. * `:servers` - the list of servers that will be be started. - * `:exception_log_filter` - a {Module, function} tuple that refers to a filter function. This must be a 1-arity function that returns a boolean, indicating whether or not a given exception should be logged or dropped. + * `:exception_log_filter` - a `{module, function :: atom}` tuple that refers to a filter function of arity 1. + This function will be called with a `GRPC.Server.Adapters.ReportException` struct and must return a boolean + indicating whether or not a given exception should be logged or dropped. Defaults to `nil`, which means all exceptions will be logged. * `:adapter_opts` - options for the adapter. Either `:endpoint` or `:servers` must be present, but not both. From eb9a05d7ed1c8106c083d77725b12fc0a5ac140f Mon Sep 17 00:00:00 2001 From: Paulo Valente <16843419+polvalente@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:23:17 -0300 Subject: [PATCH 4/7] chore: format --- lib/grpc/server/adapters/cowboy/handler.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/grpc/server/adapters/cowboy/handler.ex b/lib/grpc/server/adapters/cowboy/handler.ex index ed8bd929..eb7056dd 100644 --- a/lib/grpc/server/adapters/cowboy/handler.ex +++ b/lib/grpc/server/adapters/cowboy/handler.ex @@ -117,7 +117,6 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do defp extract_exception_log_filter_opt(opts) do case opts[:exception_log_filter] do - {module, func_name} when is_atom(module) and is_atom(func_name) -> {module, func_name} From 35053820f7bda5816301ea3b97e14e4fc989343b Mon Sep 17 00:00:00 2001 From: Paulo Valente <16843419+polvalente@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:35:22 -0300 Subject: [PATCH 5/7] test: improve test --- test/grpc/integration/server_test.exs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/grpc/integration/server_test.exs b/test/grpc/integration/server_test.exs index ebc5efe8..46caba3e 100644 --- a/test/grpc/integration/server_test.exs +++ b/test/grpc/integration/server_test.exs @@ -342,23 +342,33 @@ defmodule GRPC.Integration.ServerTest do ) end - test "passes thrown exceptions to `exception_log_filter" do - defmodule ExceptionFilterMustBeRaisedError do - def filter(%ArgumentError{message: "exception raised"}) do - true - end + defmodule ExceptionFilterMustBeRaisedError do + def filter(exception) do + data = get_in(exception.adapter_extra[:req][:headers]["test-data"]) + + {pid, ref} = :erlang.binary_to_term(data) + send(pid, {:exception_log_filter, ref}) + + true end + end + + test "passes thrown exceptions to `exception_log_filter" do + test_pid = self() + ref = make_ref() run_server( [HelloErrorServer], fn port -> - {:ok, channel} = GRPC.Stub.connect("localhost:#{port}") + {:ok, channel} = GRPC.Stub.connect("localhost:#{port}", headers: [{"test-data", :erlang.term_to_binary({test_pid, ref})}]) req = %Helloworld.HelloRequest{name: "raise", duration: 0} Helloworld.Greeter.Stub.say_hello(channel, req) end, 0, exception_log_filter: {ExceptionFilterMustBeRaisedError, :filter} ) + + assert_receive {:exception_log_filter, ^ref} end test "returns appropriate error for stream requests" do From aeb292c9ca2dd5ec803d447544e8f0ef5ab15f4e Mon Sep 17 00:00:00 2001 From: Paulo Valente <16843419+polvalente@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:38:28 -0300 Subject: [PATCH 6/7] chore: format --- test/grpc/integration/server_test.exs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/grpc/integration/server_test.exs b/test/grpc/integration/server_test.exs index 46caba3e..aa7055e6 100644 --- a/test/grpc/integration/server_test.exs +++ b/test/grpc/integration/server_test.exs @@ -360,7 +360,11 @@ defmodule GRPC.Integration.ServerTest do run_server( [HelloErrorServer], fn port -> - {:ok, channel} = GRPC.Stub.connect("localhost:#{port}", headers: [{"test-data", :erlang.term_to_binary({test_pid, ref})}]) + {:ok, channel} = + GRPC.Stub.connect("localhost:#{port}", + headers: [{"test-data", :erlang.term_to_binary({test_pid, ref})}] + ) + req = %Helloworld.HelloRequest{name: "raise", duration: 0} Helloworld.Greeter.Stub.say_hello(channel, req) end, From 95bbc7d9b499317a1ca5d4d5f444f5143c955cac Mon Sep 17 00:00:00 2001 From: Paulo Valente <16843419+polvalente@users.noreply.github.com> Date: Fri, 7 Nov 2025 20:41:03 -0300 Subject: [PATCH 7/7] fix test --- test/grpc/integration/server_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/grpc/integration/server_test.exs b/test/grpc/integration/server_test.exs index aa7055e6..12313d6f 100644 --- a/test/grpc/integration/server_test.exs +++ b/test/grpc/integration/server_test.exs @@ -344,7 +344,7 @@ defmodule GRPC.Integration.ServerTest do defmodule ExceptionFilterMustBeRaisedError do def filter(exception) do - data = get_in(exception.adapter_extra[:req][:headers]["test-data"]) + data = exception.adapter_extra[:req][:headers]["test-data"] {pid, ref} = :erlang.binary_to_term(data) send(pid, {:exception_log_filter, ref})