[HttpClient] logger integration#30537
Conversation
antonch1989
commented
Mar 12, 2019
| Q | A |
|---|---|
| Branch? | master |
| Bug fix? | no |
| New feature? | yes |
| BC breaks? | no |
| Deprecations? | no |
| Tests pass? | yes |
| Fixed tickets | #30502 |
| License | MIT |
| Doc PR |
nicolas-grekas
left a comment
There was a problem hiding this comment.
thanks for starting this, let's do something useful with the logger now :)
| * @see HttpClientInterface::OPTIONS_DEFAULTS for available options | ||
| */ | ||
| public function __construct(array $defaultOptions = [], int $maxHostConnections = 6) | ||
| public function __construct(LoggerInterface $logger = null, array $defaultOptions = [], int $maxHostConnections = 6) |
There was a problem hiding this comment.
This should be the last argument IMHO.
There was a problem hiding this comment.
That does make it harder to pass the default values properly (in case they change) on line 165: $this->multi->handle = (new self($this->logger))->multi->handle;
There was a problem hiding this comment.
True, what about something like $this->multi->handle = (clone $this)->multi->handle;, with any proper cloning handling if needed?
There was a problem hiding this comment.
We would then have to empty the clone
There was a problem hiding this comment.
What about putting the argument 2nd?
Looks best ordering to me, from most often passed to most often left to defaults.
There was a problem hiding this comment.
Alternatively: withLogger()
There was a problem hiding this comment.
Having it last in the constructor and/or using a mutator looks more legit, since from a strict object point of view, if we create it the most needed is to configure it. The logger is not a requirement for this client, this is obviously why we add it in this PR. I don't think we should break the previous implementation. Plus using a logger also surely means in most cases that DI is used and we don't care about having it third.
There was a problem hiding this comment.
Or it could implement Psr\Log\LoggerAwareInterface (adds a setLogger() method). This interface triggers the autoconfiguration in Symfony IIRC.
|
Not really a fan of having a logger inside the client implementation when it could use decoration, but really depends if you want to log what the implementation does. If it's only logging request / response transmission it should use a decoration system (or at least a trait but not a fan of this either). Using decorations would allow:
|
|
@joelwurtz same as #30539: logging in a cross-cutting concern, it's a bad fit for a middleware. I'd like implementation to log what they do internally also, e.g. dealing with redirections, or with server pushes for the |
nicolas-grekas
left a comment
There was a problem hiding this comment.
I'm fine with the adding as 2nd argument personally. We should now log some things :)
0d3acb4 to
63c48db
Compare
nicolas-grekas
left a comment
There was a problem hiding this comment.
(I pushed a 2nd commit with logs at critical points + fixes for HTTP/2 PUSH found meanwhile)
441caef to
4314e82
Compare
4314e82 to
26d15c8
Compare
|
Thank you @antonch1989. |
…grekas) This PR was merged into the 4.3-dev branch. Discussion ---------- [HttpClient] logger integration | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? | no | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | #30502 <!-- #-prefixed issue number(s), if any --> | License | MIT | Doc PR | Commits ------- 26d15c8 [HttpClient] log requests, responses and pushes when they happen fc6ba7e [HttpClient] logger integration
lyrixx
left a comment
There was a problem hiding this comment.
Sorry, I came late But I think this could increase the DX. I could do the PR if you want
|
|
||
| curl_multi_setopt($mh, CURLMOPT_PUSHFUNCTION, static function ($parent, $pushed, array $requestHeaders) use ($multi) { | ||
| return self::handlePush($parent, $pushed, $requestHeaders, $multi); | ||
| $logger = &$this->logger; |
There was a problem hiding this comment.
- Why do you use a reference here ?
- There is no need to create a logger variable here since we can use $this in a close since PHP 5.5 IIRC)
| ]; | ||
|
|
||
| if ('GET' === $method && !$options['body'] && $expectedHeaders === $pushedHeaders) { | ||
| $this->logger && $this->logger->info(sprintf('Connecting request to pushed response: %s %s', $method, $url)); |
There was a problem hiding this comment.
- I would use quote around
%s(to detect empty method or empty URL for exemple) - I would move this to debug log level
| return $pushedResponse; | ||
| } | ||
|
|
||
| $this->logger && $this->logger->info(sprintf('Rejecting pushed response for "%s": authorization headers don\'t match the request', $url)); |
There was a problem hiding this comment.
I would move that to warning log level
| $this->logger && $this->logger->info(sprintf('Rejecting pushed response for "%s": authorization headers don\'t match the request', $url)); | ||
| } | ||
|
|
||
| $this->logger && $this->logger->info(sprintf('Request: %s %s', $method, $url)); |
There was a problem hiding this comment.
I would use quote around %s (to detect empty method or empty URL for exemple)
|
|
||
| if ('GET' !== $headers[':method'] || isset($headers['range'])) { | ||
| if (!isset($headers[':method']) || !isset($headers[':scheme']) || !isset($headers[':authority']) || !isset($headers[':path']) || 'GET' !== $headers[':method'] || isset($headers['range'])) { | ||
| $logger && $logger->info(sprintf('Rejecting pushed response from "%s": pushed headers are invalid', $origin)); |
|
|
||
| return new NativeResponse($this->multi, $context, implode('', $url), $options, $gzipEnabled, $info, $resolveRedirect, $onProgress); | ||
| $url = implode('', $url); | ||
| $this->logger && $this->logger->info(sprintf('Request: %s %s', $method, $url)); |
| if (!$this->multi->openHandles) { | ||
| if ($this->logger) { | ||
| foreach ($this->multi->pushedResponses as $url => $response) { | ||
| $this->logger->info(sprintf('Unused pushed response: %s', $url)); |
|
|
||
| curl_setopt($ch, CURLOPT_PRIVATE, 'content'); | ||
| } elseif (null !== $info['redirect_url'] && $logger) { | ||
| $logger->info(sprintf('Redirecting: %s %s', $info['http_code'], $info['redirect_url'])); |
| break; | ||
| } | ||
|
|
||
| $this->logger && $this->logger->info(sprintf('Redirecting: %s %s', $this->info['http_code'], $url ?? $this->url)); |
| $isTimeout = true; | ||
| } elseif ($chunk instanceof FirstChunk && $response->logger) { | ||
| $info = $response->getInfo(); | ||
| $response->logger->info(sprintf('Response: %s %s', $info['http_code'], $info['url'])); |
|
See #30873 |
|
Who broke framework bundle? in vendor/symfony/framework-bundle/Resources/config/http_client.xml:13: <call method="setLogger">
<argument type="service" id="logger" on-invalid="ignore" />
</call> |
|
How did you produce this error? I doesn't look legit to me. |
|
I'm using 4.3.x-dev version, updated via composer update and got this error when loading my page. This is what was upgraded: - Removing symfony/cache (dev-master e5e9a6d)
- Installing symfony/cache (dev-master 7963e63): Loading from cache
- Removing symfony/contracts (dev-master 99c0737)
- Installing symfony/contracts (dev-master a4b5e69): Loading from cache
- Removing symfony/dependency-injection (dev-master 0d69ef5)
- Installing symfony/dependency-injection (dev-master c5fd454): Loading from cache
- Removing symfony/event-dispatcher (dev-master d3fe4ea)
- Installing symfony/event-dispatcher (dev-master 96212e1): Loading from cache
- Removing symfony/framework-bundle (dev-master cb79b7e)
- Installing symfony/framework-bundle (dev-master 8c262ff): Loading from cache
- Removing symfony/http-client (dev-master e6ea6d6)
- Installing symfony/http-client (dev-master 39fedf1): Loading from cache
- Removing symfony/http-foundation (dev-master bd824ed)
- Installing symfony/http-foundation (dev-master 62b6e8c): Loading from cache
- Removing symfony/http-kernel (dev-master cb89321)
- Installing symfony/http-kernel (dev-master 8d51d21): Loading from cache
- Removing symfony/security-bundle (dev-master 4f84238)
- Installing symfony/security-bundle (dev-master b36fe26): Loading from cache
- Removing symfony/twig-bundle (dev-master 3d669e5)
- Installing symfony/twig-bundle (dev-master 181d351): Loading from cache |
|
Thanks. What's the stack trace of the exception? |
|
|
Thanks, would you mind opening a separate issue with that content? |