6
6
7
7
use CurlHandle ;
8
8
use CurlMultiHandle ;
9
+ use OpenTelemetry \API \Behavior \LogsMessagesTrait ;
9
10
use OpenTelemetry \API \Globals ;
10
11
use OpenTelemetry \API \Instrumentation \CachedInstrumentation ;
11
12
use OpenTelemetry \API \Trace \Span ;
21
22
22
23
class CurlInstrumentation
23
24
{
25
+ use LogsMessagesTrait;
26
+
24
27
public const NAME = 'curl ' ;
25
28
26
29
public static function register (): void
27
30
{
28
- /** @var WeakMap<CurlHandle, CurlHandleMetadata> */
31
+ // @var WeakMap<CurlHandle, CurlHandleMetadata>
29
32
$ curlHandleToAttributes = new WeakMap ();
30
33
31
34
/** @var WeakMap<CurlMultiHandle, array> $curlMultiToHandle
@@ -72,7 +75,12 @@ public static function register(): void
72
75
return ;
73
76
}
74
77
75
- /** @psalm-suppress PossiblyNullReference */
78
+ if (!isset ($ curlHandleToAttributes [$ params [0 ]])) {
79
+ self ::logDebug ('Curl handle is not tracked ' , ['retVal ' => $ retVal , 'params ' => $ params ]);
80
+
81
+ return ;
82
+ }
83
+
76
84
$ curlHandleToAttributes [$ params [0 ]]->updateFromCurlOption ($ params [1 ], $ params [2 ]);
77
85
}
78
86
);
@@ -92,35 +100,37 @@ public static function register(): void
92
100
return ;
93
101
}
94
102
103
+ if (!isset ($ curlHandleToAttributes [$ params [0 ]])) {
104
+ self ::logDebug ('Curl handle is not tracked ' , ['retVal ' => $ retVal , 'params ' => $ params ]);
105
+
106
+ return ;
107
+ }
108
+
95
109
foreach ($ params [1 ] as $ option => $ value ) {
96
110
/** @psalm-suppress PossiblyNullReference */
97
111
$ curlHandleToAttributes [$ params [0 ]]->updateFromCurlOption ($ option , $ value );
98
112
}
99
113
}
100
114
);
101
115
102
- hook (
103
- null ,
104
- 'curl_close ' ,
105
- pre: static function ($ obj , array $ params ) use ($ curlHandleToAttributes ) {
106
- if (count ($ params ) > 0 && $ params [0 ] instanceof CurlHandle) {
107
- $ curlHandleToAttributes ->offsetUnset ($ params [0 ]);
108
- }
109
- },
110
- post: null
111
- );
112
-
113
116
hook (
114
117
null ,
115
118
'curl_copy_handle ' ,
116
119
pre: null ,
117
120
post: static function ($ obj , array $ params , mixed $ retVal ) use ($ curlHandleToAttributes ) {
118
- if ($ params [0 ] instanceof CurlHandle && $ retVal instanceof CurlHandle) {
119
- /** @psalm-suppress PossiblyNullReference
120
- * @psalm-suppress PossiblyNullArgument
121
- */
122
- $ curlHandleToAttributes [$ retVal ] = $ curlHandleToAttributes [$ params [0 ]];
121
+ if (!($ params [0 ] instanceof CurlHandle && $ retVal instanceof CurlHandle)) {
122
+ self ::logDebug ('curl_copy_handle ' , ['retVal ' => $ retVal , 'params ' => $ params ]);
123
+
124
+ return ;
125
+ }
126
+
127
+ if (!isset ($ curlHandleToAttributes [$ params [0 ]])) {
128
+ self ::logDebug ('curl_copy_handle. Handle is not tracked ' , ['retVal ' => $ retVal , 'params ' => $ params ]);
129
+
130
+ return ;
123
131
}
132
+
133
+ $ curlHandleToAttributes [$ retVal ] = $ curlHandleToAttributes [$ params [0 ]];
124
134
}
125
135
);
126
136
@@ -143,51 +153,58 @@ public static function register(): void
143
153
return ;
144
154
}
145
155
146
- /** @psalm-suppress PossiblyNullReference */
147
- $ spanName = $ curlHandleToAttributes [$ params [0 ]]->getAttributes ()[TraceAttributes::HTTP_REQUEST_METHOD ] ?? 'curl_exec ' ;
156
+ $ spanName = 'curl_exec ' ;
157
+ $ attributes = [];
158
+
159
+ if (isset ($ curlHandleToAttributes [$ params [0 ]])) {
160
+ $ attributes = $ curlHandleToAttributes [$ params [0 ]]->getAttributes ();
161
+ $ spanName = $ attributes [TraceAttributes::HTTP_REQUEST_METHOD ] ?? $ spanName ;
162
+ } else {
163
+ self ::logDebug ('Curl handle is not tracked ' , ['params ' => $ params ]);
164
+ }
148
165
149
166
$ propagator = Globals::propagator ();
150
167
$ parent = Context::getCurrent ();
151
168
152
- /** @psalm-suppress PossiblyNullReference */
153
169
$ builder = $ instrumentation ->tracer ()
154
170
->spanBuilder ($ spanName )
155
171
->setParent ($ parent )
156
172
->setSpanKind (SpanKind::KIND_CLIENT )
157
173
->setAttribute (TraceAttributes::CODE_FUNCTION_NAME , $ function )
158
174
->setAttribute (TraceAttributes::CODE_FILE_PATH , $ filename )
159
175
->setAttribute (TraceAttributes::CODE_LINE_NUMBER , $ lineno )
160
- ->setAttributes ($ curlHandleToAttributes [ $ params [ 0 ]]-> getAttributes () );
176
+ ->setAttributes ($ attributes );
161
177
162
178
$ span = $ builder ->startSpan ();
163
179
$ context = $ span ->storeInContext ($ parent );
164
- $ propagator ->inject ($ curlHandleToAttributes [$ params [0 ]], HeadersPropagator::instance (), $ context );
180
+ if (isset ($ curlHandleToAttributes [$ params [0 ]])) {
181
+ $ propagator ->inject ($ curlHandleToAttributes [$ params [0 ]], HeadersPropagator::instance (), $ context );
182
+ }
165
183
166
184
Context::storage ()->attach ($ context );
167
185
168
- $ curlSetOptInstrumentationSuppressed = true ;
186
+ if (!isset ($ curlHandleToAttributes [$ params [0 ]])) {
187
+ return ;
188
+ }
169
189
170
- /** @psalm-suppress PossiblyNullReference */
190
+ $ curlSetOptInstrumentationSuppressed = true ;
171
191
$ headers = $ curlHandleToAttributes [$ params [0 ]]->getRequestHeadersToSend ();
172
192
if ($ headers ) {
173
193
curl_setopt ($ params [0 ], CURLOPT_HTTPHEADER , $ headers );
174
194
}
175
195
176
196
if (self ::isResponseHeadersCapturingEnabled ()) {
177
- /** @psalm-suppress PossiblyNullReference */
178
197
curl_setopt ($ params [0 ], CURLOPT_HEADERFUNCTION , $ curlHandleToAttributes [$ params [0 ]]->getResponseHeaderCaptureFunction ());
179
198
}
180
199
181
200
if (self ::isRequestHeadersCapturingEnabled ()) {
182
- /** @psalm-suppress PossiblyNullReference */
183
201
if (!$ curlHandleToAttributes [$ params [0 ]]->isVerboseEnabled ()) { // we let go of captuing request headers because CURLINFO_HEADER_OUT is disabling CURLOPT_VERBOSE
184
202
curl_setopt ($ params [0 ], CURLINFO_HEADER_OUT , true );
203
+ } else {
204
+ self ::logDebug ('Request headers won \'t be captured because verbose mode is disabled ' , ['params ' => $ params ]);
185
205
}
186
- //TODO log?
187
-
188
206
}
189
207
$ curlSetOptInstrumentationSuppressed = false ;
190
-
191
208
},
192
209
post: static function ($ obj , array $ params , mixed $ retVal ) use ($ curlHandleToAttributes ) {
193
210
if (!($ params [0 ] instanceof CurlHandle)) {
@@ -213,12 +230,15 @@ public static function register(): void
213
230
$ span ->setAttribute (TraceAttributes::ERROR_TYPE , 'cURL error ( ' . $ errno . ') ' );
214
231
}
215
232
216
- /** @psalm-suppress PossiblyNullReference */
217
- $ capturedHeaders = $ curlHandleToAttributes [$ params [0 ]]->getCapturedResponseHeaders ();
218
- foreach (self ::getResponseHeadersToCapture () as $ headerToCapture ) {
219
- if (($ value = $ capturedHeaders [strtolower ($ headerToCapture )] ?? null ) != null ) {
220
- $ span ->setAttribute (sprintf ('http.response.header.%s ' , strtolower (string: $ headerToCapture )), $ value );
233
+ if (isset ($ curlHandleToAttributes [$ params [0 ]])) {
234
+ $ capturedHeaders = $ curlHandleToAttributes [$ params [0 ]]->getCapturedResponseHeaders ();
235
+ foreach (self ::getResponseHeadersToCapture () as $ headerToCapture ) {
236
+ if (($ value = $ capturedHeaders [strtolower ($ headerToCapture )] ?? null ) != null ) {
237
+ $ span ->setAttribute (sprintf ('http.response.header.%s ' , strtolower (string: $ headerToCapture )), $ value );
238
+ }
221
239
}
240
+ } else {
241
+ self ::logDebug ('Curl handle is not tracked ' , ['params ' => $ params ]);
222
242
}
223
243
224
244
$ span ->end ();
0 commit comments