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

TelemetrySendingTask::resolveDynamicData()

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
dl 0
loc 14
c 1
b 0
f 0
nc 1
nop 2
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