• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FriendsOfOpenTelemetry / opentelemetry-bundle / 24246572588

10 Apr 2026 01:57PM UTC coverage: 91.751% (+0.07%) from 91.68%
24246572588

Pull #211

github

web-flow
Merge ae31d73a6 into 19c774f8e
Pull Request #211: chore: remove Nix and replace with shivammathur/setup-php in CI

2280 of 2485 relevant lines covered (91.75%)

14.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.73
/src/Instrumentation/Symfony/HttpClient/TraceableHttpClient.php
1
<?php
2

3
namespace FriendsOfOpenTelemetry\OpenTelemetryBundle\Instrumentation\Symfony\HttpClient;
4

5
use OpenTelemetry\API\Trace\SpanKind;
6
use OpenTelemetry\API\Trace\TracerInterface;
7
use OpenTelemetry\Context\Context;
8
use OpenTelemetry\SemConv\Attributes\HttpAttributes;
9
use OpenTelemetry\SemConv\Attributes\UrlAttributes;
10
use Psr\Http\Message\UriFactoryInterface;
11
use Psr\Log\LoggerAwareInterface;
12
use Psr\Log\LoggerInterface;
13
use Symfony\Component\HttpClient\Response\ResponseStream;
14
use Symfony\Contracts\HttpClient\HttpClientInterface;
15
use Symfony\Contracts\HttpClient\ResponseInterface;
16
use Symfony\Contracts\HttpClient\ResponseStreamInterface;
17
use Symfony\Contracts\Service\ResetInterface;
18

19
final class TraceableHttpClient implements HttpClientInterface, LoggerAwareInterface, ResetInterface
20
{
21
    public function __construct(
22
        private HttpClientInterface $client,
23
        private readonly TracerInterface $tracer,
24
        private readonly UriFactoryInterface $uriFactory,
25
        private ?LoggerInterface $logger = null,
26
    ) {
27
    }
6✔
28

29
    /**
30
     * @param array<mixed> $options
31
     */
32
    public function request(string $method, string $url, array $options = []): ResponseInterface
33
    {
34
        $scope = Context::storage()->scope();
4✔
35
        if (null !== $scope) {
4✔
36
            $this->logger?->debug(sprintf('Using scope "%s"', spl_object_id($scope)));
×
37
        } else {
38
            $this->logger?->debug('No active scope');
4✔
39
        }
40

41
        $uri = $this->uriFactory->createUri($url);
4✔
42

43
        $spanBuilder = $this->tracer
4✔
44
            ->spanBuilder('http.client')
4✔
45
            ->setSpanKind(SpanKind::KIND_CLIENT)
4✔
46
            ->setParent($scope?->context())
4✔
47
            ->setAttribute(UrlAttributes::URL_FULL, $url)
4✔
48
            ->setAttribute(UrlAttributes::URL_SCHEME, $uri->getScheme())
4✔
49
            ->setAttribute(UrlAttributes::URL_PATH, $uri->getPath())
4✔
50
            ->setAttribute(UrlAttributes::URL_QUERY, $uri->getQuery())
4✔
51
            ->setAttribute(UrlAttributes::URL_FRAGMENT, $uri->getFragment())
4✔
52
            ->setAttribute(HttpAttributes::HTTP_REQUEST_METHOD, $method)
4✔
53
        ;
4✔
54

55
        $span = $spanBuilder->startSpan();
4✔
56

57
        $this->logger?->debug(sprintf('Starting span "%s"', $span->getContext()->getSpanId()));
4✔
58

59
        return new TraceableResponse($this->client, $this->client->request($method, $url, $options), $span);
4✔
60
    }
61

62
    public function stream(iterable|ResponseInterface $responses, ?float $timeout = null): ResponseStreamInterface
63
    {
64
        if ($responses instanceof TraceableResponse) {
1✔
65
            $responses = [$responses];
1✔
66
        } elseif (!is_iterable($responses)) {
×
67
            throw new \TypeError(sprintf('"%s()" expects parameter 1 to be an iterable of TraceableResponse objects, "%s" given.', __METHOD__, get_debug_type($responses)));
×
68
        }
69

70
        return new ResponseStream(TraceableResponse::stream($this->client, $responses, $timeout));
1✔
71
    }
72

73
    /**
74
     * @param array<mixed> $options
75
     */
76
    public function withOptions(array $options): static
77
    {
78
        $clone = clone $this;
×
79
        $clone->client = $this->client->withOptions($options);
×
80

81
        return $clone;
×
82
    }
83

84
    public function setLogger(LoggerInterface $logger): void
85
    {
86
        if ($this->client instanceof LoggerAwareInterface) {
×
87
            $this->client->setLogger($logger);
×
88
        }
89
        $this->logger = $logger;
×
90
    }
91

92
    public function reset(): void
93
    {
94
        if ($this->client instanceof ResetInterface) {
2✔
95
            $this->client->reset();
2✔
96
        }
97
    }
98
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc