-
Notifications
You must be signed in to change notification settings - Fork 59
/
Copy pathMiddleware.php
100 lines (83 loc) · 3.05 KB
/
Middleware.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?php
declare(strict_types=1);
namespace Zipkin\Instrumentation\Http\Server\Psr15;
use Zipkin\Tracer;
use Zipkin\SpanCustomizerShield;
use Zipkin\Span;
use Zipkin\Propagation\TraceContext;
use Zipkin\Propagation\SamplingFlags;
use Zipkin\Propagation\DefaultSamplingFlags;
use Zipkin\Kind;
use Zipkin\Instrumentation\Http\Server\Request as ServerRequest;
use Zipkin\Instrumentation\Http\Server\Psr15\Propagation\RequestHeaders;
use Zipkin\Instrumentation\Http\Server\HttpServerTracing;
use Zipkin\Instrumentation\Http\Server\HttpServerParser;
use Throwable;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;
final class Middleware implements MiddlewareInterface
{
private Tracer $tracer;
/**
* @var callable(ServerRequestInterface):SamplingFlags
*/
private $extractor;
private HttpServerParser $parser;
/**
* @var (callable(ServerRequest):?bool)|null
*/
private $requestSampler;
public function __construct(HttpServerTracing $tracing)
{
$this->tracer = $tracing->getTracing()->getTracer();
$this->extractor = $tracing->getTracing()->getPropagation()->getExtractor(new RequestHeaders());
$this->parser = $tracing->getParser();
$this->requestSampler = $tracing->getRequestSampler();
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$extractedContext = ($this->extractor)($request);
$span = $this->nextSpan($extractedContext, $request);
$scopeCloser = $this->tracer->openScope($span);
if ($span->isNoop()) {
try {
return $handler->handle($request);
} finally {
$span->finish();
$scopeCloser();
}
}
$parsedRequest = new Request($request);
$span->setKind(Kind\SERVER);
$spanCustomizer = new SpanCustomizerShield($span);
$this->parser->request($parsedRequest, $span->getContext(), $spanCustomizer);
try {
$response = $handler->handle($request);
$this->parser->response(new Response($response, $parsedRequest), $span->getContext(), $spanCustomizer);
return $response;
} catch (Throwable $e) {
$span->setError($e);
throw $e;
} finally {
$span->finish();
$scopeCloser();
}
}
private function nextSpan(?SamplingFlags $extractedContext, ServerRequestInterface $request): Span
{
if ($extractedContext instanceof TraceContext) {
return $this->tracer->joinSpan($extractedContext);
}
$extractedContext ??= DefaultSamplingFlags::createAsEmpty();
if ($this->requestSampler === null) {
return $this->tracer->nextSpan($extractedContext);
}
return $this->tracer->nextSpanWithSampler(
$this->requestSampler,
[$request],
$extractedContext
);
}
}