最近浏览php源码,为了验证成果,写了一个php扩大,次要性能就是打造php本人的链路追踪和性能监控
先从github下载源码 https://github.com/wuxian12/i…
编译装置就能够应用了
当初只是一个基本功能,前面缓缓欠缺
外围性能就是改写php的执行函数,就是平时常常写的代理
PHP_MINIT_FUNCTION(pid) { REGISTER_INI_ENTRIES(); ori_execute_ex = zend_execute_ex; zend_execute_ex = pid_execute_ex; ori_execute_internal = zend_execute_internal; zend_execute_internal = pid_execute_internal; return SUCCESS; }
执行时发现是要拦挡的函数就获取函数的参数返回值记录日志,继续执行php原始的执行函数
ZEND_API void pid_execute_core(int internal, zend_execute_data *execute_data, zval *return_value) { char *logs_dir = {0}; char *re_func = {0}; char *file_log = "trace.log"; //从php.ini文件读取拦挡函数和日志目录 logs_dir = INI_STR("pid.log_path"); re_func = INI_STR("pid.function"); char *name = (char *) malloc(strlen(logs_dir) + strlen(file_log)); sprintf(name, "%s%s", logs_dir, file_log); FILE *fp; if((fp = fopen(name, "a+")) == NULL){ printf("file cannot open \n"); } zend_function *zf = obtain_zend_function(execute_data); int flag = 0; char str_1[512] = {0}; char *token; const char s[2] = ","; if (zf->common.function_name != NULL){ sprintf(str_1, ZSTR_VAL(zf->common.function_name)); /* 获取第一个子字符串 */ token = strtok(re_func, s); /* 持续获取其余的子字符串 */ while( token != NULL ) { printf( "%s\n", token ); if(strcmp(str_1, token) == 0){ flag = 1; fputs("\n执行函数的名字:", fp); fputs( str_1, fp); break; }else{ flag = 0; } token = strtok(NULL, s); } } int arg_count = 0; arg_count = ZEND_CALL_NUM_ARGS(execute_data); smart_str res = {0}; smart_str buf = {0}; if (arg_count) { zval *p = ZEND_CALL_ARG(execute_data, 1); if (execute_data->func->type == ZEND_USER_FUNCTION) { uint32_t first_extra_arg = execute_data->func->op_array.num_args; if (first_extra_arg && arg_count > first_extra_arg) { p = ZEND_CALL_VAR_NUM(execute_data, execute_data->func->op_array.last_var + execute_data->func->op_array.T); } } int i; for (i = 0; i < arg_count; i++) { php_var_export_ex(p, 2, &buf); p++; } if(flag == 1){ fputs(";执行函数的参数:", fp); fputs( ZSTR_VAL(buf.s), fp); //printf("执行函数的参数 %s ......\n", ZSTR_VAL(buf.s)); } } if (internal) { if (ori_execute_internal) { ori_execute_internal(execute_data, return_value); } else { execute_internal(execute_data, return_value); } } else { ori_execute_ex(execute_data); } if (return_value) { /* internal */ php_var_export_ex(return_value, 2, &res); if(flag == 1){ fputs(";执行函数的返回后果:", fp); fputs( ZSTR_VAL(res.s), fp); //printf("外部函数返回的后果 %s === \n", ZSTR_VAL(res.s)); } } else if (execute_data->return_value) { /* user function */ php_var_export_ex(execute_data->return_value, 2, &res); if(flag == 1){ fputs(";执行函数的返回后果:", fp); fputs( ZSTR_VAL(res.s), fp); //printf("自定义函数返回后果 %s ===\n", ZSTR_VAL(res.s)); } } fclose(fp); }