@@ -618,6 +618,159 @@ defmodule Sentry.LoggerHandler.LogsTest do
618618 end
619619 end
620620
621+ describe "before_send_log callback" do
622+ test "allows modifying log events before sending" , % { bypass: bypass , buffer: buffer } do
623+ test_pid = self ( )
624+
625+ put_test_config (
626+ before_send_log: fn log_event ->
627+ % { log_event | attributes: Map . put ( log_event . attributes , "custom_attr" , "injected" ) }
628+ end
629+ )
630+
631+ Bypass . expect_once ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
632+ { :ok , body , conn } = Plug.Conn . read_body ( conn )
633+ [ _header , _item_header , item_body , _ ] = String . split ( body , "\n " )
634+
635+ item_body_map = decode! ( item_body )
636+ assert % { "items" => [ log_event ] } = item_body_map
637+
638+ assert log_event [ "attributes" ] [ "custom_attr" ] == % {
639+ "type" => "string" ,
640+ "value" => "injected"
641+ }
642+
643+ send ( test_pid , :envelope_sent )
644+ Plug.Conn . resp ( conn , 200 , ~s< {"id": "test-123"}> )
645+ end )
646+
647+ Logger . info ( "Test message" )
648+
649+ assert_buffer_size ( buffer , 1 )
650+
651+ LogEventBuffer . flush ( server: buffer )
652+
653+ assert_receive :envelope_sent , 1000
654+ end
655+
656+ test "filters out log events when callback returns nil" , % { bypass: bypass , buffer: buffer } do
657+ put_test_config (
658+ before_send_log: fn log_event ->
659+ if String . contains? ( log_event . body , "should_be_filtered" ) do
660+ nil
661+ else
662+ log_event
663+ end
664+ end
665+ )
666+
667+ test_pid = self ( )
668+
669+ Bypass . expect_once ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
670+ { :ok , body , conn } = Plug.Conn . read_body ( conn )
671+ [ _header , _item_header , item_body , _ ] = String . split ( body , "\n " )
672+
673+ item_body_map = decode! ( item_body )
674+ assert % { "items" => [ log_event ] } = item_body_map
675+ assert log_event [ "body" ] == "This message should pass"
676+
677+ send ( test_pid , :envelope_sent )
678+ Plug.Conn . resp ( conn , 200 , ~s< {"id": "test-123"}> )
679+ end )
680+
681+ Logger . info ( "This message should_be_filtered" )
682+ Logger . info ( "This message should pass" )
683+
684+ assert_buffer_size ( buffer , 2 )
685+
686+ LogEventBuffer . flush ( server: buffer )
687+
688+ assert_receive :envelope_sent , 1000
689+ end
690+
691+ test "filters out log events when callback returns false" , % { bypass: bypass , buffer: buffer } do
692+ put_test_config (
693+ before_send_log: fn log_event ->
694+ if String . contains? ( log_event . body , "drop_me" ) do
695+ false
696+ else
697+ log_event
698+ end
699+ end
700+ )
701+
702+ test_pid = self ( )
703+
704+ Bypass . expect_once ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
705+ { :ok , body , conn } = Plug.Conn . read_body ( conn )
706+ [ _header , _item_header , item_body , _ ] = String . split ( body , "\n " )
707+
708+ item_body_map = decode! ( item_body )
709+ assert % { "items" => [ log_event ] } = item_body_map
710+ assert log_event [ "body" ] == "Keep this message"
711+
712+ send ( test_pid , :envelope_sent )
713+ Plug.Conn . resp ( conn , 200 , ~s< {"id": "test-123"}> )
714+ end )
715+
716+ Logger . info ( "drop_me please" )
717+ Logger . info ( "Keep this message" )
718+
719+ assert_buffer_size ( buffer , 2 )
720+
721+ LogEventBuffer . flush ( server: buffer )
722+
723+ assert_receive :envelope_sent , 1000
724+ end
725+
726+ test "supports MFA tuple callback format" , % { bypass: bypass , buffer: buffer } do
727+ test_pid = self ( )
728+
729+ put_test_config ( before_send_log: { __MODULE__ , :before_send_log_callback } )
730+
731+ Bypass . expect_once ( bypass , "POST" , "/api/1/envelope/" , fn conn ->
732+ { :ok , body , conn } = Plug.Conn . read_body ( conn )
733+ [ _header , _item_header , item_body , _ ] = String . split ( body , "\n " )
734+
735+ item_body_map = decode! ( item_body )
736+ assert % { "items" => [ log_event ] } = item_body_map
737+
738+ assert log_event [ "attributes" ] [ "mfa_added" ] == % {
739+ "type" => "string" ,
740+ "value" => "true"
741+ }
742+
743+ send ( test_pid , :envelope_sent )
744+ Plug.Conn . resp ( conn , 200 , ~s< {"id": "test-123"}> )
745+ end )
746+
747+ Logger . info ( "Test MFA callback" )
748+
749+ assert_buffer_size ( buffer , 1 )
750+
751+ LogEventBuffer . flush ( server: buffer )
752+
753+ assert_receive :envelope_sent , 1000
754+ end
755+
756+ test "does not send any logs when all are filtered" , % { buffer: buffer } do
757+ put_test_config ( before_send_log: fn _log_event -> nil end )
758+
759+ Logger . info ( "All messages filtered 1" )
760+ Logger . info ( "All messages filtered 2" )
761+
762+ assert_buffer_size ( buffer , 2 )
763+
764+ LogEventBuffer . flush ( server: buffer )
765+
766+ refute_receive _ , 100
767+ end
768+ end
769+
770+ def before_send_log_callback ( log_event ) do
771+ % { log_event | attributes: Map . put ( log_event . attributes , "mfa_added" , "true" ) }
772+ end
773+
621774 defp add_logs_handler ( % { buffer: buffer } ) do
622775 handler_name = :"sentry_logs_handler_#{ System . unique_integer ( [ :positive ] ) } "
623776
0 commit comments