88use Http \Client \HttpClient ;
99use Psr \Http \Message \RequestInterface ;
1010use Psr \Http \Message \ResponseInterface ;
11+ use Symfony \Component \Stopwatch \Stopwatch ;
12+ use Symfony \Component \Stopwatch \StopwatchEvent ;
1113
1214/**
1315 * The ProfileClient decorates any client that implement both HttpClient and HttpAsyncClient interfaces to gather target
@@ -34,13 +36,24 @@ class ProfileClient implements HttpClient, HttpAsyncClient
3436 */
3537 private $ formatter ;
3638
39+ /**
40+ * @var Stopwatch
41+ */
42+ private $ stopwatch ;
43+
44+ /**
45+ * @var array
46+ */
47+ private $ eventNames = [];
48+
3749 /**
3850 * @param HttpClient|HttpAsyncClient $client The client to profile. Client must implement both HttpClient and
3951 * HttpAsyncClient interfaces.
4052 * @param Collector $collector
4153 * @param Formatter $formatter
54+ * @param Stopwatch $stopwatch
4255 */
43- public function __construct ($ client , Collector $ collector , Formatter $ formatter )
56+ public function __construct ($ client , Collector $ collector , Formatter $ formatter, Stopwatch $ stopwatch )
4457 {
4558 if (!($ client instanceof HttpClient && $ client instanceof HttpAsyncClient)) {
4659 throw new \RuntimeException (sprintf (
@@ -54,6 +67,7 @@ public function __construct($client, Collector $collector, Formatter $formatter)
5467 $ this ->client = $ client ;
5568 $ this ->collector = $ collector ;
5669 $ this ->formatter = $ formatter ;
70+ $ this ->stopwatch = $ stopwatch ;
5771 }
5872
5973 /**
@@ -63,16 +77,21 @@ public function sendAsyncRequest(RequestInterface $request)
6377 {
6478 $ stack = $ this ->collector ->getCurrentStack ();
6579 $ this ->collectRequestInformations ($ request , $ stack );
80+ $ event = $ this ->stopwatch ->start ($ this ->getStopwatchEventName ($ request ));
6681
67- return $ this ->client ->sendAsyncRequest ($ request )->then (function (ResponseInterface $ response ) use ($ stack ) {
68- $ this ->collectResponseInformations ($ response , $ stack );
82+ return $ this ->client ->sendAsyncRequest ($ request )->then (
83+ function (ResponseInterface $ response ) use ($ event , $ stack ) {
84+ $ event ->stop ();
85+ $ this ->collectResponseInformations ($ response , $ event , $ stack );
6986
70- return $ response ;
71- }, function (\Exception $ exception ) use ($ stack ) {
72- $ this ->collectExceptionInformations ($ exception , $ stack );
87+ return $ response ;
88+ }, function (\Exception $ exception ) use ($ event , $ stack ) {
89+ $ event ->stop ();
90+ $ this ->collectExceptionInformations ($ exception , $ event , $ stack );
7391
74- throw $ exception ;
75- });
92+ throw $ exception ;
93+ }
94+ );
7695 }
7796
7897 /**
@@ -82,15 +101,18 @@ public function sendRequest(RequestInterface $request)
82101 {
83102 $ stack = $ this ->collector ->getCurrentStack ();
84103 $ this ->collectRequestInformations ($ request , $ stack );
104+ $ event = $ this ->stopwatch ->start ($ this ->getStopwatchEventName ($ request ));
85105
86106 try {
87107 $ response = $ this ->client ->sendRequest ($ request );
108+ $ event ->stop ();
88109
89- $ this ->collectResponseInformations ($ response , $ stack );
110+ $ this ->collectResponseInformations ($ response , $ event , $ stack );
90111
91112 return $ response ;
92113 } catch (\Exception $ e ) {
93- $ this ->collectExceptionInformations ($ e , $ stack );
114+ $ event ->stop ();
115+ $ this ->collectExceptionInformations ($ e , $ event , $ stack );
94116
95117 throw $ e ;
96118 }
@@ -115,32 +137,56 @@ private function collectRequestInformations(RequestInterface $request, Stack $st
115137
116138 /**
117139 * @param ResponseInterface $response
140+ * @param StopwatchEvent $event
118141 * @param Stack|null $stack
119142 */
120- private function collectResponseInformations (ResponseInterface $ response , Stack $ stack = null )
143+ private function collectResponseInformations (ResponseInterface $ response , StopwatchEvent $ event , Stack $ stack = null )
121144 {
122145 if (!$ stack ) {
123146 return ;
124147 }
125148
149+ $ stack ->setDuration ($ event ->getDuration ());
126150 $ stack ->setResponseCode ($ response ->getStatusCode ());
127151 $ stack ->setClientResponse ($ this ->formatter ->formatResponse ($ response ));
128152 }
129153
130154 /**
131- * @param \Exception $exception
132- * @param Stack|null $stack
155+ * @param \Exception $exception
156+ * @param StopwatchEvent $event
157+ * @param Stack|null $stack
133158 */
134- private function collectExceptionInformations (\Exception $ exception , Stack $ stack = null )
159+ private function collectExceptionInformations (\Exception $ exception , StopwatchEvent $ event , Stack $ stack = null )
135160 {
136161 if ($ exception instanceof HttpException) {
137- $ this ->collectResponseInformations ($ exception ->getResponse (), $ stack );
162+ $ this ->collectResponseInformations ($ exception ->getResponse (), $ event , $ stack );
138163 }
139164
140165 if (!$ stack ) {
141166 return ;
142167 }
143168
169+ $ stack ->setDuration ($ event ->getDuration ());
144170 $ stack ->setClientException ($ this ->formatter ->formatException ($ exception ));
145171 }
172+
173+ /**
174+ * Generates the event name.
175+ *
176+ * @param RequestInterface $request
177+ *
178+ * @return string
179+ */
180+ private function getStopwatchEventName (RequestInterface $ request )
181+ {
182+ $ name = sprintf ('%s %s ' , $ request ->getMethod (), $ request ->getUri ());
183+
184+ if (isset ($ this ->eventNames [$ name ])) {
185+ $ name .= sprintf (' [#%d] ' , ++$ this ->eventNames [$ name ]);
186+ } else {
187+ $ this ->eventNames [$ name ] = 1 ;
188+ }
189+
190+ return $ name ;
191+ }
146192}
0 commit comments