. */ declare(strict_types=1); namespace FireflyIII\Jobs; use Carbon\Carbon; use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Telemetry; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Collection; use JsonException; use Log; use Sentry\State\Scope; use function Sentry\captureMessage; use function Sentry\configureScope; /** * Class SubmitTelemetryData */ class SubmitTelemetryData implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; private Carbon $date; private bool $force; /** * Create a new job instance. * * @codeCoverageIgnore * * @param Carbon|null $date */ public function __construct(?Carbon $date) { $this->date = $date; Log::debug('Created new SubmitTelemetryData'); } /** * @throws FireflyException */ public function handle(): void { $url = sprintf('%s/submit', config('firefly.telemetry_endpoint')); Log::debug(sprintf('Will submit telemetry to endpoint: %s', $url)); $telemetry = $this->collectTelemetry(); if (0 === $telemetry->count()) { Log::debug('Nothing to submit.'); return; } // submit to Sentry one by one: /** @var Telemetry $entry */ foreach($telemetry as $entry) { configureScope(function (Scope $scope) use ($entry): void { $scope->setContext('telemetry', [ 'installation_id' => $entry->installation_id, 'collected_at' => $entry->created_at->format('r'), 'type' => $entry->type, 'key' => $entry->key, 'value' => $entry->value, ]); }); captureMessage('Telemetry submission'); } $this->markAsSubmitted($telemetry); // $json = $this->parseJson($telemetry); // try { // $body = json_encode($json, JSON_THROW_ON_ERROR); // } catch (JsonException $e) { // Log::error($e->getMessage()); // Log::error('Could not parse JSON.'); // throw new FireflyException(sprintf('Could not parse telemetry JSON: %s', $e->getMessage()), 0, $e); // } // // $client = new Client; // $options = [ // 'body' => $body, // 'headers' => [ // 'Content-Type' => 'application/json', // 'Accept' => 'application/json', // 'connect_timeout' => 3.14, // 'User-Agent' => sprintf('FireflyIII/%s', config('firefly.version')), // ], // ]; // try { // $result = $client->post($url, $options); // } catch (GuzzleException | Exception $e) { // Log::error($e->getMessage()); // Log::error($e->getTraceAsString()); // Log::error('Could not submit telemetry.'); // throw new FireflyException(sprintf('Could not submit telemetry: %s', $e->getMessage()), 0, $e); // } // $body = (string)$result->getBody(); // $statusCode = $result->getStatusCode(); // Log::info(sprintf('Result of submission [%d]: %s', $statusCode, $body)); // if (200 === $statusCode) { // // mark as submitted: // $this->markAsSubmitted($telemetry); // } } /** * @return Collection */ private function collectTelemetry(): Collection { $collection = Telemetry::whereNull('submitted')->take(50)->get(); Log::debug(sprintf('Found %d entry(s) to submit', $collection->count())); return $collection; } /** * @param Collection $telemetry * * @return array */ private function parseJson(Collection $telemetry): array { $array = []; /** @var Telemetry $entry */ foreach ($telemetry as $entry) { $array[] = [ 'installation_id' => $entry->installation_id, 'collected_at' => $entry->created_at->format('r'), 'type' => $entry->type, 'key' => $entry->key, 'value' => $entry->value, ]; } return $array; } /** * @param Collection $telemetry */ private function markAsSubmitted(Collection $telemetry): void { $telemetry->each( static function (Telemetry $entry) { $entry->submitted = today(config('app.timezone')); $entry->save(); } ); } /** * @param Carbon $date */ public function setDate(Carbon $date): void { $this->date = $date; } /** * @param bool $force */ public function setForce(bool $force): void { $this->force = $force; } }