@@ -29,7 +29,8 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
2929 pid: server_rpc_pid :: pid ,
3030 handling_timer: timeout_timer_ref :: reference ,
3131 pending_reader: nil | pending_reader ,
32- access_mode: GRPC.Server.Stream . access_mode ( )
32+ access_mode: GRPC.Server.Stream . access_mode ( ) ,
33+ exception_log_filter: exception_log_filter ( )
3334 }
3435 @ type init_result ::
3536 { :cowboy_loop , :cowboy_req . req ( ) , stream_state } | { :ok , :cowboy_req . req ( ) , init_state }
@@ -40,6 +41,8 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
4041
4142 @ type headers :: % { binary ( ) => binary ( ) }
4243
44+ @ type exception_log_filter :: { module ( ) , atom ( ) } | nil
45+
4346 @ doc """
4447 This function is meant to be called whenever a new request arrives to an existing connection.
4548 This handler works mainly with two linked processes.
@@ -52,6 +55,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
5255 @ spec init ( :cowboy_req . req ( ) , state :: init_state ) :: init_result
5356 def init ( req , { endpoint , { _name , server } , route , opts } = state ) do
5457 http_method = extract_http_method ( req ) |> String . to_existing_atom ( )
58+ exception_log_filter = extract_exception_log_filter_opt ( opts )
5559
5660 with { :ok , access_mode , sub_type , content_type } <- find_content_type_subtype ( req ) ,
5761 { :ok , codec } <- find_codec ( sub_type , content_type , server ) ,
@@ -98,7 +102,8 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
98102 pid: server_rpc_pid ,
99103 handling_timer: timer_ref ,
100104 pending_reader: nil ,
101- access_mode: access_mode
105+ access_mode: access_mode ,
106+ exception_log_filter: exception_log_filter
102107 }
103108 }
104109 else
@@ -110,6 +115,19 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
110115 end
111116 end
112117
118+ defp extract_exception_log_filter_opt ( opts ) do
119+ case opts [ :exception_log_filter ] do
120+ { module , func_name } when is_atom ( module ) and is_atom ( func_name ) ->
121+ { module , func_name }
122+
123+ nil ->
124+ nil
125+
126+ invalid ->
127+ raise ArgumentError , "invalid exception log filter: #{ inspect ( invalid ) } "
128+ end
129+ end
130+
113131 defp find_codec ( subtype , content_type , server ) do
114132 if codec = Enum . find ( server . __meta__ ( :codecs ) , nil , fn c -> c . name ( ) == subtype end ) do
115133 { :ok , codec }
@@ -466,7 +484,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
466484
467485 [ req: req ]
468486 |> ReportException . new ( error )
469- |> log_error ( )
487+ |> maybe_log_error ( state . exception_log_filter )
470488
471489 { :stop , req , state }
472490 end
@@ -488,12 +506,12 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
488506 end
489507
490508 # expected error raised from user to return error immediately
491- def info ( { :EXIT , pid , { % RPCError { } = error , stacktrace } } , req , state = % { pid: pid } ) do
509+ def info ( { :EXIT , pid , { :shutdown , { % RPCError { } = error , stacktrace } } } , req , state = % { pid: pid } ) do
492510 req = send_error ( req , error , state , :rpc_error )
493511
494512 [ req: req ]
495513 |> ReportException . new ( error , stacktrace )
496- |> log_error ( stacktrace )
514+ |> maybe_log_error ( state . exception_log_filter , stacktrace )
497515
498516 { :stop , req , state }
499517 end
@@ -506,7 +524,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
506524
507525 [ req: req ]
508526 |> ReportException . new ( reason , stack , kind )
509- |> log_error ( stack )
527+ |> maybe_log_error ( state . exception_log_filter , stack )
510528
511529 { :stop , req , state }
512530 end
@@ -517,7 +535,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
517535
518536 [ req: req ]
519537 |> ReportException . new ( reason , stacktrace )
520- |> log_error ( stacktrace )
538+ |> maybe_log_error ( state . exception_log_filter , stacktrace )
521539
522540 { :stop , req , state }
523541 end
@@ -550,7 +568,7 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
550568
551569 case result do
552570 { :error , % GRPC.RPCError { } = e } ->
553- exit ( { e , _stacktrace = [ ] } )
571+ exit ( { :shutdown , { e , _stacktrace = [ ] } } )
554572
555573 { :error , % { kind: _kind , reason: _reason , stack: _stack } = e } ->
556574 exit ( { :handle_error , e } )
@@ -705,11 +723,31 @@ defmodule GRPC.Server.Adapters.Cowboy.Handler do
705723 { :wait , ref }
706724 end
707725
708- defp log_error ( % ReportException { kind: kind } = exception , stacktrace \\ [ ] ) do
726+ defp maybe_log_error ( exception , filter , stacktrace \\ [ ] )
727+
728+ defp maybe_log_error (
729+ % ReportException { } = exception ,
730+ { module , func_name } ,
731+ stacktrace
732+ ) do
733+ if apply ( module , func_name , [ exception ] ) do
734+ log_error ( exception , stacktrace )
735+ else
736+ :ok
737+ end
738+ end
739+
740+ defp maybe_log_error ( exception , nil , stacktrace ) do
741+ log_error ( exception , stacktrace )
742+ end
743+
744+ defp log_error ( % ReportException { kind: kind } = exception , stacktrace ) do
709745 crash_reason = GRPC.Logger . crash_reason ( kind , exception , stacktrace )
710746
711747 kind
712748 |> Exception . format ( exception , stacktrace )
713749 |> Logger . error ( crash_reason: crash_reason )
750+
751+ :ok
714752 end
715753end
0 commit comments