@@ -102,14 +102,6 @@ type EventProcessor func(event *Event, hint *EventHint) *Event
102102// needing the otel dependency on the root package.
103103type externalContextTraceResolver func (ctx context.Context ) (traceID TraceID , spanID SpanID , ok bool )
104104
105- // EventModifier is the interface that wraps the ApplyToEvent method.
106- //
107- // ApplyToEvent changes an event based on external data and/or
108- // an event hint.
109- type EventModifier interface {
110- ApplyToEvent (event * Event , hint * EventHint , client * Client ) * Event
111- }
112-
113105var globalEventProcessors []EventProcessor
114106
115107// AddGlobalEventProcessor adds processor to the global list of event
@@ -641,48 +633,68 @@ func (client *Client) GetDataCollection() DataCollection {
641633 return * cloneDataCollection (client .options .DataCollection )
642634}
643635
644- // CaptureMessage captures an arbitrary message.
645- func (client * Client ) CaptureMessage (message string , hint * EventHint , scope EventModifier ) * EventID {
636+ // CaptureMessage captures an arbitrary message using the scope carried by ctx .
637+ func (client * Client ) CaptureMessage (ctx context. Context , message string , options ... CaptureOption ) * EventID {
646638 if ! client .IsEnabled () {
647639 return nil
648640 }
649- event := client .EventFromMessage (message , LevelInfo )
650- return client .CaptureEvent (event , hint , scope )
641+ opts := resolveCaptureOptions (ctx , options ... )
642+ opts .defaultLevel = LevelInfo
643+ if message == "" {
644+ err := usageError {fmt .Errorf ("%s called with empty message" , callerFunctionName ())}
645+ return client .capture (ctx , client .eventFromException (err ), opts )
646+ }
647+ return client .capture (ctx , client .eventFromMessage (message ), opts )
651648}
652649
653- // CaptureException captures an error.
654- func (client * Client ) CaptureException (exception error , hint * EventHint , scope EventModifier ) * EventID {
650+ // CaptureException captures an error using the scope carried by ctx .
651+ func (client * Client ) CaptureException (ctx context. Context , exception error , options ... CaptureOption ) * EventID {
655652 if ! client .IsEnabled () {
656653 return nil
657654 }
658- event := client .EventFromException (exception , LevelError )
659- return client .CaptureEvent (event , hint , scope )
655+ opts := resolveCaptureOptions (ctx , options ... )
656+ if opts .hint .OriginalException == nil {
657+ opts .hint .OriginalException = exception
658+ }
659+ opts .defaultLevel = LevelError
660+ if exception == nil {
661+ exception = usageError {fmt .Errorf ("%s called with nil error" , callerFunctionName ())}
662+ }
663+ return client .capture (ctx , client .eventFromException (exception ), opts )
660664}
661665
662- // CaptureCheckIn captures a check in.
663- func (client * Client ) CaptureCheckIn (checkIn * CheckIn , monitorConfig * MonitorConfig , scope EventModifier ) * EventID {
666+ // CaptureCheckIn captures a check-in using the scope carried by ctx.
667+ func (client * Client ) CaptureCheckIn (
668+ ctx context.Context ,
669+ checkIn * CheckIn ,
670+ monitorConfig * MonitorConfig ,
671+ options ... CaptureOption ,
672+ ) * EventID {
664673 if ! client .IsEnabled () {
665674 return nil
666675 }
667- event := client .EventFromCheckIn (checkIn , monitorConfig )
668- if event != nil && event .CheckIn != nil {
669- if client .CaptureEvent (event , nil , scope ) != nil {
670- return & event .CheckIn .ID
671- }
676+ event := client .eventFromCheckIn (checkIn , monitorConfig )
677+ if event == nil {
678+ return nil
672679 }
673- return nil
680+ id := event .CheckIn .ID
681+ if client .capture (ctx , event , resolveCaptureOptions (ctx , options ... )) == nil {
682+ return nil
683+ }
684+ return & id
674685}
675686
676- // CaptureEvent captures an event on the currently active client if any.
677- //
678- // The event must already be assembled. Typically, code would instead use
679- // the utility methods like CaptureException. The return value is the
680- // event ID. In case Sentry is disabled or event was dropped, the return value will be nil.
681- func (client * Client ) CaptureEvent (event * Event , hint * EventHint , scope EventModifier ) * EventID {
687+ // CaptureEvent captures an event using the scope carried by ctx.
688+ func (client * Client ) CaptureEvent (ctx context.Context , event * Event , options ... CaptureOption ) * EventID {
682689 if ! client .IsEnabled () {
683690 return nil
684691 }
685- return client .processEvent (event , hint , scope )
692+ opts := resolveCaptureOptions (ctx , options ... )
693+ if event == nil {
694+ event = client .eventFromException (usageError {fmt .Errorf ("%s called with nil event" , callerFunctionName ())})
695+ opts .defaultLevel = LevelError
696+ }
697+ return client .capture (ctx , event , opts )
686698}
687699
688700func (client * Client ) captureLog (log * Log , _ * Scope ) bool {
@@ -750,58 +762,27 @@ func (client *Client) captureMetric(metric *Metric, _ *Scope) bool {
750762 return true
751763}
752764
753- // Recover captures a panic.
754- // Returns EventID if successfully, or nil if there's no error to recover from.
755- func (client * Client ) Recover (err any , hint * EventHint , scope EventModifier ) * EventID {
756- if err == nil {
757- err = recover ()
758- }
759-
760- // Normally we would not pass a nil Context, but RecoverWithContext doesn't
761- // use the Context for communicating deadline nor cancelation. All it does
762- // is store the Context in the EventHint and there nil means the Context is
763- // not available.
764- // nolint: staticcheck
765- return client .RecoverWithContext (nil , err , hint , scope )
766- }
767-
768- // RecoverWithContext captures a panic and passes relevant context object.
769- // Returns EventID if successfully, or nil if there's no error to recover from.
770- func (client * Client ) RecoverWithContext (
771- ctx context.Context ,
772- err any ,
773- hint * EventHint ,
774- scope EventModifier ,
775- ) * EventID {
776- if err == nil {
777- err = recover ()
778- }
779- if err == nil {
780- return nil
781- }
782- if ! client .IsEnabled () {
765+ func (client * Client ) capturePanic (ctx context.Context , recovered any , options ... CaptureOption ) * EventID {
766+ if recovered == nil || ! client .IsEnabled () {
783767 return nil
784768 }
785769
786- if ctx != nil {
787- if hint == nil {
788- hint = & EventHint {}
789- }
790- if hint .Context == nil {
791- hint .Context = ctx
792- }
770+ opts := resolveCaptureOptions (ctx , options ... )
771+ if opts .hint .RecoveredException == nil {
772+ opts .hint .RecoveredException = recovered
793773 }
794774
795775 var event * Event
796- switch err := err .(type ) {
776+ switch recovered := recovered .(type ) {
797777 case error :
798- event = client .EventFromException ( err , LevelFatal )
778+ event = client .eventFromException ( recovered )
799779 case string :
800- event = client .EventFromMessage ( err , LevelFatal )
780+ event = client .eventFromMessage ( recovered )
801781 default :
802- event = client .EventFromMessage (fmt .Sprintf ("%#v" , err ), LevelFatal )
782+ event = client .eventFromMessage (fmt .Sprintf ("%#v" , recovered ) )
803783 }
804- return client .CaptureEvent (event , hint , scope )
784+ opts .defaultLevel = LevelFatal
785+ return client .capture (ctx , event , opts )
805786}
806787
807788// Flush waits until the underlying Transport sends any buffered events to the
@@ -876,14 +857,8 @@ func (client *Client) Close() {
876857 client .Transport .Close ()
877858}
878859
879- // EventFromMessage creates an event from the given message string.
880- func (client * Client ) EventFromMessage (message string , level Level ) * Event {
881- if message == "" {
882- err := usageError {fmt .Errorf ("%s called with empty message" , callerFunctionName ())}
883- return client .EventFromException (err , level )
884- }
860+ func (client * Client ) eventFromMessage (message string ) * Event {
885861 event := NewEvent ()
886- event .Level = level
887862 event .Message = message
888863
889864 if client .options .AttachStacktrace {
@@ -897,23 +872,14 @@ func (client *Client) EventFromMessage(message string, level Level) *Event {
897872 return event
898873}
899874
900- // EventFromException creates a new Sentry event from the given `error` instance.
901- func (client * Client ) EventFromException (exception error , level Level ) * Event {
875+ func (client * Client ) eventFromException (exception error ) * Event {
902876 event := NewEvent ()
903- event .Level = level
904-
905- err := exception
906- if err == nil {
907- err = usageError {fmt .Errorf ("%s called with nil error" , callerFunctionName ())}
908- }
909-
910- event .SetException (err , client .options .MaxErrorDepth )
877+ event .SetException (exception , client .options .MaxErrorDepth )
911878
912879 return event
913880}
914881
915- // EventFromCheckIn creates a new Sentry event from the given `check_in` instance.
916- func (client * Client ) EventFromCheckIn (checkIn * CheckIn , monitorConfig * MonitorConfig ) * Event {
882+ func (client * Client ) eventFromCheckIn (checkIn * CheckIn , monitorConfig * MonitorConfig ) * Event {
917883 if checkIn == nil {
918884 return nil
919885 }
@@ -956,12 +922,7 @@ func (client *Client) GetSDKIdentifier() string {
956922 return client .sdkIdentifier
957923}
958924
959- func (client * Client ) processEvent (event * Event , hint * EventHint , scope EventModifier ) * EventID {
960- if event == nil {
961- err := usageError {fmt .Errorf ("%s called with nil event" , callerFunctionName ())}
962- return client .CaptureException (err , hint , scope )
963- }
964-
925+ func (client * Client ) capture (ctx context.Context , event * Event , opts captureOptions ) * EventID {
965926 // Transactions are sampled by options.TracesSampleRate or
966927 // options.TracesSampler when they are started. Other events
967928 // (errors, messages) are sampled here. Does not apply to check-ins.
@@ -971,14 +932,13 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
971932 return nil
972933 }
973934
974- if event = client .prepareEvent (event , hint , scope ); event == nil {
935+ scope := scopeFromContextOrGlobal (ctx )
936+ if event = client .prepareEvent (event , scope , opts ); event == nil {
975937 return nil
976938 }
977939
978940 // Apply beforeSend* processors
979- if hint == nil {
980- hint = & EventHint {}
981- }
941+ hint := opts .hint
982942 switch event .Type {
983943 case transactionType :
984944 if client .options .BeforeSendTransaction != nil {
@@ -1009,15 +969,19 @@ func (client *Client) processEvent(event *Event, hint *EventHint, scope EventMod
1009969 if client .telemetryProcessor != nil {
1010970 if ! client .telemetryProcessor .Add (event ) {
1011971 debuglog .Println ("Event dropped: telemetry buffer full or unavailable" )
972+ return nil
1012973 }
1013974 } else {
1014975 client .Transport .SendEvent (event )
1015976 }
1016977
978+ if event .Type != transactionType && event .Type != checkInType {
979+ scope .setLastEventID (event .EventID )
980+ }
1017981 return & event .EventID
1018982}
1019983
1020- func (client * Client ) prepareEvent (event * Event , hint * EventHint , scope EventModifier ) * Event {
984+ func (client * Client ) prepareEvent (event * Event , scope * Scope , opts captureOptions ) * Event {
1021985 if event .EventID == "" {
1022986 // TODO set EventID when the event is created, same as in other SDKs. It's necessary for profileTransaction.ID.
1023987 event .EventID = EventID (uuid ())
@@ -1027,10 +991,6 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
1027991 event .Timestamp = time .Now ()
1028992 }
1029993
1030- if event .Level == "" {
1031- event .Level = LevelInfo
1032- }
1033-
1034994 if event .ServerName == "" {
1035995 event .ServerName = client .options .ServerName
1036996
@@ -1063,17 +1023,26 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
10631023 }
10641024
10651025 if scope != nil {
1066- event = scope .ApplyToEvent (event , hint , client )
1026+ event = scope .ApplyToEvent (event , opts . hint , client )
10671027 if event == nil {
10681028 return nil
10691029 }
10701030 }
1031+ if event .Level == "" {
1032+ event .Level = opts .defaultLevel
1033+ }
1034+ if event .Level == "" {
1035+ event .Level = LevelInfo
1036+ }
1037+ if opts .level != "" {
1038+ event .Level = opts .level
1039+ }
10711040
10721041 for _ , processor := range client .eventProcessors {
10731042 id := event .EventID
10741043 category := event .toCategory ()
10751044 spanCountBefore := event .GetSpanCount ()
1076- event = processor (event , hint )
1045+ event = processor (event , opts . hint )
10771046 if event == nil {
10781047 debuglog .Printf ("Event dropped by one of the Client EventProcessors: %s\n " , id )
10791048 client .reportRecorder .RecordOne (report .ReasonEventProcessor , category )
@@ -1094,7 +1063,7 @@ func (client *Client) prepareEvent(event *Event, hint *EventHint, scope EventMod
10941063 id := event .EventID
10951064 category := event .toCategory ()
10961065 spanCountBefore := event .GetSpanCount ()
1097- event = processor (event , hint )
1066+ event = processor (event , opts . hint )
10981067 if event == nil {
10991068 debuglog .Printf ("Event dropped by one of the Global EventProcessors: %s\n " , id )
11001069 client .reportRecorder .RecordOne (report .ReasonEventProcessor , category )
0 commit comments