Apache拡張モジュール「mod_resource_checker」のソースを眺めてる (途中)
はじめに
- Cのお勉強のいっかんとして取り組んでいます
- なので、誤った情報である可能性があります
- 自分用の覚え書き情報が主なので、役に立たないかもしれません
お題
mod_resource_checker?
Process Resource Logging Module using JSON format into file or piped program.
アクセス毎にApacheプロセスの使用したOSのリソース情報を、JSON形式でログ出力することができます。
[PMAC226S ~/Downloads]$ tail -1 resource.log | jq . { "module": "mod_resource_checker", "date": "Sun Feb 28 22:53:58 2016", "type": "RCheckALL", "unit": null, "location": "/var/www/*/*/web/", "remote_ip": "123.456.789.000", "filename": "/var/www/web/wp/index.php", "scheme": "http", "method": "GET", "hostname": "hoge.com", "server_ip": "192.168.0.111", "uri": "/wp/index.php", "real_server_name": null, "uid": 1234, "size": 418, "content_length": 0, "status": 200, "pid": 16431, "threshold": null, "response_time": 0, "result": { "RCheckUCPU": 0.552367, "RCheckSCPU": 0.00806, "RCheckMEM": 0.644531 } }
mod_resource_checker.c
読んでいきます
1. 末尾のモジュールをApacheへ登録する部分
722 723 #ifdef __APACHE24__ 724 AP_DECLARE_MODULE(resource_checker) = { 725 #else 726 module AP_MODULE_DECLARE_DATA resource_checker_module = { 727 #endif 728 STANDARD20_MODULE_STUFF, (void *)resource_checker_create_dir_config, /* create per-dir config structures */ 729 NULL, /* merge per-dir config structures */ 730 (void *)resource_checker_create_config, /* create per-server config structures */ 731 NULL, /* merge per-server config structures */ 732 resource_checker_cmds, /* table of config file commands */ 733 resource_checker_register_hooks /* register hooks */ 734 };
__APACHE24__
で判定しているのは、Apache2.4とそれ以前で定義方法に差異があるからでしょうか。
728〜732行は http://blog.matsumoto-r.jp/?p=603 を読んでお勉強。
とりあえず今は設定がちゃんとされてますか、の面倒をApache起動時に見るための記述という理解。
リクエストを処理する際に気にするところは、 resource_checker_register_hooks
の中で設定されたhook関数群かな
2. 登録されたhook関数
715 static void resource_checker_register_hooks(apr_pool_t *p) 716 { 717 ap_hook_post_config((void *)resource_checker_init, NULL, NULL, APR_HOOK_MIDDLE); 718 ap_hook_access_checker(before_resource_checker, NULL, NULL, APR_HOOK_LAST); 719 ap_hook_fixups(resource_checker_handler, NULL, NULL, APR_HOOK_LAST); 720 ap_hook_log_transaction(after_resource_checker, NULL, NULL, APR_HOOK_LAST); 721 }
ap_hook_XXXX
はhookさせたいタイミングに応じて、様々な種類がある。詳細は http://d.hatena.ne.jp/dayflower/20081029/1225266220 と http://blog.matsumoto-r.jp/?p=1625 にまとまっている。
今回のものでいくと、
- ap_hook_post_config - 設定初期化時
- ap_hook_access_checker - アクセス制御を行う前(なので、アクセス制御をおこなう)
- ap_hook_fixups - よくわからん・・・
- ap_hook_log_transaction - レスポンス後のロギング処理時
今回の mod_resource_checker
はリソース情報をロギングすることが目的なので、 ap_hook_log_transaction
が重要な仕事をやってそう。
3. ap_hook_log_transaction でやっていること
577 static int after_resource_checker(request_rec *r) 578 { 579 mod_rc_dir_conf *dconf = (mod_rc_dir_conf *)ap_get_module_config(r->per_dir_config, &resource_checker_module); 580 mod_rc_conf *sconf = (mod_rc_conf *)ap_get_module_config(r->server->module_config, &resource_checker_module); 581 mod_rc_rusage *before_resources = dconf->before_resources; 582 583 if (dconf->cpu_utime == INITIAL_VALUE && dconf->cpu_stime == INITIAL_VALUE && dconf->shared_mem == INITIAL_VALUE && 584 dconf->check_status == OFF && dconf->check_all == OFF) 585 return DECLINED; 586 587 int match; 588 struct stat sb; 589 mod_rc_rusage *after_resources; 590 after_resources = (mod_rc_rusage *)apr_pcalloc(r->pool, sizeof(mod_rc_rusage)); 591 mod_rc_rusage *use_resources; 592 use_resources = (mod_rc_rusage *)apr_pcalloc(r->pool, sizeof(mod_rc_rusage)); 593 594 mod_rc_client_data *cdata; 595 cdata = (mod_rc_client_data *)apr_pcalloc(r->pool, sizeof(mod_rc_client_data)); 596 597 if (resource_checker_initialized == 0) { 598 return OK; 599 } 600 601 if (r->main && (stat(r->filename, &sb) == -1) && errno == ENOENT) { 602 return OK; 603 } 604 605 cdata->access_uri = r->uri; 606 cdata->access_file = r->filename; 607 #ifdef __APACHE24__ 608 cdata->access_src_ip = r->connection->client_ip; 609 #else 610 cdata->access_src_ip = r->connection->remote_ip; 611 #endif 612 cdata->access_dst_host = r->server->server_hostname; 613 614 if (dconf->check_status == ON) { 615 _mod_resource_checker_logging(r, 0, 0, NULL, dconf, cdata, MODULE_NAME, "RCheckSTATUS", NULL, r->pool); 616 } 617 618 // threashould check 619 if (before_resources == NULL) { 620 ap_log_rerror(APLOG_MARK, APLOG_NOTICE, 0, r, "%s NOTICE %s: Can not check resource of the request: file = %s", 621 MODULE_NAME, __func__, r->filename); 622 return DECLINED; 623 } 624 625 match = 0; 626 after_resources->cpu_utime = INITIAL_VALUE; 627 after_resources->cpu_stime = INITIAL_VALUE; 628 after_resources->shared_mem = INITIAL_VALUE; 629 630 if (dconf->cpu_utime > INITIAL_VALUE || dconf->check_all == ON) { 631 match = 1; 632 if (dconf->check_all == ON) 633 after_resources->cpu_utime = _get_rusage_resource(r->pool, "ALL", "cpu_utime"); 634 else 635 after_resources->cpu_utime = _get_rusage_resource(r->pool, dconf->utime_process_type, "cpu_utime"); 636 } 637 638 if (dconf->cpu_stime > INITIAL_VALUE || dconf->check_all == ON) { 639 match = 1; 640 if (dconf->check_all == ON) 641 after_resources->cpu_stime = _get_rusage_resource(r->pool, "ALL", "cpu_stime"); 642 else 643 after_resources->cpu_stime = _get_rusage_resource(r->pool, dconf->stime_process_type, "cpu_stime"); 644 } 645 646 if (dconf->shared_mem > INITIAL_VALUE || dconf->check_all == ON) { 647 match = 1; 648 if (dconf->check_all == ON) 649 after_resources->shared_mem = _get_rusage_resource(r->pool, "ALL", "shared_mem"); 650 else 651 after_resources->shared_mem = _get_rusage_resource(r->pool, dconf->mem_process_type, "shared_mem"); 652 } 653 654 if (match == 0) { 655 return OK; 656 } 657 658 use_resources->cpu_utime = after_resources->cpu_utime - before_resources->cpu_utime; 659 use_resources->cpu_stime = after_resources->cpu_stime - before_resources->cpu_stime; 660 use_resources->shared_mem = after_resources->shared_mem - before_resources->shared_mem; 661 662 // unexpected value; resource is negative number 663 if (use_resources->cpu_utime < 0) { 664 use_resources->cpu_utime = 0; 665 } 666 if (use_resources->cpu_stime < 0) { 667 use_resources->cpu_stime = 0; 668 } 669 if (use_resources->shared_mem < 0) { 670 use_resources->shared_mem = 0; 671 } 672 673 if (dconf->cpu_utime > INITIAL_VALUE && use_resources->cpu_utime >= dconf->cpu_utime) { 674 _mod_resource_checker_logging(r, use_resources->cpu_utime, dconf->cpu_utime, dconf->utime_process_type, dconf, 675 cdata, MODULE_NAME, "RCheckUCPU", "sec", r->pool); 676 } 677 678 if (dconf->cpu_stime > INITIAL_VALUE && use_resources->cpu_stime >= dconf->cpu_stime) { 679 _mod_resource_checker_logging(r, use_resources->cpu_stime, dconf->cpu_stime, dconf->stime_process_type, dconf, 680 cdata, MODULE_NAME, "RCheckSCPU", "sec", r->pool); 681 } 682 683 if (dconf->shared_mem > INITIAL_VALUE && use_resources->shared_mem >= dconf->shared_mem) { 684 _mod_resource_checker_logging(r, use_resources->shared_mem, dconf->shared_mem, dconf->mem_process_type, dconf, 685 cdata, MODULE_NAME, "RCheckMEM", "MiB", r->pool); 686 } 687 688 if (dconf->check_all == ON && dconf->json_fmt == ON) { 689 _mod_resource_checker_logging_all(r, use_resources, dconf, sconf, cdata, r->pool); 690 } 691 692 return OK; 693 }
アクセス元IP・CPU使用量・メモリ使用量などかきあつめて、どこまで記録するかの設定に応じてロギング関数に投げてるのかな。
メモ
- 下部のモジュール定義の書き方、処理させたいタイミングに応じてhook関数を設定する、というやり方は他のApacheモジュールでも同じっぽくて、今後読むときはそこから見ていこう
- 様々なhookさせるポイントがあって、むずかしい。
- 調べてもあんまり情報でてこなくて辛い
ほとんど独り言みたいな内容になってしまった。おしまい