@101-s

Как сделать логирование для многопоточного curl?

Подскажите, в каком направлении копать или может уже есть готовые решения? Необходимо парсить большой объем данных через прокси и при этом сделать вывод логов. Используется многопоточное скачивание в cURL
  • Вопрос задан
  • 165 просмотров
Решения вопроса 2
uDenX
@uDenX
PHP Developer
Ответ написан
Комментировать
gzhegow
@gzhegow
aka "ОбнимиБизнесмена"
Почитать и подумать (желательно):

https://github.com/6562680/support/blob/main/src/X...
https://github.com/6562680/support/blob/main/src/X...

Устанавливаем:

composer require monolog/monolog
composer require gzhegow/support:1.16.21


Запускаем:

require __DIR__ . '/vendor/autoload.php';


// const
define('__LOGS__', __DIR__ . '/logs');

// vars
$channelName = 'curl';

// dirs
if (! is_dir($var = __LOGS__)) mkdir($var, 0775, true); // на unix есть ограничение в /etc/php/fpm с помощью umask и listen/owner, и вместо 0775 может быть создано меньше полномочий

// init
$logger = new \Monolog\Logger($channelName, [
  new \Monolog\Handler\StreamHandler(__LOGS__ . '/monolog/' . date('Y-m-d') . '/' . date('H') . '_' . $channelName . '.log'), // в файл
  // new \Monolog\Handler\StreamHandler('php://stdout'), // для консоли
  // new \Monolog\Handler\StreamHandler('php://output'), // для браузера
  // куда-нибудь ещё...
]);

$xcurl = \Gzhegow\Support\XCurl::getInstance();

// data
$urls = [
  // index => url
  'myIndex1' => 'https://google.com',
  0 => 'https://google.com',
];

// action
$curls = [];
foreach ($urls as $index => $url) {
  // >>> логируем, что делаем запрос на внешний адрес
  $logger->notice('Fetching url: ' . $urls[ $index ]);

  $ch = curl_init($url);
  // curl_setopt($ch, CURLOPT_HEADER, 0); // и т.д.

  $curls[ $index ] = $ch;
}

$retry = null; // создаем пустую переменную, она по ссылке будет передавать состояние в каждом шаге цикла
$retries = 3; // три повтора, условия выхода из бесконечного цикла
foreach ($generator = $xcurl->walkmulti($curls, $retry) as $step => [ $index, $curl ]) {
  // $retry автоматически становится null в начале каждой проверки (так написал в walkmulti). То есть если проверок не сделать, $retry будет null и повторов не будет.

  // проверяем ошибку. добавь столько ЕСЛИ, сколько нужно. длина контента. время запроса. код ответа, всё в этот ЕСЛИ
  if (curl_errno($curl)) {
    // проверяем условие, после которого повторы делать не надо. например, у нас только три попытки
    if ($step >= $retries) {
      // >>> логируем, что больше не выйдет
      $logger->notice('Unable to retry url: ' . $urls[ $index ]);

      $retry = false; // false = больше не спрашивай про него, результат не сохраняй
      // $retry = null; // null = сохрани результат последнего и больше не спрашивай про него
      continue;
    
    } else {
      // >>> логируем что пошел повтор
      $logger->notice('Retrying url: ' . $urls[ $index ] . '. Retries left: ' . $retries - $step);

      $ch = curl_init($urls[ $index ]); // в curl нельзя повторно выполнить запрос по тому же ресурсу, собираем заново такой же как был, вероятно - с новой прокси
      // curl_setopt($ch, CURLOPT_HEADER, 0); // и т.д.

      $retry = $ch; // передаем по ссылке новый курл, который после всех проверок выполнится в пачке ещё раз
      continue;
    }
  }
}

$results = $generator->getReturn();

var_dump($results); // [ 'myIndex1' => <content>, 0 => <content> ]
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы