dd-trace-php
dd-trace-php copied to clipboard
Support CurlHttpClient
First of all, DataDog is great! We have it integrated on several services, some of which communicate using guzzle, while others use Symfony's CurlHttpClient. We see traces involving multiple services when guzzle is used, but those using symfony don't get linked together. Before spending hours of investigation I would like to ask if CurlHttpClient is supposed to provide cross-service-tracing (add the corresponding headers) out of the box? We don't have a Symfony app, we just use the HTTP client. We set custom headers when making the request. I guess that shouldn't remove your headers.
Ping
Hello @Firtzberg! I missed this feature request, sorry for the late reply.
The issue here is not related to CurlHttpClient but by the fact it uses curl multi under the hoods.
Distributed tracing automatic injection works out of the box, tracing does not. This means that you will not see a curl
span but the two services will be connected.
We cannot commit to prioritize work to support CurlHttpClient
for tracing as well, but you are more than welcomed to contribute an integration.
Hello! I cannot see any traces on my end with CurlHttpClient from Symfony. Am I missing something?
Related to https://github.com/DataDog/dd-trace-php/issues/1156
If it can help, my company implement a custom support with this class:
<?php
use DDTrace\GlobalTracer;
use DDTrace\Tag;
use DDTrace\Type;
use Symfony\Component\HttpClient\AsyncDecoratorTrait;
use Symfony\Component\HttpClient\Response\AsyncContext;
use Symfony\Component\HttpClient\Response\AsyncResponse;
use Symfony\Contracts\HttpClient\ChunkInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
final class HttpClientTracer implements HttpClientInterface
{
use AsyncDecoratorTrait;
public function __construct(HttpClientInterface $decoratedClient)
{
$this->client = $decoratedClient;
}
/**
* {@inheritDoc}
*/
public function request(string $method, string $url, array $options = []): ResponseInterface
{
if (!\extension_loaded('ddtrace')) {
return new AsyncResponse($this->client, $method, $url, $options);
}
$scope = GlobalTracer::get()->startActiveSpan('symfony.http_client.request');
$span = $scope->getSpan();
$span->setTag(Tag::SPAN_TYPE, Type::HTTP_CLIENT);
$span->setTag(Tag::SERVICE_NAME, "some-service/http-client");
return new AsyncResponse(
$this->client,
$method,
$url,
$options,
function (ChunkInterface $chunk, AsyncContext $context) use ($url, $options, $scope, $span) {
yield $chunk;
if ($chunk->isLast()) {
/** @var string $url */
$url = $context->getInfo('url');
$span->setResource($options['extra']['trace_group'] ?? \Safe\parse_url($url, \PHP_URL_HOST));
$span->setError($context->getStatusCode() >= 400);
$span->setTag(Tag::HTTP_METHOD, $context->getInfo('http_method'));
$span->setTag(Tag::HTTP_STATUS_CODE, $context->getStatusCode());
$span->setTag(Tag::HTTP_URL, $url);
$span->setTag('http.total_time', $context->getInfo('total_time'));
$scope->close();
}
},
);
}
/**
* Ease adding trace group name on Symfony HTTP client options.
*
* @return array<string, mixed>
*/
public static function traceGroup(string $name, array $options = []): array
{
$options['extra']['trace_group'] = $name;
return $options;
}
}
And in services.yaml
:
HttpClientTracer:
decorates: http_client
Isn't that issue fixed now that multi curl is supported?
I confirm it's fixed by https://github.com/DataDog/dd-trace-php/pull/2347
At least it's working as expected for me thanks to multi_curl integration.
@B-Galati Thanks, good call out, then we can close this issue :-)