PageRenderTime 49ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/slowphp.c

https://github.com/xurenlu/slowphp
C | 393 lines | 234 code | 35 blank | 124 comment | 26 complexity | 2a8a3366a71f96b9c9d825bfe42f0737 MD5 | raw file
  1. #ifdef HAVE_CONFIG_H
  2. #include "config.h"
  3. #endif
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. #include <stdio.h>
  8. #include <regex.h>
  9. #include "php.h"
  10. #include "php_globals.h"
  11. #include "ext/standard/info.h"
  12. #include "main/php_output.h"
  13. #include "zend_API.h"
  14. #include "SAPI.h"
  15. #include "php_ini.h"
  16. #include "php_slowphp.h"
  17. #define MICRO_IN_SEC 1000000.00
  18. #define slowphp_DEF 1
  19. /**
  20. * debug function
  21. * */
  22. void writelog(char * buf){
  23. /**
  24. int fd=open( "/tmp/msg", O_WRONLY|O_APPEND|O_CREAT,S_IRWXU);
  25. write(fd,(void * )buf,strlen(buf));
  26. close(fd);
  27. */
  28. }
  29. /**
  30. copy from slowphp 's source file
  31. */
  32. double slowphp_get_utime(void)
  33. {
  34. #ifdef HAVE_GETTIMEOFDAY
  35. struct timeval tp;
  36. long sec = 0L;
  37. double msec = 0.0;
  38. if (gettimeofday((struct timeval *) &tp, NULL) == 0) {
  39. sec = tp.tv_sec;
  40. msec = (double) (tp.tv_usec / MICRO_IN_SEC);
  41. if (msec >= 1.0) {
  42. msec -= (long) msec;
  43. }
  44. return msec + sec;
  45. }
  46. #endif
  47. return 0;
  48. }
  49. /*}}}*/
  50. /**
  51. * char * pattern :要检测的正则表达式
  52. * char * line:要检测的字符串
  53. * @return
  54. * return 0:表示字符串符合正则表达式
  55. * return 1:表示字符串不符合正则表达式
  56. *
  57. **/
  58. int chk_line(char *pattern,char *line){
  59. int rtn,i,len;
  60. regmatch_t pmatch;
  61. regex_t reg;
  62. rtn = regcomp(&reg,pattern,REG_ICASE|REG_EXTENDED);
  63. if(rtn)
  64. {
  65. //php_error(sprintf("can't compile regexp:%s",pattern));
  66. return -1;
  67. }
  68. rtn = regexec(&reg,line,1,&pmatch,0);
  69. regfree(&reg);
  70. return rtn;
  71. }
  72. ///* If you declare any globals in php_slowphp.h uncomment this:
  73. PHPAPI ZEND_DECLARE_MODULE_GLOBALS(slowphp)
  74. //*/
  75. /* True global resources - no need for thread safety here */
  76. static int le_slowphp;
  77. double start_time=0;
  78. double end_time=0;
  79. /* {{{ slowphp_functions[]
  80. *
  81. * Every user visible function must have an entry in slowphp_functions[].
  82. */
  83. zend_function_entry slowphp_functions[] = {
  84. PHP_FE(confirm_slowphp_compiled, NULL)
  85. PHP_FE(slowphp_get_long_query_time, NULL)
  86. PHP_FE(slowphp_get_long_query_log, NULL)
  87. PHP_FE(slowphp_get_query_log_probability, NULL)
  88. PHP_FE(slowphp_get_query_log_lock_file, NULL)
  89. PHP_FE(slowphp_get_magic_line, NULL)
  90. {NULL, NULL, NULL}
  91. };
  92. /* }}} */
  93. /* {{{ slowphp_module_entry
  94. */
  95. zend_module_entry slowphp_module_entry = {
  96. #if ZEND_MODULE_API_NO >= 20010901
  97. STANDARD_MODULE_HEADER,
  98. #endif
  99. "slowphp",
  100. slowphp_functions,
  101. PHP_MINIT(slowphp),
  102. PHP_MSHUTDOWN(slowphp),
  103. PHP_RINIT(slowphp), /* Replace with NULL if there's nothing to do at request start */
  104. PHP_RSHUTDOWN(slowphp), /* Replace with NULL if there's nothing to do at request end */
  105. PHP_MINFO(slowphp),
  106. #if ZEND_MODULE_API_NO >= 20010901
  107. "0.1", /* Replace with version number for your extension */
  108. #endif
  109. PHP_MODULE_GLOBALS(slowphp),
  110. NULL,
  111. NULL,
  112. NULL,
  113. STANDARD_MODULE_PROPERTIES_EX
  114. };
  115. /* }}} */
  116. #ifdef COMPILE_DL_SLOWPHP
  117. ZEND_GET_MODULE(slowphp)
  118. #endif
  119. /* {{{ PHP_INI
  120. */
  121. PHP_INI_BEGIN()
  122. STD_PHP_INI_ENTRY("slowphp.long_query_time", "5", PHP_INI_ALL, OnUpdateLong, long_query_time, zend_slowphp_globals, slowphp_globals)
  123. STD_PHP_INI_ENTRY("slowphp.long_query_log", "/var/log/php_long_query.log", PHP_INI_ALL, OnUpdateString, long_query_log, zend_slowphp_globals, slowphp_globals)
  124. STD_PHP_INI_ENTRY("slowphp.long_query_log_probability", "100", PHP_INI_ALL, OnUpdateLong, long_query_log_probability, zend_slowphp_globals, slowphp_globals)
  125. STD_PHP_INI_ENTRY("slowphp.long_query_lock_file", "/tmp/php_long_query.lock", PHP_INI_ALL, OnUpdateString, long_query_lock_file, zend_slowphp_globals, slowphp_globals)
  126. STD_PHP_INI_ENTRY("slowphp.magic_line", "", PHP_INI_ALL, OnUpdateString, magic_line, zend_slowphp_globals, slowphp_globals)
  127. STD_PHP_INI_ENTRY("slowphp.long_query_uri_pattern", "", PHP_INI_ALL, OnUpdateString, long_query_uri_pattern, zend_slowphp_globals, slowphp_globals)
  128. PHP_INI_END()
  129. /* }}} */
  130. /* {{{ php_slowphp_init_globals
  131. */
  132. //* Uncomment this function if you have INI entries
  133. static void php_slowphp_init_globals(zend_slowphp_globals *slowphp_globals)
  134. {
  135. slowphp_globals->long_query_time= 0;
  136. slowphp_globals->magic_line = NULL;
  137. slowphp_globals->long_query_log = NULL;
  138. }
  139. //*/
  140. /* }}} */
  141. /* {{{ PHP_MINIT_FUNCTION
  142. */
  143. PHP_MINIT_FUNCTION(slowphp)
  144. {
  145. //* If you have INI entries, uncomment these lines
  146. REGISTER_INI_ENTRIES();
  147. //*/
  148. return SUCCESS;
  149. }
  150. /* }}} */
  151. /* {{{ PHP_MSHUTDOWN_FUNCTION
  152. */
  153. PHP_MSHUTDOWN_FUNCTION(slowphp)
  154. {
  155. //* uncomment this line if you have INI entries
  156. UNREGISTER_INI_ENTRIES();
  157. //*/
  158. return SUCCESS;
  159. }
  160. /* }}} */
  161. /* Remove if there's nothing to do at request start */
  162. /* {{{ PHP_RINIT_FUNCTION
  163. */
  164. PHP_RINIT_FUNCTION(slowphp)
  165. {
  166. start_time=slowphp_get_utime();
  167. //运行magic_line
  168. /**
  169. char buf[4096];
  170. sprintf(buf,"include('%s');\n",slowphp_globals.magic_line);
  171. printf("magic_line:%s\n",buf);
  172. zend_eval_string(buf,NULL,"error occured when run slowphp.magic_line;" TSRMLS_CC );
  173. */
  174. return SUCCESS;
  175. }
  176. /* }}} */
  177. /* Remove if there's nothing to do at request end */
  178. /* {{{ PHP_RSHUTDOWN_FUNCTION
  179. */
  180. PHP_RSHUTDOWN_FUNCTION(slowphp)
  181. {
  182. char line[40960];
  183. //sprintf(line,"include('%s');\n",slowphp_globals.magic_line);
  184. sprintf(line,"%s",slowphp_globals.magic_line);
  185. //printf("magic_line:%s\n",line);
  186. zend_eval_string(line,NULL,"error occured when run slowphp.magic_line;" TSRMLS_CC );
  187. char buf[8192];
  188. end_time=slowphp_get_utime();
  189. double cost_time=end_time-start_time;
  190. int log=0;//默认不记录
  191. //如果满足四项条件中的任一项,就记录:
  192. //a:long_query_lock_file存在
  193. //b:cost_time < long_query_time
  194. //c:在0和long_query_probability之间产生的随机数刚好是1
  195. //d:probability 设置的值小于等于1;
  196. if(slowphp_globals.long_query_log_probability<=1){
  197. //printf("open log because long_query_log_probability<=1");
  198. writelog("log because probability");
  199. log=1;
  200. }
  201. else if(cost_time > slowphp_globals.long_query_time){
  202. //printf("open log because cost_time > long_query_time,cost_time:%f, long_query_time:%ld\n",cost_time,slowphp_globals.long_query_time);
  203. writelog("log because query time");
  204. log=1;
  205. }
  206. else {
  207. //generate a random seed;
  208. srand((int)time(0));
  209. int rand_num=0;
  210. rand_num=rand();
  211. int rand_should=0;
  212. rand_should=(int)(RAND_MAX/slowphp_globals.long_query_log_probability);
  213. if(rand_num<=rand_should)
  214. {
  215. //printf("open log because rand_num<=rand_should:rand_num:%d,rand_should:%d\n",rand_num,rand_should);
  216. writelog("log because rand");
  217. log=1;
  218. }
  219. else {
  220. struct stat info;
  221. int stat_result;
  222. if( (stat_result=stat(slowphp_globals.long_query_lock_file,&info))!=-1 ){
  223. //printf("open log because exists file:long_query_lock_file:%s\n",slowphp_globals.long_query_lock_file);
  224. writelog("log because lock file");
  225. log =1;
  226. }
  227. }
  228. }
  229. //now ,check the request uri;
  230. /**
  231. zval * result_value;
  232. MAKE_STD_ZVAL( result_value);
  233. zend_eval_string("print('helo world');",result_value,"inner of slowph.c:197" TSRMLS_CC );
  234. */
  235. zval ** script_file_zval;
  236. zval ** request_uri_zval;
  237. if(log!=1){
  238. if(strcmp(slowphp_globals.long_query_uri_pattern,"")!=0) {
  239. if ( zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht,
  240. "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &request_uri_zval) == SUCCESS ) {
  241. char * request_uri=(zval ** )Z_STRVAL_PP(request_uri_zval);
  242. int rtn = chk_line(slowphp_globals.long_query_uri_pattern,request_uri);
  243. if(rtn==0){
  244. writelog("log the time because request_uri match the uri");
  245. log =1;
  246. }
  247. }
  248. }
  249. }
  250. if(log==0) return SUCCESS;
  251. if (
  252. PG(http_globals)[TRACK_VARS_SERVER]
  253. &&
  254. zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht,
  255. "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &script_file_zval) == SUCCESS
  256. &&
  257. zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht,
  258. "REQUEST_URI", sizeof("REQUEST_URI"), (void **) &request_uri_zval) == SUCCESS
  259. ){
  260. char * script_filename=(zval ** )Z_STRVAL_PP(script_file_zval);
  261. char * request_uri=(zval ** )Z_STRVAL_PP(request_uri_zval);
  262. sprintf(buf,"%f\t%f\t%s\t%s\n",start_time,cost_time,script_filename,request_uri);
  263. }
  264. else if(
  265. PG(http_globals)[TRACK_VARS_SERVER] &&
  266. zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht,
  267. "SCRIPT_FILENAME", sizeof("SCRIPT_FILENAME"), (void **) &script_file_zval) == SUCCESS
  268. ){
  269. char * script_filename=(zval ** )Z_STRVAL_PP(script_file_zval);
  270. sprintf(buf,"%f\t%f\t%s\n",start_time,cost_time,script_filename);
  271. }
  272. else {
  273. sprintf(buf,"%f\t%f\t[can't fetch SCRIPT_FILENAME]\n",start_time,cost_time);
  274. }
  275. int fd=open( slowphp_globals.long_query_log, O_WRONLY|O_APPEND|O_CREAT,S_IRWXU);
  276. write(fd,(void * )buf,strlen(buf));
  277. close(fd);
  278. return SUCCESS;
  279. }
  280. /* }}} */
  281. /* {{{ PHP_MINFO_FUNCTION
  282. */
  283. PHP_MINFO_FUNCTION(slowphp)
  284. {
  285. php_info_print_table_start();
  286. php_info_print_table_header(2, "slowphp support", "enabled");
  287. php_info_print_table_end();
  288. /* Remove comments if you have entries in php.ini
  289. DISPLAY_INI_ENTRIES();
  290. */
  291. }
  292. /* }}} */
  293. /* Remove the following function when you have succesfully modified config.m4
  294. so that your module can be compiled into PHP, it exists only for testing
  295. purposes. */
  296. /* {{{ slowphp_get_long_query_time
  297. */
  298. PHP_FUNCTION(slowphp_get_long_query_time)
  299. {
  300. RETURN_LONG( (long) slowphp_globals.long_query_time);
  301. }/*}}}*/
  302. /* {{{ slowphp_get_long_query_log
  303. */
  304. PHP_FUNCTION(slowphp_get_long_query_log)
  305. {
  306. RETURN_STRINGL( slowphp_globals.long_query_log, strlen(slowphp_globals.long_query_log),1);
  307. }
  308. /*}}}*/
  309. /** {{{ slowphp_get_query_log_probability
  310. * return the ini.setting: slowphp.long_query_log_probability
  311. */
  312. PHP_FUNCTION(slowphp_get_query_log_probability)
  313. {
  314. RETURN_LONG(slowphp_globals.long_query_log_probability);
  315. }
  316. /*}}}*/
  317. /** {{{ slowphp_get_query_log_lock_file
  318. * */
  319. PHP_FUNCTION(slowphp_get_query_log_lock_file)
  320. {
  321. RETURN_STRINGL( slowphp_globals.long_query_lock_file, strlen(slowphp_globals.long_query_lock_file),1);
  322. }
  323. /*}}}*/
  324. /** {{{ slowphp_get_magic_line
  325. * */
  326. PHP_FUNCTION(slowphp_get_magic_line)
  327. {
  328. RETURN_STRINGL( slowphp_globals.magic_line, strlen(slowphp_globals.magic_line),1);
  329. }
  330. /*}}}*/
  331. /* Every user-visible function in PHP should document itself in the source */
  332. /* {{{ proto string confirm_slowphp_compiled(string arg)
  333. Return a string to confirm that the module is compiled in */
  334. PHP_FUNCTION(confirm_slowphp_compiled)
  335. {
  336. char *arg = NULL;
  337. int arg_len, len;
  338. char *strg;
  339. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
  340. return;
  341. }
  342. len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "slowphp", arg);
  343. RETURN_STRINGL(strg, len, 0);
  344. }
  345. /* }}} */
  346. /* The previous line is meant for vim and emacs, so it can correctly fold and
  347. unfold functions in source code. See the corresponding marks just before
  348. function definition, where the functions purpose is also documented. Please
  349. follow this convention for the convenience of others editing your code.
  350. */
  351. /*
  352. * Local variables:
  353. * tab-width: 4
  354. * c-basic-offset: 4
  355. * End:
  356. * vim600: noet sw=4 ts=4 fdm=marker
  357. * vim<600: noet sw=4 ts=4
  358. */