• Час читання ~2 хв
  • 10.08.2022

Найбільша проблема роботи зі сторонніми API полягає в тому, що ми маємо дуже низьку видимість. Ми інтегруємо їх у нашу кодову базу та тестуємо, але ми не маємо уявлення про те, як часто ми їх використовуємо, якщо API, з яким ми інтегруємо, не має показників, які ми можемо використовувати. Я був дуже розчарований цим протягом досить тривалого часу, але ми можемо щось зробити.

Телескоп Laravel — це помічник із налагодження вашої програми, що означає, що він буде реєструвати та давати вам уявлення про те, що відбувається на високому рівні. Ми можемо скористатися цим і додати користувацькі спостерігачі, щоб увімкнути більше налагодження та журналювання, і саме це ми зробимо в цьому короткому посібнику.

Після того, як ви встановили Laravel Telescope, переконайтеся, що ви опублікували конфігурацію та перенесли базу даних, ми можемо почати створювати наш спостерігач для Guzzle — клієнта під фасадом Http. Найлогічнішим місцем для зберігання цих класів, принаймні для мене, є app/Telescope/Watchers, оскільки код належить до нашої програми, але ми розширюємо сам Telescope.Але як виглядає стандартний спостерігач? Нижче я покажу вам приблизний нарис основних вимог:

class YourWatcher extends Watcher
{
  public function register($app): void
  {
    // handle code for watcher here.
  }
}

Це приблизний нарис. Ви можете додати стільки методів, скільки потрібно, щоб додати спостерігач, який вам підходить. Отже, без зайвих слів, давайте створимо новий спостерігач app/Telescope/Watchers/GuzzleRequestWatcher.php, і ми розповімо, що йому потрібно робити.

declare(strict_types=1);
 
namespace App\\Telescope\\Watchers;
 
use GuzzleHttp\\Client;
use GuzzleHttp\\TransferStats;
use Laravel\\Telescope\\IncomingEntry;
use Laravel\\Telescope\\Telescope;
use Laravel\\Telescope\\Watchers\\FetchesStackTrace;
use Laravel\\Telescope\\Watchers\\Watcher;
 
final class GuzzleRequestWatcher extends Watcher
{
  use FetchesStackTrace;
}

Спочатку нам потрібно включити трейт FetchesStackTrace, оскільки це дозволяє нам фіксувати, звідки надходять ці запити. Якщо ми реорганізуємо ці HTTP-виклики в інші місця, ми зможемо переконатися, що ми називаємо їх так, як ми збираємося. Далі нам потрібно додати метод для реєстрації нашого спостерігача:

declare(strict_types=1);
 
namespace App\\Telescope\\Watchers;
 
use GuzzleHttp\\Client;
use GuzzleHttp\\TransferStats;
use Laravel\\Telescope\\IncomingEntry;
use Laravel\\Telescope\\Telescope;
use Laravel\\Telescope\\Watchers\\FetchesStackTrace;
use Laravel\\Telescope\\Watchers\\Watcher;
 
final class GuzzleRequestWatcher extends Watcher
{
  use FetchesStackTrace;
 
  public function register($app)
  {
    $app->bind(
      abstract: Client::class,
      concrete: $this->buildClient(
        app: $app,
      ),
    );
  }
}

Ми перехоплюємо клієнт Guzzle і реєструємо його в контейнері, але для цього ми хочемо вказати, як ми хочемо, щоб клієнт був створений. Давайте подивимося на метод buildClient:

private function buildClient(Application $app): Closure
{
  return static function (Application $app): Client {
  	$config = $app['config']['guzzle'] ?? [];
 
    if (Telescope::isRecording()) {
      // Record our Http query.
    }
 
    return new Client(
      config: $config,
    );
  };
}

Ми повертаємо тут статичну функцію, яка створює наш Guzzle Client. Спочатку ми отримуємо будь-яку конфігурацію guzzle, а потім, якщо телескоп записує, ми додаємо спосіб запису запиту.Нарешті, ми повертаємо клієнта з його конфігурацією. Отже, як нам записати наш HTTP-запит? Давайте подивимося:

if (Telescope::isRecording()) {
  $config['on_stats'] = static function (TransferStats $stats): void {
    $caller = $this->getCallerFromStackTrace(); // This comes from the trait we included.
 
    Telescope::recordQuery(
      entry: IncomingEntry::make([
        'connection' => 'guzzle',
        'bindings' => [],
        'sql' => (string) $stats->getEffectiveUri(),
        'time' => number_format(
          num: $stats->getTransferTime() * 1000,
          decimals: 2,
          thousand_separator: '',
        ),
        'slow' => $stats->getTransferTime() > 1,
        'file' => $caller['file'],
        'line' => $caller['line'],
        'hash' => md5((string) $stats->getEffectiveUri())
      ]),
    );
  };
}

Тож ми розширюємо конфігурацію, додаючи опцію on_stats, яка є зворотним викликом. Цей зворотній виклик отримає трасування стека та запише новий запит. Цей новий запис міститиме всі відповідні речі щодо запиту, який ми можемо записати. Отже, якщо ми зведемо все разом:

declare(strict_types=1);
 
namespace App\Telescope\Watchers;
 
use Closure;
use GuzzleHttp\Client;
use GuzzleHttp\TransferStats;
use Illuminate\Foundation\Application;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\Watchers\FetchesStackTrace;
use Laravel\Telescope\Watchers\Watcher;
 
final class GuzzleRequestWatcher extends Watcher
{
    use FetchesStackTrace;
 
    public function register($app): void
    {
        $app->bind(
            abstract: Client::class,
            concrete: $this->buildClient(
                app: $app,
            ),
        );
    }
 
    private function buildClient(Application $app): Closure
    {
        return static function (Application $app): Client {
            $config = $app['config']['guzzle'] ?? [];
 
            if (Telescope::isRecording()) {
                $config['on_stats'] = function (TransferStats $stats) {
                    $caller = $this->getCallerFromStackTrace();
                    Telescope::recordQuery(
                        entry: IncomingEntry::make([
                            'connection' => 'guzzle',
                            'bindings' => [],
                            'sql' => (string) $stats->getEffectiveUri(),
                            'time' => number_format(
                                num: $stats->getTransferTime() * 1000,
                                decimals: 2,
                                thousands_separator: '',
                            ),
                            'slow' => $stats->getTransferTime() > 1,
                            'file' => $caller['file'],
                            'line' => $caller['line'],
                            'hash' => md5((string) $stats->getEffectiveUri()),
                        ]),
                    );
                };
            }
 
            return new Client(
                config: $config,
            );
        };
    }
}

Тепер усе, що нам потрібно зробити, — це переконатися, що ми зареєстрували цей новий спостерігач у config/telescope.php, і наші запити Http повинні почати реєструватися.

'watchers' => [
  // all other watchers
  App\\Telescope\\Watchers\\GuzzleRequestWatcher::class,
]

Щоб перевірити це, створіть тестовий маршрут:

Route::get('/guzzle-test', function () {
    Http::post('<https://jsonplaceholder.typicode.com/posts>', ['title' => 'test']);
});

Коли ви відкриваєте Telescope, ви маєте побачити елемент навігації збоку під назвою HTTP Client, і якщо ви відкриєте його, ви побачите, що тут з’являться журнали – ви можете перевірити заголовки, корисне навантаження та статус запиту. Отже, якщо ви почнете спостерігати збої під час інтеграції API, це значно допоможе вам із налагодженням.

Чи знайшлося це для вас корисним?Які ще способи ви використовуєте для моніторингу та реєстрації зовнішніх запитів API? Повідомте нас у Twitter!

Comments

No comments yet
Sarah 3:34 PM

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

Replies

Sarah 3:34 PM

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

Sarah 3:34 PM

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.

Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297