1+ <?php
2+
3+ namespace App \Http \Middleware ;
4+
5+ use Closure ;
6+ use Illuminate \Http \Request ;
7+ use Symfony \Component \HttpFoundation \Response ;
8+ use Keepsuit \LaravelOpenTelemetry \Facades \Tracer ;
9+ use Illuminate \Log \LogManager ;
10+ use OpenTelemetry \API \Baggage \Baggage ;
11+ use OpenTelemetry \Context \ScopeInterface ;
12+
13+ class TrackRequestMiddleware
14+ {
15+ private const ATTRIBUTE_START_TIME = '_start_time ' ;
16+ private const EVENT_REQUEST_STARTED = 'request.started ' ;
17+ private const EVENT_REQUEST_FINISHED = 'request.finished ' ;
18+
19+ protected LogManager $ logger ;
20+ private ?ScopeInterface $ baggageScope = null ;
21+ private bool $ shouldTrack ;
22+
23+ public function __construct (LogManager $ logger )
24+ {
25+ $ this ->logger = $ logger ;
26+ $ this ->shouldTrack = env ('OTEL_SERVICE_ENABLED ' , false );
27+ }
28+
29+ public function handle (Request $ request , Closure $ next )
30+ {
31+ if (!$ this ->shouldTrack ) {
32+ return $ next ($ request );
33+ }
34+
35+ try {
36+ $ request ->attributes ->set (self ::ATTRIBUTE_START_TIME , microtime (true ));
37+ if ($ span = Tracer::activeSpan ()) {
38+ if ($ ray = $ request ->header ('cf-ray ' )) {
39+ $ span ->setAttribute ('cloudflare.cf-ray ' , $ ray );
40+
41+ $ baggage = Baggage::getCurrent ()
42+ ->toBuilder ()
43+ ->set ('cf-ray ' , $ ray )
44+ ->set ('user_agent ' , substr ($ request ->userAgent () ?? 'unknown ' , 0 , 100 ))
45+ ->build ();
46+
47+ $ this ->baggageScope = $ baggage ->activate ();
48+ }
49+
50+ $ span ->addEvent (self ::EVENT_REQUEST_STARTED , [
51+ 'method ' => $ request ->method (),
52+ 'url ' => $ request ->fullUrl (),
53+ ]);
54+ }
55+ } catch (\Throwable $ e ) {
56+ $ this ->logger ->channel ('daily ' )->error ("Error on request tracking: " . $ e ->getMessage ());
57+ }
58+
59+ return $ next ($ request );
60+ }
61+
62+ public function terminate (Request $ request , Response $ response ): void
63+ {
64+ if (!$ this ->shouldTrack ) {
65+ return ;
66+ }
67+
68+ try {
69+ $ start = (float ) $ request ->attributes ->get (self ::ATTRIBUTE_START_TIME , microtime (true ));
70+ $ ms = (int ) ((microtime (true ) - $ start ) * 1000 );
71+
72+ if ($ span = Tracer::activeSpan ()) {
73+ $ span ->setAttribute ('app.response_ms ' , $ ms );
74+ $ span ->setAttribute ('http.status_code ' , $ response ->getStatusCode ());
75+ $ span ->addEvent (self ::EVENT_REQUEST_FINISHED , ['response_ms ' => $ ms ]);
76+ }
77+ } catch (\Throwable $ e ) {
78+ $ this ->logger ->channel ('daily ' )->error ("Error on request tracking: " . $ e ->getMessage ());
79+ } finally {
80+ if ($ this ->baggageScope ) {
81+ $ this ->baggageScope ->detach ();
82+ $ this ->baggageScope = null ;
83+ }
84+ }
85+ }
86+ }
0 commit comments