55use Utopia \Span \Span ;
66
77/**
8- * Exports spans to Sentry as events .
8+ * Exports error spans to Sentry Issues .
99 *
10- * Sends error spans with full stacktraces (level: error) and
11- * non-error spans as messages (level: info) to Sentry Issues .
10+ * Only spans with errors are sent. Non- error spans are silently skipped.
11+ * Use the Stdout exporter for non-error spans .
1212 */
1313class Sentry implements Exporter
1414{
@@ -92,6 +92,12 @@ public function export(Span $span): void
9292
9393 private function buildEnvelope (Span $ span ): ?string
9494 {
95+ $ error = $ span ->getError ();
96+
97+ if ($ error === null ) {
98+ return null ;
99+ }
100+
95101 $ attributes = $ span ->getAttributes ();
96102
97103 $ traceId = (string ) ($ attributes ['span.trace_id ' ] ?? '' );
@@ -100,8 +106,6 @@ private function buildEnvelope(Span $span): ?string
100106 $ finishedAt = (float ) ($ attributes ['span.finished_at ' ] ?? microtime (true ));
101107 $ action = $ span ->getAction ();
102108
103- $ error = $ span ->getError ();
104-
105109 $ traceContext = [
106110 'trace_id ' => $ traceId ,
107111 'span_id ' => $ spanId ,
@@ -122,50 +126,48 @@ private function buildEnvelope(Span $span): ?string
122126 'content_type ' => 'application/json ' ,
123127 ]);
124128
129+ $ frames = [];
130+ foreach (array_reverse ($ error ->getTrace ()) as $ frame ) {
131+ if (!isset ($ frame ['file ' ])) {
132+ continue ;
133+ }
134+ $ sentryFrame = [
135+ 'filename ' => $ frame ['file ' ],
136+ 'lineno ' => $ frame ['line ' ] ?? 0 ,
137+ 'in_app ' => !str_contains ($ frame ['file ' ], '/vendor/ ' ),
138+ ];
139+ if (isset ($ frame ['function ' ])) {
140+ $ sentryFrame ['function ' ] = isset ($ frame ['class ' ])
141+ ? $ frame ['class ' ] . $ frame ['type ' ] . $ frame ['function ' ]
142+ : $ frame ['function ' ];
143+ }
144+ $ frames [] = $ sentryFrame ;
145+ }
146+
147+ $ frames [] = [
148+ 'filename ' => $ error ->getFile (),
149+ 'lineno ' => $ error ->getLine (),
150+ 'in_app ' => !str_contains ($ error ->getFile (), '/vendor/ ' ),
151+ ];
152+
125153 $ payloadData = [
126- 'level ' => $ error !== null ? 'error ' : ' info ' ,
154+ 'level ' => 'error ' ,
127155 'platform ' => 'php ' ,
128156 'timestamp ' => $ finishedAt ,
129- 'message ' => $ action ,
157+ 'transaction ' => $ action ,
158+ 'message ' => $ error ->getMessage (),
130159 'contexts ' => [
131160 'trace ' => $ traceContext ,
132161 ],
133- 'extra ' => $ attributes ,
134- ];
135-
136- if ($ error !== null ) {
137- $ frames = [];
138- foreach (array_reverse ($ error ->getTrace ()) as $ frame ) {
139- if (!isset ($ frame ['file ' ])) {
140- continue ;
141- }
142- $ sentryFrame = [
143- 'filename ' => $ frame ['file ' ],
144- 'lineno ' => $ frame ['line ' ] ?? 0 ,
145- 'in_app ' => !str_contains ($ frame ['file ' ], '/vendor/ ' ),
146- ];
147- if (isset ($ frame ['function ' ])) {
148- $ sentryFrame ['function ' ] = isset ($ frame ['class ' ])
149- ? $ frame ['class ' ] . $ frame ['type ' ] . $ frame ['function ' ]
150- : $ frame ['function ' ];
151- }
152- $ frames [] = $ sentryFrame ;
153- }
154-
155- $ frames [] = [
156- 'filename ' => $ error ->getFile (),
157- 'lineno ' => $ error ->getLine (),
158- 'in_app ' => !str_contains ($ error ->getFile (), '/vendor/ ' ),
159- ];
160-
161- $ payloadData ['exception ' ] = [
162+ 'exception ' => [
162163 'values ' => [[
163164 'type ' => $ error ::class,
164165 'value ' => $ error ->getMessage (),
165166 'stacktrace ' => ['frames ' => $ frames ],
166167 ]],
167- ];
168- }
168+ ],
169+ 'extra ' => $ attributes ,
170+ ];
169171
170172 if ($ this ->environment !== null ) {
171173 $ payloadData ['environment ' ] = $ this ->environment ;
0 commit comments