laravel7开始加入了httpclient包,比guzzle库好用,如果是低于laravel7可以把Httpclient包手动引入到项目中
这里对httpclient做一些修改使得其可以自动记录成功以及错误日志
创建事件
<?phpnamespace App\Light\HttpClient;use Illuminate\Contracts\Support\Arrayable;class HttpSendSuccessEvent implements \JsonSerializable,Arrayable{public $request_id; //请求标识public $url; //urlpublic $params; //请求参数public $method; //请求方法public $created_at; //请求时间public $response; //响应内容public $response_header; //响应头public $request_header; //请求头public $handler_stats; //请求信息public $tag; //标签public function toArray(){return ['request_id' => $this->request_id,'url' => $this->url,'params' => $this->params,'method' => $this->method,'created_at' => $this->created_at,'response' => $this->response,'response_header' => $this->response_header,'request_header' => $this->request_header,'handler_stats' => $this->handler_stats,'tag' => $this->tag,];}public function jsonSerialize(){return $this->toArray();}public function __toString(){return json_encode($this, JSON_UNESCAPED_UNICODE);}}
<?phpnamespace App\Light\HttpClient;use Illuminate\Contracts\Support\Arrayable;class HttpSendFailEvent implements \JsonSerializable,Arrayable{public $request_id; //请求标识public $url; //urlpublic $params; //请求参数public $method; //请求方法public $created_at; //请求时间public $error; //错误信息public $response_header; //响应头public $tag; //标签public function toArray(){return ['request_id' => $this->request_id,'url' => $this->url,'params' => $this->params,'method' => $this->method,'created_at' => $this->created_at,'error' => $this->error,'response_header' => $this->response_header,'tag' => $this->tag,];}public function jsonSerialize(){return $this->toArray();}public function __toString(){return json_encode($this, JSON_UNESCAPED_UNICODE);}}
增加日志逻辑
修改httpclient包中PendingReques类中的send方法
public function send(string $method, string $url, array $options = []){$url = ltrim(rtrim($this->baseUrl, '/') . '/' . ltrim($url, '/'), '/');if (isset($options[$this->bodyFormat])) {if ($this->bodyFormat === 'multipart') {$options[$this->bodyFormat] = $this->parseMultipartBodyFormat($options[$this->bodyFormat]);} elseif ($this->bodyFormat === 'body') {$options[$this->bodyFormat] = $this->pendingBody;}if (is_array($options[$this->bodyFormat])) {$options[$this->bodyFormat] = array_merge($options[$this->bodyFormat], $this->pendingFiles);}}[$this->pendingBody, $this->pendingFiles] = [null, []];return retry($this->tries ?? 1, function () use ($method, $url, $options) {try {$laravelData = $this->parseRequestData($method, $url, $options);return tap(new Response($this->buildClient()->request($method, $url, $this->mergeOptions(['laravel_data' => $laravelData,'on_stats' => function ($transferStats) {$this->transferStats = $transferStats;},], $options))), function ($response) use ($method, $url, $options) {$response->cookies = $this->cookies;$response->transferStats = $this->transferStats;//新加入//生产事件$event = new HttpSendSuccessEvent();$event->url = $url;$event->params = $options;$event->method = $method;$event->created_at = Carbon::now()->toDateTimeString();$event->response = $response->body();$event->request_header = $response->transferStats->getRequest()->getHeaders();$event->response_header = $response->headers();$event->handler_stats = $response->handlerStats();//发事件event($event);if ($this->tries > 1 && !$response->successful()) {$response->throw();}});} catch (ConnectException $e) {//新加入//生产事件$event = new HttpSendFailEvent();$event->url = $url;$event->params = $options;$event->method = $method;$event->created_at = Carbon::now()->toDateTimeString();$event->error = $e->getHandlerContext();$event->request_header = $e->getRequest()->getHeaders();//发事件event($event);throw new ConnectionException($e->getMessage(), 0, $e);}}, $this->retryDelay ?? 100);}
创建事件处理器
这里使用了生成请求唯一标识和terminate中间件 参考laravel技巧—请求日志和laravel技巧-terminate延迟处理
<?phpnamespace App\Light\HttpClient;use App\Light\RequestID\ResID;use App\Light\TerminateHandle\TerminateEvent;use App\Light\TerminateHandle\TerminateHandle;use Carbon\Carbon;use Illuminate\Support\Facades\DB;class HttpSendSuccessEventListener{public function handle(HttpSendSuccessEvent $event){//延迟记录TerminateHandle::add(new TerminateEvent(function () use ($event) {$event->request_id = ResID::get(); //请求标识DB::connection('mongodb')->collection('curl_' . Carbon::now()->format('Ym'))->insert($event->toArray());}));}}
<?phpnamespace App\Light\HttpClient;use App\Light\RequestID\ResID;use App\Light\TerminateHandle\TerminateEvent;use App\Light\TerminateHandle\TerminateHandle;use Carbon\Carbon;use Illuminate\Support\Facades\DB;class HttpSendFailEventListener{public function handle(HttpSendFailEvent $event){//延迟记录TerminateHandle::add(new TerminateEvent(function () use ($event) {try {$event->request_id = ResID::get(); //请求标识DB::connection('mongodb')->collection('curl_error_' . Carbon::now()->format('Ym'))->insert($event->toArray());} catch (\Exception $exception) {}}));}}
注册事件处理器
class EventServiceProvider extends ServiceProvider{/*** The event listener mappings for the application.** @var array*/protected $listen = [//新增HttpSendSuccessEvent::class => [HttpSendSuccessEventListener::class],HttpSendFailEvent::class => [HttpSendFailEventListener::class],];
查看结果
成功结果
失败结果
