CodeIgniter框架中抽取部分類庫作問題追蹤的思路

背景

因爲各類緣由,沒有接入完整的調用鏈追蹤,(┬_┬)。可是咱們自身再經過php的curl調用各端接口時,會請求屢次。那麼有沒有一種方法能夠在不植入業務代碼的前提下,捕捉到這些curl的請求呢。顯然,ci有基本的hook操做。咱們能夠在相關節點時,可選擇的把這些收集到到的經過異步的方式發送給指定的監聽者。php

curl類庫(部分代碼)

class Ycurl
{
    public $resource_arr;
    public static $resource_id = 0; //資源(resource handle id
    public $save_requests = true;//是否保存,默認所有保存
    public $requests = array();//n次請求參數、返回參數,錯誤(若是有)
    public $request_counts = 0;//總的請求次數,可能一個頁面調用屢次
    public $send_redis_email = false;//是否須要以異常方式發送郵件

    ...
    
   $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

從ci對象中抽取curl對象,其餘自定義的對象也能夠一樣思路。redis

$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();
    }

    /**
     *抽取整個ci對象的全部curl對象實例
     * @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));
                    }

                }

            }

        }
    }

}

隊列中的結果

clipboard.png

不足

ci框架中不可避免的使用了exit操做,或者其餘業務代碼中也使用。這樣致使鉤子函數沒法正常完成他的使用。除了必要規範沒必要要的exit以外,咱們也能夠用register_shut_down這個函數來實現每次都必須記錄。(考慮性價比吧)json

相關文章
相關標籤/搜索