Issues (22)

src/Utils/SpansCreator.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * Spans creator
4
 * User: moyo
5
 * Date: 19/12/2017
6
 * Time: 4:52 PM
7
 */
8
9
namespace Carno\Tracing\Utils;
10
11
use Carno\Container\DI;
12
use Carno\Coroutine\Context;
13
use Carno\Promise\Promised;
14
use Carno\Tracing\Chips\Timestamp;
15
use Carno\Tracing\Contracts\Platform;
16
use Carno\Tracing\Contracts\Vars\CTX;
17
use Carno\Tracing\Contracts\Vars\FMT;
18
use Carno\Tracing\Contracts\Vars\LOG;
19
use Carno\Tracing\Contracts\Vars\TAG;
20
use Carno\Tracing\Standard\Span;
21
use Carno\Tracing\Standard\Tracer;
22
use OpenTracing\Exceptions\SpanContextNotFound;
23
use OpenTracing\SpanContext;
24
use OpenTracing\SpanOptions;
25
use Throwable;
26
27
trait SpansCreator
28
{
29
    use Timestamp;
30
31
    /**
32
     * @return bool
33
     */
34
    protected function traced() : bool
35
    {
36
        /**
37
         * @var Platform $platform
38
         */
39
40
        if (DI::has(Platform::class) && $platform = DI::get(Platform::class)) {
41
            return $platform->joined();
42
        }
43
44
        return false;
45
    }
46
47
    /**
48
     * @param Context $context
49
     * @param string $name
50
     * @param array $tags
51
     * @param array $log
52
     * @param string $exaFormat
53
     * @param mixed $exaCarrier
54
     * @param SpanContext $exaContext
55
     * @param Platform $platform
56
     * @param int $timestamp
57
     */
58
    protected function newSpan(
59
        Context $context,
60
        string $name,
61
        array $tags = [],
62
        array $log = [],
63
        string $exaFormat = null,
64
        $exaCarrier = null,
65
        SpanContext $exaContext = null,
66
        Platform $platform = null,
67
        int $timestamp = null
68
    ) : void {
69
        if (is_null($platform)) {
70
            if (DI::has(Platform::class)) {
71
                $platform = DI::get(Platform::class);
72
            } else {
73
                // missing platform support
74
                return;
75
            }
76
        }
77
78
        // check platform is ready
79
        if (!$platform->joined()) {
80
            return;
81
        }
82
83
        // get/set tracer
84
        if ($context->has(CTX::G_TRACER)) {
85
            $tracer = $context->get(CTX::G_TRACER);
86
        } else {
87
            $context->set(CTX::G_TRACER, $tracer = new Tracer($platform));
88
        }
89
90
        // options
91
        $options = [
92
            'start_time' => $timestamp ?? $this->microseconds(),
93
            'tags' => array_merge($platform->env()->tags(), $tags),
94
        ];
95
96
        // inherit from root
97
        if (is_null($exaFormat) && $context->has(CTX::G_ROOT)) {
98
            $exaFormat = FMT::PREV_CTX;
99
            $exaCarrier = $context->get(CTX::G_ROOT);
100
        }
101
102
        // extracting
103
        if ($exaFormat) {
104
            try {
105
                // check reference
106
                if ($exaContext) {
107
                    $tracer->inject($exaContext, $exaFormat, $exaCarrier);
108
                    $options['child_of'] = $exaContext;
109
                } else {
110
                    $options['child_of'] = $tracer->extract($exaFormat, $exaCarrier);
111
                }
112
            } catch (SpanContextNotFound $e) {
113
                // root span
114
            }
115
        }
116
117
        // is root
118
        $root = ! $context->has(CTX::G_SPAN);
119
120
        // new span
121
        $context->set(CTX::G_SPAN, $span = $tracer->startSpan($name, SpanOptions::create($options)));
122
123
        // root ctx
124
        $root && $context->set(CTX::G_ROOT, $span->getContext());
125
126
        // some log
127
        $span->log($log);
128
    }
129
130
    /**
131
     * @param Promised $finished
132
     * @param Context $traced
133
     * @return Promised
134
     */
135
    protected function finishSpan(Promised $finished, Context $traced = null) : Promised
136
    {
137
        $traced && $finished->then(function () use ($traced) {
138
            $this->closeSpan($traced);
139
        }, function (Throwable $e) use ($traced) {
140
            $this->errorSpan($traced, $e);
141
        });
142
        return $finished;
143
    }
144
145
    /**
146
     * @param Context $context
147
     * @param array $tags
148
     * @param int $time
149
     */
150
    protected function closeSpan(Context $context, array $tags = [], int $time = null) : void
151
    {
152
        if ($context->has(CTX::G_SPAN)) {
153
            /**
154
             * @var Span $span
155
             */
156
            $span = $context->get(CTX::G_SPAN);
157
            $span->setTags($tags);
158
            $span->finish($time);
159
            $this->endingSpan($context);
160
        }
161
    }
162
163
    /**
164
     * @param Context $context
165
     * @param Throwable $err
166
     * @param array $tags
167
     * @param int $time
168
     */
169
    protected function errorSpan(Context $context, Throwable $err = null, array $tags = [], int $time = null) : void
170
    {
171
        if ($context->has(CTX::G_SPAN)) {
172
            /**
173
             * @var Span $span
174
             */
175
            $span = $context->get(CTX::G_SPAN);
176
            $span->setTags(array_merge([TAG::ERROR => true], $tags));
177
            $span->log([
178
                LOG::EVENT => TAG::ERROR,
179
                LOG::ERROR_KIND => get_class($err),
180
                LOG::ERROR_OBJECT => $err,
181
                LOG::MESSAGE => $err->getMessage(),
0 ignored issues
show
The method getMessage() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

181
                LOG::MESSAGE => $err->/** @scrutinizer ignore-call */ getMessage(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
182
                LOG::STACK => $err->getTraceAsString(),
183
            ]);
184
            $span->finish($time);
185
            $this->endingSpan($context);
186
        }
187
    }
188
189
    /**
190
     * @param Context $context
191
     */
192
    private function endingSpan(Context $context) : void
193
    {
194
        if ($context->has(CTX::G_TRACER)) {
195
            /**
196
             * @var Tracer $tracer
197
             */
198
            $tracer = $context->get(CTX::G_TRACER);
199
            $tracer->flush();
200
        }
201
    }
202
}
203