Test Failed
Push — main ( d01f4c...5af89f )
by Bingo
15:56
created

TelemetrySendingTask::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 8
dl 0
loc 18
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 8

How to fix   Many Parameters   

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
namespace Jabe\Engine\Impl\Telemetry\Reporter;
4
5
use GuzzleHttp\ClientInterface;
6
use Jabe\Engine\Impl\ProcessEngineLogger;
7
use Jabe\Engine\Impl\Cmd\IsTelemetryEnabledCmd;
8
use Jabe\Engine\Impl\Interceptor\CommandExecutorInterface;
9
use Jabe\Engine\Impl\Metrics\{
10
    Meter,
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Metrics\Meter was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
    MetricsRegistry
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Metrics\MetricsRegistry was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
};
13
use Jabe\Engine\Impl\Metrics\Util\{
14
    MetricsUtil
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Metrics\Util\MetricsUtil was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
};
16
use Jabe\Engine\Impl\Telemetry\{
17
    CommandCounter,
18
    TelemetryLogger,
19
    TelemetryRegistry
20
};
21
use Jabe\Engine\Impl\Telemetry\Dto\{
22
    ApplicationServerImpl,
23
    CommandImpl,
24
    TelemetryDataImpl,
25
    InternalsImpl,
26
    MetricImpl,
27
    ProductImpl
28
};
29
use Jabe\Engine\Impl\Util\{
30
    ConnectUtil,
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Util\ConnectUtil was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
    JsonUtil,
32
    StringUtil,
33
    TelemetryUtil
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Util\TelemetryUtil was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
34
};
35
use Jabe\Engine\Telemetry\{
36
    CommandInterface,
37
    MetricInterface
38
};
39
use Jabe\Engine\Impl\Util\Concurrent\{
40
    RunnableInterface,
41
    TimerTask
42
};
43
use Jabe\Engine\Impl\Util\Core\MediaType;
44
use Jabe\Engine\Impl\Util\Net\HttpURLConnection;
45
use Jabe\Engine\Management\Metrics;
46
47
class TelemetrySendingTask extends TimerTask
48
{
49
    protected const METRICS_TO_REPORT = [
50
        Metrics::ROOT_PROCESS_INSTANCE_START,
51
        Metrics::EXECUTED_DECISION_INSTANCES,
52
        Metrics::EXECUTED_DECISION_ELEMENTS,
53
        Metrics::ACTIVTY_INSTANCE_START
54
    ];
55
    //protected static final TelemetryLogger LOG = ProcessEngineLogger.TELEMETRY_LOGGER;
56
    protected const UUID4_PATTERN = "/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$/i";
57
58
    protected $commandExecutor;
59
    protected $telemetryEndpoint;
60
    protected $staticData;
61
    protected $httpConnector;
62
    protected $telemetryRequestRetries;
63
    protected $telemetryRegistry;
64
    protected $metricsRegistry;
65
    protected $telemetryRequestTimeout;
66
67
    public function __construct(
68
        CommandExecutorInterface $commandExecutor,
69
        string $telemetryEndpoint,
70
        int $telemetryRequestRetries,
71
        TelemetryDataImpl $data,
72
        ClientInterface $httpConnector,
73
        TelemetryRegistry $telemetryRegistry,
74
        MetricsRegistry $metricsRegistry,
75
        int $telemetryRequestTimeout
76
    ) {
77
        $this->commandExecutor = $commandExecutor;
78
        $this->telemetryEndpoint = $telemetryEndpoint;
79
        $this->telemetryRequestRetries = $telemetryRequestRetries;
80
        $this->staticData = $data;
81
        $this->httpConnector = $httpConnector;
82
        $this->telemetryRegistry = $telemetryRegistry;
83
        $this->metricsRegistry = $metricsRegistry;
84
        $this->telemetryRequestTimeout = $telemetryRequestTimeout;
85
    }
86
87
    public function run(): void
88
    {
89
        //LOG.startTelemetrySendingTask();
90
91
        if (!isTelemetryEnabled()) {
0 ignored issues
show
Bug introduced by
The function isTelemetryEnabled was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

91
        if (!/** @scrutinizer ignore-call */ isTelemetryEnabled()) {
Loading history...
92
            //LOG.telemetryDisabled();
93
            return;
94
        }
95
96
        TelemetryUtil::toggleLocalTelemetry(true, $this->telemetryRegistry, $this->metricsRegistry);
97
98
        $scope = $this;
99
        $this->performDataSend(new class ($scope) implements RunnableInterface {
100
            private $scope;
101
102
            public function __construct($scope)
103
            {
104
                $this->scope = $scope;
105
            }
106
107
            public function run(): void
108
            {
109
                $this->scope->updateAndSendData(true, true);
110
            }
111
        });
112
    }
113
114
    public function updateAndSendData(bool $sendData, bool $addLegacyNames): TelemetryDataImpl
115
    {
116
        $this->updateStaticData();
117
        $dynamicData = $this->resolveDynamicData($sendData, $addLegacyNames);
118
        $mergedData = new TelemetryDataImpl($staticData);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $staticData seems to be never defined.
Loading history...
119
        $mergedData->mergeInternals($dynamicData);
120
121
        if ($sendData) {
122
            try {
123
                $this->sendData($mergedData);
124
            } catch (\Exception $e) {
125
                // so that we send it again the next time
126
                $this->restoreDynamicData($dynamicData);
127
                throw $e;
128
            }
129
        }
130
        return $mergedData;
131
    }
132
133
    protected function updateStaticData(): void
134
    {
135
        $internals = $this->staticData->getProduct()->getInternals();
136
137
        if ($internals->getApplicationServer() == null) {
138
            $applicationServer = $telemetryRegistry->getApplicationServer();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $telemetryRegistry seems to be never defined.
Loading history...
139
            $internals->setApplicationServer($applicationServer);
0 ignored issues
show
Bug introduced by
The method setApplicationServer() does not exist on Jabe\Engine\Telemetry\InternalsInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Jabe\Engine\Telemetry\InternalsInterface. ( Ignorable by Annotation )

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

139
            $internals->/** @scrutinizer ignore-call */ 
140
                        setApplicationServer($applicationServer);
Loading history...
140
        }
141
142
        if ($internals->isTelemetryEnabled() == null) {
0 ignored issues
show
Bug introduced by
The method isTelemetryEnabled() does not exist on Jabe\Engine\Telemetry\InternalsInterface. ( Ignorable by Annotation )

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

142
        if ($internals->/** @scrutinizer ignore-call */ isTelemetryEnabled() == null) {

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...
143
            $internals->setTelemetryEnabled(true);// this can only be true, otherwise we would not collect data to send
0 ignored issues
show
Bug introduced by
The method setTelemetryEnabled() does not exist on Jabe\Engine\Telemetry\InternalsInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Jabe\Engine\Telemetry\InternalsInterface. ( Ignorable by Annotation )

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

143
            $internals->/** @scrutinizer ignore-call */ 
144
                        setTelemetryEnabled(true);// this can only be true, otherwise we would not collect data to send
Loading history...
144
        }
145
146
        // license key and Webapps data is fed from the outside to the registry but needs to be constantly updated
147
        $internals->setLicenseKey($telemetryRegistry->getLicenseKey());
0 ignored issues
show
Bug introduced by
The method setLicenseKey() does not exist on Jabe\Engine\Telemetry\InternalsInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Jabe\Engine\Telemetry\InternalsInterface. ( Ignorable by Annotation )

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

147
        $internals->/** @scrutinizer ignore-call */ 
148
                    setLicenseKey($telemetryRegistry->getLicenseKey());
Loading history...
148
        $internals->setWebapps($telemetryRegistry->getWebapps());
0 ignored issues
show
Bug introduced by
The method setWebapps() does not exist on Jabe\Engine\Telemetry\InternalsInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Jabe\Engine\Telemetry\InternalsInterface. ( Ignorable by Annotation )

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

148
        $internals->/** @scrutinizer ignore-call */ 
149
                    setWebapps($telemetryRegistry->getWebapps());
Loading history...
149
    }
150
151
    protected function isTelemetryEnabled(): bool
152
    {
153
        $telemetryEnabled = $this->commandExecutor->execute(new IsTelemetryEnabledCmd());
154
        return $telemetryEnabled != null && $telemetryEnabled->booleanValue();
155
    }
156
157
    protected function sendData(TelemetryDataImpl $dataToSend): void
158
    {
159
        $telemetryData = JsonUtil::asString($dataToSend);
0 ignored issues
show
Bug introduced by
$dataToSend of type Jabe\Engine\Impl\Telemetry\Dto\TelemetryDataImpl is incompatible with the type array|null expected by parameter $properties of Jabe\Engine\Impl\Util\JsonUtil::asString(). ( Ignorable by Annotation )

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

159
        $telemetryData = JsonUtil::asString(/** @scrutinizer ignore-type */ $dataToSend);
Loading history...
160
        $requestParams = ConnectUtil::assembleRequestParameters(
161
            ConnectUtil::METHOD_NAME_POST,
162
            $this->telemetryEndpoint,
163
            MediaType::APPLICATION_JSON,
164
            $telemetryData
165
        );
166
        $requestParams = ConnectUtil::addRequestTimeoutConfiguration($requestParams, $this->telemetryRequestTimeout);
167
168
        $response = $this->httpConnector->request(ConnectUtil::METHOD_NAME_POST, $this->telemetryEndpoint, $requestParams);
169
170
        if ($response == null) {
171
            //LOG.unexpectedResponseWhileSendingTelemetryData();
172
        } else {
173
            $responseCode = $response->getResponseParameter(ConnectUtil::PARAM_NAME_RESPONSE_STATUS_CODE);
0 ignored issues
show
Bug introduced by
The method getResponseParameter() does not exist on Psr\Http\Message\ResponseInterface. ( Ignorable by Annotation )

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

173
            /** @scrutinizer ignore-call */ 
174
            $responseCode = $response->getResponseParameter(ConnectUtil::PARAM_NAME_RESPONSE_STATUS_CODE);

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...
174
175
            if ($this->isSuccessStatusCode($responseCode)) {
176
                if ($responseCode != HttpURLConnection::HTTP_ACCEPTED) {
177
                    //LOG.unexpectedResponseSuccessCode(responseCode);
178
                }
179
                //LOG.telemetrySentSuccessfully();
180
            } else {
181
                //throw LOG.unexpectedResponseWhileSendingTelemetryData(responseCode);
182
            }
183
        }
184
    }
185
186
    /**
187
     * @return true if status code is 2xx
188
     */
189
    protected function isSuccessStatusCode(int $statusCode): bool
0 ignored issues
show
Unused Code introduced by
The parameter $statusCode is not used and could be removed. ( Ignorable by Annotation )

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

189
    protected function isSuccessStatusCode(/** @scrutinizer ignore-unused */ int $statusCode): bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
190
    {
191
        return ($this->statusCode / 100) == 2;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->statusCode / 100 == 2 returns the type boolean which is incompatible with the documented return type true.
Loading history...
Bug Best Practice introduced by
The property statusCode does not exist on Jabe\Engine\Impl\Telemet...er\TelemetrySendingTask. Did you maybe forget to declare it?
Loading history...
192
    }
193
194
    protected function restoreDynamicData(InternalsImpl $internals): void
195
    {
196
        $commands = $internals->getCommands();
197
198
        foreach ($commands as $key => $value) {
199
            $this->telemetryRegistry->markOccurrence($key, $value->getCount());
200
        }
201
202
        if ($this->metricsRegistry != null) {
203
            $metrics = $internals->getMetrics();
204
205
            foreach (self::METRICS_TO_REPORT as $metricToReport) {
206
                $metricValue = $metrics[$metricToReport];
207
                $metricsRegistry->markTelemetryOccurrence($metricToReport, $metricValue->getCount());
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $metricsRegistry does not exist. Did you maybe mean $metrics?
Loading history...
208
            }
209
        }
210
    }
211
212
    protected function resolveDynamicData(bool $reset, bool $addLegacyNames): InternalsImpl
213
    {
214
        $result = new InternalsImpl();
0 ignored issues
show
Bug introduced by
The call to Jabe\Engine\Impl\Telemet...nalsImpl::__construct() has too few arguments starting with databaseOrOnternals. ( Ignorable by Annotation )

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

214
        $result = /** @scrutinizer ignore-call */ new InternalsImpl();

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
215
216
        $metrics = $this->calculateMetrics($reset, $addLegacyNames);
217
        $result->setMetrics($metrics);
218
219
        // command counts are modified after the metrics are retrieved, because
220
        // metric retrieval can fail and resetting the command count is a side effect
221
        // that we would otherwise have to undo
222
        $commands = $this->fetchAndResetCommandCounts($reset);
223
        $result->setCommands($commands);
224
225
        return $result;
226
    }
227
228
    protected function fetchAndResetCommandCounts(bool $reset): array
229
    {
230
        $commandsToReport = [];
231
        $originalCounts = $this->telemetryRegistry->getCommands();
232
        foreach ($originalCounts as $key => $counter) {
233
            $occurrences = $counter->get($reset);
234
            $commandsToReport[$key] = new CommandImpl($occurrences);
235
        }
236
        return $commandsToReport;
237
    }
238
239
    protected function calculateMetrics(bool $reset, bool $addLegacyNames): array
240
    {
241
        $metrics = [];
242
243
        if ($this->metricsRegistry != null) {
244
            $telemetryMeters = $metricsRegistry->getTelemetryMeters();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $metricsRegistry does not exist. Did you maybe mean $metrics?
Loading history...
245
246
            foreach (self::METRICS_TO_REPORT as $metricToReport) {
247
                $value = $telemetryMeters[$metricToReport]->get($reset);
248
249
                if ($addLegacyNames) {
250
                    $metrics[$metricToReport] = new MetricImpl($value);
251
                }
252
253
                // add public names
254
                $metrics[MetricsUtil::resolvePublicName($metricToReport)] = new MetricImpl($value);
255
            }
256
        }
257
258
        return $metrics;
259
    }
260
261
    protected function performDataSend(RunnableInterface $runnable): void
262
    {
263
        if ($this->validateData($this->staticData)) {
264
            $triesLeft = $telemetryRequestRetries + 1;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $telemetryRequestRetries seems to be never defined.
Loading history...
265
            $requestSuccessful = false;
266
            do {
267
                try {
268
                    $triesLeft -= 1;
269
                    $runnable->run();
270
                    $requestSuccessful = true;
271
                } catch (\Exception $e) {
272
                    //LOG.exceptionWhileSendingTelemetryData(e);
273
                }
274
            } while (!$requestSuccessful && $triesLeft > 0);
275
        } else {
276
            //LOG.sendingTelemetryDataFails(staticData);
277
        }
278
    }
279
280
    protected function validateData(TelemetryDataImpl $dataToSend): bool
281
    {
282
        // validate product data
283
        $product = $dataToSend->getProduct();
284
        $installationId = $dataToSend->getInstallation();
285
        $edition = $product->getEdition();
286
        $version = $product->getVersion();
287
        $name = $product->getName();
288
289
        // ensure that data is not null or empty strings
290
        $validProductData = StringUtil::hasText($name) && StringUtil::hasText($version) && StringUtil::hasText($edition) && StringUtil::hasText($installationId);
0 ignored issues
show
Bug introduced by
The method hasText() does not exist on Jabe\Engine\Impl\Util\StringUtil. ( Ignorable by Annotation )

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

290
        $validProductData = StringUtil::/** @scrutinizer ignore-call */ hasText($name) && StringUtil::hasText($version) && StringUtil::hasText($edition) && StringUtil::hasText($installationId);

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...
291
292
        // validate installation id
293
        if ($validProductData) {
294
            $validProductData = $validProductData && preg_match(self::UUID4_PATTERN, $installationId);
295
        }
296
297
        return $validProductData;
298
    }
299
}
300