background
Due to various reasons, there is no access to the complete call chain trace (┬). However, when we call each end interface through curl of php, we will request multiple times. So is there a way to capture these curl requests without embedding business code. Obviously, ci has basic hook operations. We can choose to send the collected data to the specified listener asynchronously at the relevant nodes.
curl class library (partial code)
class Ycurl { public $resource_arr; public static $resource_id = 0; //resource handle id public $save_requests = true;//Save or not, save all by default public $requests = array();//n request parameters, return parameters, error (if any) public $request_counts = 0;//The total number of requests, maybe a page is called more than once public $send_redis_email = false;//Need to send mail in abnormal way ... $ret = curl_exec($ch); $curl_info_arr = curl_getinfo($ch); $this->request_counts += 1; if ($this->save_requests === true) { $arg_list = func_get_args(); $this->requests[$resource_id]['url'] = $curl_info_arr['url']; $this->requests[$resource_id]['req_params'] = json_encode([$arg_list], 320); $this->requests[$resource_id]['response'] = $ret; $this->requests[$resource_id]['http_code'] = $curl_info_arr['http_code']; $this->requests[$resource_id]['is_error'] = curl_error($ch); $this->requests[$resource_id]['total_time'] = $curl_info_arr['total_time']; $this->requests[$resource_id]['primary_ip'] = $curl_info_arr['primary_ip']; if($this->send_redis_email){ redis_list_add(json_encode($this->requests,320)); } }
hooks config
Extracting curl objects from ci objects, other custom objects can be the same way.
$hook['post_system'][] = array( 'class' => 'Curl_trace', 'function' => '_split_ci_of_curl', 'filename' => 'curl_trace.php', 'filepath' => 'hooks'
curl_trace.php
<?php /** * Created by PhpStorm. * User: TongBo * Date: 2019/2/26 * Time: 16:19 */ defined('BASEPATH') OR exit('No direct script access allowed'); Class Curl_trace { public $ci; public function __construct() { $this->ci =& get_instance(); } /** *Extract all curl object instances of the entire ci object * @time 2019/3/1 11:12 * @author tongbo */ public function _split_ci_of_curl() { $class = $this->ci->router->fetch_class(); $need_trace_controller = [ 'home', 'admin', ]; $func = $this->ci->router->fetch_method(); if (in_array($class, $need_trace_controller) or 1) { foreach (get_object_vars($this->ci) as $name => $ci_object) { if (is_object($ci_object)) { if ($ci_object instanceof Ycurl) { $curls[get_class($this->ci) . "/{$func}:$" . $name] = $ci_object; } } } if (!empty($curls)) { foreach ($curls as $ctl_func => $curl) { foreach ($curl->requests as $index => $single_curl_obj) { $tmp[$ctl_func][$index] = $single_curl_obj; $tmp[$ctl_func][$index]['record_time'] = date('Ymd H:i:s' . substr((string)microtime(), 1, 8) . ' e'); redis_list_add(json_encode([$ctl_func . "_" . $index, $tmp[$ctl_func][$index]], 320)); } } } } } }
Results in queue
Insufficient
ci framework inevitably uses exit operation, or other business code. As a result, the hook function cannot be used normally. In addition to the necessary specification of unnecessary exit, we can also use the function register "shut" down to implement the record every time. (consider cost performance)