dd-trace-php icon indicating copy to clipboard operation
dd-trace-php copied to clipboard

Support CurlHttpClient

Open Firtzberg opened this issue 3 years ago • 6 comments

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.

Firtzberg avatar Jul 14 '21 17:07 Firtzberg

Ping

Firtzberg avatar Jul 29 '21 20:07 Firtzberg

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.

labbati avatar Aug 02 '21 11:08 labbati

Hello! I cannot see any traces on my end with CurlHttpClient from Symfony. Am I missing something?

B-Galati avatar Jan 26 '22 19:01 B-Galati

Related to https://github.com/DataDog/dd-trace-php/issues/1156

rmikalkenas avatar Mar 07 '22 11:03 rmikalkenas

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

B-Galati avatar Apr 05 '23 09:04 B-Galati

Isn't that issue fixed now that multi curl is supported?

B-Galati avatar Dec 20 '23 12:12 B-Galati

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 avatar Mar 28 '24 15:03 B-Galati

@B-Galati Thanks, good call out, then we can close this issue :-)

bwoebi avatar Mar 28 '24 15:03 bwoebi