Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using the tracer instance from context, append Trace-Id to Response Header #6023

Merged
merged 7 commits into from
Aug 15, 2023

Conversation

huangdijia
Copy link
Member

@huangdijia huangdijia commented Aug 15, 2023

子协程里需要创建新的 tracer,在协程结束的时候执行 $tracer->flush(),防止 span 丢失或者在 finish 之前就被上报了。

#5003

创建子协程的时候需要处理一下。

<?php

declare(strict_types=1);

namespace App\Kernel\Context;

use App\Kernel\Log\AppendRequestIdProcessor;
use Hyperf\Context\Context;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Engine\Coroutine as Co;
use OpenTracing\Span;
use OpenTracing\Tracer;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Log\LoggerInterface;
use Sentry\SentrySdk;
use Throwable;

use function Hyperf\Support\call;
use function Hyperf\Support\make;

class Coroutine
{
    protected LoggerInterface $logger;

    public function __construct(protected ContainerInterface $container)
    {
        $this->logger = $container->get(StdoutLoggerInterface::class);
    }

    /**
     * @return int Returns the coroutine ID of the coroutine just created.
     *             Returns -1 when coroutine create failed.
     */
    public function create(callable $callable): int
    {
        $id = Co::id();
        $root = Context::get('tracer.root');

        $coroutine = Co::create(function () use ($callable, $id, $root) {
            try {
                // Shouldn't copy all contexts to avoid socket already been bound to another coroutine.
                Context::copy($id, [
                    AppendRequestIdProcessor::REQUEST_ID,
                    ServerRequestInterface::class,
                    SentrySdk::class,
                ]);

                // Tracer
                if ($root instanceof Span) {
                    /** @var Tracer $tracer */
                    $tracer = make(Tracer::class);
                    Context::set('tracer.tracer', $tracer);
                    $child = $tracer->startSpan('coroutine', [
                        'child_of' => $root->getContext(),
                    ]);
                    $child->setTag('coroutine.id', Co::id());
                    Context::set('tracer.root', $child);
                    Co::defer(function () use ($child, $tracer) {
                        $child->finish();
                        $tracer->flush();
                    });
                }

                call($callable);
            } catch (Throwable $throwable) {
                if (isset($child)) {
                    $child->setTag('error', true);
                    $child->log(['message', $throwable->getMessage(), 'code' => $throwable->getCode(), 'stacktrace' => $throwable->getTraceAsString()]);
                }
                $this->logger->warning((string) $throwable);
            }
        });

        try {
            return $coroutine->getId();
        } catch (Throwable $throwable) {
            $this->logger->warning((string) $throwable);
            return -1;
        }
    }
}

@huangdijia huangdijia changed the title Append Trace-Id to Response Header Allow using the tracer instance from context, append Trace-Id to Response Header Aug 15, 2023
@huangdijia huangdijia marked this pull request as ready for review August 15, 2023 08:28
@limingxinleo limingxinleo merged commit bcdb508 into hyperf:master Aug 15, 2023
53 checks passed
@huangdijia huangdijia deleted the trace-id branch August 15, 2023 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants