SpansCreator::newSpan()   B
last analyzed

Complexity

Conditions 11
Paths 99

Size

Total Lines 70
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 29
c 2
b 0
f 1
dl 0
loc 70
rs 7.3166
cc 11
nc 99
nop 9

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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
Bug introduced by
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