| 1 |
<?php |
| 2 |
|
| 3 |
declare (strict_types=1); |
| 4 |
namespace WCPOS\Vendor\Sentry\Tracing; |
| 5 |
|
| 6 |
use WCPOS\Vendor\GuzzleHttp\Exception\RequestException as GuzzleRequestException; |
| 7 |
use WCPOS\Vendor\GuzzleHttp\Psr7\Uri; |
| 8 |
use WCPOS\Vendor\Psr\Http\Message\RequestInterface; |
| 9 |
use WCPOS\Vendor\Psr\Http\Message\ResponseInterface; |
| 10 |
use WCPOS\Vendor\Sentry\Breadcrumb; |
| 11 |
use WCPOS\Vendor\Sentry\ClientInterface; |
| 12 |
use WCPOS\Vendor\Sentry\SentrySdk; |
| 13 |
use WCPOS\Vendor\Sentry\State\HubInterface; |
| 14 |
use function WCPOS\Vendor\Sentry\getBaggage; |
| 15 |
use function WCPOS\Vendor\Sentry\getTraceparent; |
| 16 |
/** |
| 17 |
* This handler traces each outgoing HTTP request by recording performance data. |
| 18 |
*/ |
| 19 |
final class GuzzleTracingMiddleware |
| 20 |
{ |
| 21 |
public static function trace(?HubInterface $hub = null) : \Closure |
| 22 |
{ |
| 23 |
return static function (callable $handler) use($hub) : \Closure { |
| 24 |
return static function (RequestInterface $request, array $options) use($hub, $handler) { |
| 25 |
$hub = $hub ?? SentrySdk::getCurrentHub(); |
| 26 |
$client = $hub->getClient(); |
| 27 |
$parentSpan = $hub->getSpan(); |
| 28 |
$partialUri = Uri::fromParts(['scheme' => $request->getUri()->getScheme(), 'host' => $request->getUri()->getHost(), 'port' => $request->getUri()->getPort(), 'path' => $request->getUri()->getPath()]); |
| 29 |
$spanAndBreadcrumbData = ['http.request.method' => $request->getMethod(), 'http.request.body.size' => $request->getBody()->getSize()]; |
| 30 |
if ($request->getUri()->getQuery() !== '') { |
| 31 |
$spanAndBreadcrumbData['http.query'] = $request->getUri()->getQuery(); |
| 32 |
} |
| 33 |
if ($request->getUri()->getFragment() !== '') { |
| 34 |
$spanAndBreadcrumbData['http.fragment'] = $request->getUri()->getFragment(); |
| 35 |
} |
| 36 |
$childSpan = null; |
| 37 |
if ($parentSpan !== null && $parentSpan->getSampled()) { |
| 38 |
$spanContext = new SpanContext(); |
| 39 |
$spanContext->setOp('http.client'); |
| 40 |
$spanContext->setData($spanAndBreadcrumbData); |
| 41 |
$spanContext->setOrigin('auto.http.guzzle'); |
| 42 |
$spanContext->setDescription($request->getMethod() . ' ' . $partialUri); |
| 43 |
$childSpan = $parentSpan->startChild($spanContext); |
| 44 |
$hub->setSpan($childSpan); |
| 45 |
} |
| 46 |
if (self::shouldAttachTracingHeaders($client, $request)) { |
| 47 |
$traceParent = getTraceparent(); |
| 48 |
if ($traceParent !== '') { |
| 49 |
$request = $request->withHeader('sentry-trace', $traceParent); |
| 50 |
} |
| 51 |
$baggage = getBaggage(); |
| 52 |
if ($baggage !== '') { |
| 53 |
$request = $request->withHeader('baggage', $baggage); |
| 54 |
} |
| 55 |
} |
| 56 |
$handlerPromiseCallback = static function ($responseOrException) use($hub, $spanAndBreadcrumbData, $childSpan, $parentSpan, $partialUri) { |
| 57 |
if ($childSpan !== null) { |
| 58 |
// We finish the span (which means setting the span end timestamp) first to ensure the measured time |
| 59 |
// the span spans is as close to only the HTTP request time and do the data collection afterwards |
| 60 |
$childSpan->finish(); |
| 61 |
$hub->setSpan($parentSpan); |
| 62 |
} |
| 63 |
$response = null; |
| 64 |
if ($responseOrException instanceof ResponseInterface) { |
| 65 |
$response = $responseOrException; |
| 66 |
} elseif ($responseOrException instanceof GuzzleRequestException && \method_exists($responseOrException, 'getResponse')) { |
| 67 |
$response = $responseOrException->getResponse(); |
| 68 |
} |
| 69 |
$breadcrumbLevel = Breadcrumb::LEVEL_INFO; |
| 70 |
if ($response !== null) { |
| 71 |
$spanAndBreadcrumbData['http.response.body.size'] = $response->getBody()->getSize(); |
| 72 |
$spanAndBreadcrumbData['http.response.status_code'] = $response->getStatusCode(); |
| 73 |
if ($response->getStatusCode() >= 400 && $response->getStatusCode() < 500) { |
| 74 |
$breadcrumbLevel = Breadcrumb::LEVEL_WARNING; |
| 75 |
} elseif ($response->getStatusCode() >= 500) { |
| 76 |
$breadcrumbLevel = Breadcrumb::LEVEL_ERROR; |
| 77 |
} |
| 78 |
} |
| 79 |
if ($childSpan !== null) { |
| 80 |
if ($response !== null) { |
| 81 |
$childSpan->setStatus(SpanStatus::createFromHttpStatusCode($response->getStatusCode())); |
| 82 |
$childSpan->setData($spanAndBreadcrumbData); |
| 83 |
} else { |
| 84 |
$childSpan->setStatus(SpanStatus::internalError()); |
| 85 |
} |
| 86 |
} |
| 87 |
$hub->addBreadcrumb(new Breadcrumb($breadcrumbLevel, Breadcrumb::TYPE_HTTP, 'http', null, \array_merge(['url' => (string) $partialUri], $spanAndBreadcrumbData))); |
| 88 |
if ($responseOrException instanceof \Throwable) { |
| 89 |
throw $responseOrException; |
| 90 |
} |
| 91 |
return $responseOrException; |
| 92 |
}; |
| 93 |
return $handler($request, $options)->then($handlerPromiseCallback, $handlerPromiseCallback); |
| 94 |
}; |
| 95 |
}; |
| 96 |
} |
| 97 |
private static function shouldAttachTracingHeaders(?ClientInterface $client, RequestInterface $request) : bool |
| 98 |
{ |
| 99 |
if ($client === null) { |
| 100 |
return \false; |
| 101 |
} |
| 102 |
$sdkOptions = $client->getOptions(); |
| 103 |
// Check if the request destination is allow listed in the trace_propagation_targets option. |
| 104 |
return $sdkOptions->getTracePropagationTargets() === null || \in_array($request->getUri()->getHost(), $sdkOptions->getTracePropagationTargets()); |
| 105 |
} |
| 106 |
} |
| 107 |
|