2
2
3
3
namespace Sentry \Laravel \Tracing \Integrations ;
4
4
5
+ use GraphQL \Language \AST \DocumentNode ;
5
6
use GraphQL \Language \AST \OperationDefinitionNode ;
6
- use Illuminate \Contracts \Events \Dispatcher ;
7
+ use Illuminate \Contracts \Events \Dispatcher as EventDispatcher ;
7
8
use Nuwave \Lighthouse \Events \EndExecution ;
8
9
use Nuwave \Lighthouse \Events \EndRequest ;
9
10
use Nuwave \Lighthouse \Events \StartExecution ;
12
13
use Sentry \SentrySdk ;
13
14
use Sentry \Tracing \SpanContext ;
14
15
15
- class LighthouseIntegration
16
+ class LighthouseIntegration implements IntegrationInterface
16
17
{
17
- /** @var array<int, < string|null , \GraphQL\Language\AST\OperationDefinitionNode> > $operations */
18
+ /** @var array<int, array{? string, \GraphQL\Language\AST\OperationDefinitionNode} > $operations */
18
19
private $ operations ;
19
20
20
21
/** @var \Sentry\Tracing\Span|null $previousSpan */
@@ -26,16 +27,12 @@ class LighthouseIntegration
26
27
/** @var \Sentry\Tracing\Span|null $operationSpan */
27
28
private $ operationSpan ;
28
29
29
- public function __construct (Dispatcher $ evenDispatcher )
30
+ public function __construct (EventDispatcher $ eventDispatcher )
30
31
{
31
- if (!class_exists (StartRequest::class)) {
32
- return ;
33
- }
34
-
35
- $ evenDispatcher ->listen (StartRequest::class, [$ this , 'handleStartRequest ' ]);
36
- $ evenDispatcher ->listen (StartExecution::class, [$ this , 'handleStartExecution ' ]);
37
- $ evenDispatcher ->listen (EndExecution::class, [$ this , 'handleEndExecution ' ]);
38
- $ evenDispatcher ->listen (EndRequest::class, [$ this , 'handleEndRequest ' ]);
32
+ $ eventDispatcher ->listen (StartRequest::class, [$ this , 'handleStartRequest ' ]);
33
+ $ eventDispatcher ->listen (StartExecution::class, [$ this , 'handleStartExecution ' ]);
34
+ $ eventDispatcher ->listen (EndExecution::class, [$ this , 'handleEndExecution ' ]);
35
+ $ eventDispatcher ->listen (EndRequest::class, [$ this , 'handleEndRequest ' ]);
39
36
}
40
37
41
38
public function handleStartRequest (StartRequest $ startRequest ): void
@@ -46,12 +43,12 @@ public function handleStartRequest(StartRequest $startRequest): void
46
43
return ;
47
44
}
48
45
49
- $ this ->operations = [];
50
-
51
46
$ context = new SpanContext ;
52
47
$ context ->setOp ('graphql.request ' );
53
48
54
- $ this ->requestSpan = $ this ->previousSpan ->startChild ($ context );
49
+ $ this ->operations = [];
50
+ $ this ->requestSpan = $ this ->previousSpan ->startChild ($ context );
51
+ $ this ->operationSpan = null ;
55
52
56
53
SentrySdk::getCurrentHub ()->setSpan ($ this ->requestSpan );
57
54
}
@@ -62,14 +59,18 @@ public function handleStartExecution(StartExecution $startExecution): void
62
59
return ;
63
60
}
64
61
62
+ if (!$ startExecution ->query instanceof DocumentNode) {
63
+ return ;
64
+ }
65
+
65
66
/** @var \GraphQL\Language\AST\OperationDefinitionNode|null $operationDefinition */
66
67
$ operationDefinition = $ startExecution ->query ->definitions [0 ] ?? null ;
67
68
68
- if ($ operationDefinition === null ) {
69
+ if (! $ operationDefinition instanceof OperationDefinitionNode ) {
69
70
return ;
70
71
}
71
72
72
- $ this ->operations [] = [$ startExecution ->operationName , $ operationDefinition ];
73
+ $ this ->operations [] = [$ startExecution ->operationName ?? null , $ operationDefinition ];
73
74
74
75
$ context = new SpanContext ;
75
76
$ context ->setOp (
@@ -147,6 +148,9 @@ private function updateTransaction(): void
147
148
SentrySdk::getCurrentHub ()->getTransaction ()->setName ($ transactionName );
148
149
}
149
150
151
+ /**
152
+ * @return array<int, string>
153
+ */
150
154
private function extractOperationNames (OperationDefinitionNode $ operation ): array
151
155
{
152
156
if ($ operation ->name !== null ) {
@@ -157,9 +161,9 @@ private function extractOperationNames(OperationDefinitionNode $operation): arra
157
161
158
162
/** @var \GraphQL\Language\AST\FieldNode $selection */
159
163
foreach ($ operation ->selectionSet ->selections as $ selection ) {
160
- $ selectionSet [] = $ selection -> alias === null
161
- ? $ selection -> name -> value
162
- : $ selection ->alias ->value ;
164
+ // Not respecting aliases because they are only relevant for clients
165
+ // and the tracing we extract here is targeted at server developers.
166
+ $ selectionSet [] = $ selection ->name ->value ;
163
167
}
164
168
165
169
sort ($ selectionSet , SORT_STRING );
@@ -169,6 +173,10 @@ private function extractOperationNames(OperationDefinitionNode $operation): arra
169
173
170
174
public static function supported (): bool
171
175
{
172
- return class_exists (StartRequest::class);
176
+ if (!class_exists (StartRequest::class) || !class_exists (StartExecution::class)) {
177
+ return false ;
178
+ }
179
+
180
+ return property_exists (StartExecution::class, 'query ' );
173
181
}
174
182
}
0 commit comments