├── Changes ├── LICENSE ├── README.md ├── config └── src ├── ngx_http_sysguard_module.c ├── ngx_http_sysguard_module.h ├── ngx_http_sysguard_node.c ├── ngx_http_sysguard_node.h ├── ngx_http_sysguard_sysinfo.c ├── ngx_http_sysguard_sysinfo.h ├── ngx_http_sysguard_variables.c └── ngx_http_sysguard_variables.h /Changes: -------------------------------------------------------------------------------- 1 | v0.1.0 [Thu Feb 23 2017 YoungJoo.Kim ] 2 | * The first version. 3 | 4 | * Feature: changed the algorithm for calculating response time 5 | in sysguard_rt directive to avoid being stuck in 503 after redirect. 6 | 7 | * Feature: added "method=" option in sysguard_rt directive. 8 | 9 | * Feature: added embedded Variables. 10 | 11 | # vi:set ft=changelog ts=4 sw=4 et fdm=marker: 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2010-2015 Alibaba Group Holding Limited 2 | Copyright (C) 2017, YoungJoo.Kim 3 | 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without modification, 7 | are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 20 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 22 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 25 | OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nginx sysguard module 2 | ========== 3 | 4 | [![License](http://img.shields.io/badge/license-BSD-brightgreen.svg)](https://github.com/vozlt/nginx-module-sysguard/blob/master/LICENSE) 5 | 6 | Nginx sysguard module 7 | 8 | Table of Contents 9 | ================= 10 | 11 | * [Version](#version) 12 | * [Dependencies](#dependencies) 13 | * [Compatibility](#compatibility) 14 | * [Installation](#installation) 15 | * [Synopsis](#synopsis) 16 | * [Description](#description) 17 | * [Embedded Variables](#embedded-variables) 18 | * [Directives](#directives) 19 | * [sysguard](#sysguard) 20 | * [sysguard_load](#sysguard_load) 21 | * [sysguard_mem](#sysguard_mem) 22 | * [sysguard_rt](#sysguard_rt) 23 | * [sysguard_mode](#sysguard_mode) 24 | * [sysguard_interval](#sysguard_interval) 25 | * [sysguard_log_level](#sysguard_log_level) 26 | * [See Also](#see-also) 27 | * [TODO](#todo) 28 | * [Donation](#donation) 29 | * [Author](#Author) 30 | 31 | ## Version 32 | This document describes nginx-module-sysguard `v0.1.0` released on 23 Feb 2017. 33 | 34 | ## Dependencies 35 | * [nginx](http://nginx.org) 36 | * sysinfo(2) \| getloadavg(3) 37 | * /proc/meminfo 38 | 39 | ## Compatibility 40 | * 1.11.x (last tested: 1.11.10) 41 | 42 | Earlier versions is not tested. 43 | 44 | 45 | ## Installation 46 | 47 | 1. Clone the git repository. 48 | 49 | ``` 50 | shell> git clone git://github.com/vozlt/nginx-module-sysguard.git 51 | ``` 52 | 53 | 2. Add the module to the build configuration by adding 54 | ``` 55 | --add-module=/path/to/nginx-module-sysguard 56 | ``` 57 | 58 | 3. Build the nginx binary. 59 | 60 | 4. Install the nginx binary. 61 | 62 | ## Synopsis 63 | 64 | ```Nginx 65 | http { 66 | 67 | ... 68 | 69 | server { 70 | 71 | ... 72 | 73 | sysguard on; 74 | sysguard_mode or; 75 | 76 | sysguard_load load=10.5 action=/loadlimit; 77 | sysguard_mem swapratio=20% action=/swaplimit; 78 | sysguard_mem free=100M action=/freelimit; 79 | sysguard_rt rt=0.01 period=5s method=AMM:10 action=/rtlimit; 80 | 81 | location /loadlimit { 82 | return 503; 83 | } 84 | 85 | location /swaplimit { 86 | return 503; 87 | } 88 | 89 | location /freelimit { 90 | return 503; 91 | } 92 | 93 | location /rtlimit { 94 | return 503; 95 | } 96 | } 97 | 98 | ... 99 | 100 | server { 101 | 102 | ... 103 | 104 | location /api { 105 | sysguard on; 106 | sysguard_mode or; 107 | sysguard_load load=20 action=/limit; 108 | sysguard_mem swapratio=10% action=/limit; 109 | sysguard_rt rt=2.01 period=5s method=WMA:10 action=/limit; 110 | 111 | ... 112 | 113 | } 114 | 115 | location /images { 116 | sysguard on; 117 | sysguard_mode and; 118 | sysguard_load load=20 action=/limit; 119 | sysguard_mem swapratio=10% action=/limit; 120 | sysguard_rt rt=2.01 period=5s method=WMA:10 action=/limit; 121 | 122 | ... 123 | 124 | } 125 | 126 | location /limit { 127 | return 503; 128 | } 129 | } 130 | 131 | } 132 | ``` 133 | 134 | ## Description 135 | This module can be used to protect your server in case system load, memory use goes too high or requests are responded too slow. 136 | This is a porting version of the [sysguard](http://tengine.taobao.org/document/http_sysguard.html) in [tengine](https://github.com/alibaba/tengine) to the pure NGINX so as to support the same features. 137 | 138 | `Caveats:` Note this module requires the sysinfo(2) system call, or getloadavg(3) function in glibc. It also requires the /proc file system to get memory information. 139 | 140 | ## Embedded Variables 141 | The following embedded variables are provided: 142 | 143 | * **$sysguard_load** 144 | * The load of system. If `$sysguard_load`'s value is 100, then load is 0.1(100/1000). (/msec) 145 | * **$sysguard_swapstat** 146 | * The ratio of using swap. (/per) 147 | * **$sysguard_free** 148 | * The real free space of memory. (/byte) 149 | * **$sysguard_rt** 150 | * The average of request processing times. If `$sysguard_rt`'s value is 100, then response time is 0.1sec(100/1000). (/msec) 151 | * **$sysguard_meminfo_totalram** 152 | * The total memory of meminfo. (/byte) 153 | * **$sysguard_meminfo_freeram** 154 | * The free memory of meminfo. (/byte) 155 | * **$sysguard_meminfo_bufferram** 156 | * The buffer memory of meminfo. (/byte) 157 | * **$sysguard_meminfo_cachedram** 158 | * The cached memory of meminfo. (/byte) 159 | * **$sysguard_meminfo_totalswap** 160 | * The total swap of meminfo. (/byte) 161 | * **$sysguard_meminfo_freeswap** 162 | * The free swap of meminfo. (/byte) 163 | 164 | 165 | ## Directives 166 | 167 | ### sysguard 168 | 169 | | - | - | 170 | | --- | --- | 171 | | **Syntax** | **sysguard** \ | 172 | | **Default** | off | 173 | | **Context** | http, server, location | 174 | 175 | `Description:` Enables or disables the module working. 176 | 177 | ### sysguard_load 178 | 179 | | - | - | 180 | | --- | --- | 181 | | **Syntax** | **sysguard_load** load=*number* [action=*/url*] | 182 | | **Default** | - | 183 | | **Context** | http, server, location | 184 | 185 | `Description:` Specify the load threshold. When the system load exceeds this threshold, all subsequent requests will be redirected to the URL specified by the 'action' parameter. It will return 503 if there's no 'action' URL defined. This directive also support using ncpuratio to instead of the fixed threshold, 'ncpu' means the number of cpu's cores, you can use this directive like this: load=ncpu1.5 186 | 187 | ### sysguard_mem 188 | 189 | | - | - | 190 | | --- | --- | 191 | | **Syntax** | **sysguard_mem** swapratio=*ratio*% free=*size* [action=*/url*] | 192 | | **Default** | - | 193 | | **Context** | http, server, location | 194 | 195 | `Description:` Specify the used swap memory or free memory threshold. When the swap memory use ratio exceeds this threshold or memory free less than the size, all subsequent requests will be redirected to the URL specified by the 'action' parameter. It will return 503 if there's no 'action' URL. Sysguard uses this strategy to calculate memory free: "memfree = free + buffered + cached" 196 | 197 | ### sysguard_rt 198 | 199 | | - | - | 200 | | --- | --- | 201 | | **Syntax** | **sysguard_rt** rt=*second* period=*time* [method=\:*number*] [action=*/url*] | 202 | | **Default** | - | 203 | | **Context** | http, server, location | 204 | 205 | `Description:` Specify the response time threshold. 206 | Parameter rt is used to set a threshold of the average response time, in second. 207 | Parameter period is used to specify the period of the statistics cycle. 208 | If the average response time of the system exceeds the threshold specified by the user, 209 | the incoming request will be redirected to a specified url which is defined by parameter 'action'. 210 | If no 'action' is presented, the request will be responsed with 503 error directly. 211 | The `method` is a formula that calculate the average of response processing times. 212 | The `number` in method is the number of samples to calculate the average. 213 | The default method is set to be `method=AMM:period`. 214 | 215 | * **AMM** 216 | * The AMM is the [arithmetic mean](https://en.wikipedia.org/wiki/Arithmetic_mean). 217 | * **WMA** 218 | * THE WMA is the [weighted moving average](https://en.wikipedia.org/wiki/Moving_average#Weighted_moving_average). 219 | 220 | ### sysguard_mode 221 | 222 | | - | - | 223 | | --- | --- | 224 | | **Syntax** | **sysguard_mode** \ | 225 | | **Default** | or | 226 | | **Context** | http, server, location | 227 | 228 | `Description:` If there are more than one type of monitor, this directive is used to specified the relations among all the monitors which are: 'and' for all matching and 'or' for any matching. 229 | 230 | ### sysguard_interval 231 | 232 | | - | - | 233 | | --- | --- | 234 | | **Syntax** | **sysguard_interval** *time* | 235 | | **Default** | 1s | 236 | | **Context** | http, server, location | 237 | 238 | `Description:` Specify the time interval to update your system information. 239 | The default value is one second, which means sysguard updates the server status once a second. 240 | 241 | ### sysguard_log_level 242 | 243 | | - | - | 244 | | --- | --- | 245 | | **Syntax** | **sysguard_log_level** \ | 246 | | **Default** | error | 247 | | **Context** | http, server, location | 248 | 249 | `Description:` Specify the log level of sysguard. 250 | 251 | ## See Also 252 | * [nginx-module-vts](https://github.com/vozlt/nginx-module-vts) 253 | * [nginx-module-sts](https://github.com/vozlt/nginx-module-sts) 254 | 255 | ## TODO 256 | 257 | ## Donation 258 | [![License](http://img.shields.io/badge/PAYPAL-DONATE-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=PWWSYKQ9VKH38&lc=KR¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) 259 | 260 | ## Author 261 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 262 | * Copyright (C) 2017, YoungJoo.Kim \ 263 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_sysguard_module 2 | 3 | HTTP_SYSGUARD_SRCS=" \ 4 | $ngx_addon_dir/src/ngx_http_sysguard_module.c \ 5 | $ngx_addon_dir/src/ngx_http_sysguard_sysinfo.c \ 6 | $ngx_addon_dir/src/ngx_http_sysguard_node.c \ 7 | $ngx_addon_dir/src/ngx_http_sysguard_variables.c \ 8 | " 9 | 10 | HTTP_SYSGUARD_DEPS=" \ 11 | $ngx_addon_dir/src/ngx_http_sysguard_module.h \ 12 | $ngx_addon_dir/src/ngx_http_sysguard_sysinfo.h \ 13 | $ngx_addon_dir/src/ngx_http_sysguard_node.h \ 14 | $ngx_addon_dir/src/ngx_http_sysguard_variables.h \ 15 | " 16 | if test -n "$ngx_module_link"; then 17 | ngx_module_type=HTTP 18 | ngx_module_name=$ngx_addon_name 19 | ngx_module_srcs="$HTTP_SYSGUARD_SRCS" 20 | ngx_module_deps="$HTTP_SYSGUARD_DEPS" 21 | 22 | . auto/module 23 | else 24 | HTTP_MODULES="$HTTP_MODULES $ngx_addon_name" 25 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $HTTP_SYSGUARD_SRCS" 26 | NGX_ADDON_DEPS="$NGX_ADDON_DEPS $HTTP_SYSGUARD_DEPS" 27 | fi 28 | 29 | 30 | ngx_feature="sysinfo()" 31 | ngx_feature_name="NGX_HAVE_SYSINFO" 32 | ngx_feature_run=no 33 | ngx_feature_incs="#include " 34 | ngx_feature_path= 35 | ngx_feature_libs= 36 | ngx_feature_test="struct sysinfo s; 37 | sysinfo(&s);" 38 | . auto/feature 39 | 40 | 41 | ngx_feature="getloadavg()" 42 | ngx_feature_name="NGX_HAVE_GETLOADAVG" 43 | ngx_feature_run=no 44 | ngx_feature_incs="#include " 45 | ngx_feature_path= 46 | ngx_feature_libs= 47 | ngx_feature_test="double loadavg[1]; 48 | getloadavg(loadavg, 1);" 49 | . auto/feature 50 | 51 | 52 | ngx_feature="/proc/meminfo" 53 | ngx_feature_name="NGX_HAVE_PROC_MEMINFO" 54 | ngx_feature_run=yes 55 | ngx_feature_incs="#include " 56 | ngx_feature_path= 57 | ngx_feature_libs= 58 | ngx_feature_test='int fd; 59 | if (open("/proc/meminfo", O_RDONLY) == -1) return 1;' 60 | . auto/feature 61 | 62 | ngx_feature="vm.stats" 63 | ngx_feature_name="NGX_HAVE_VM_STATS" 64 | ngx_feature_run=yes 65 | ngx_feature_incs="#include " 66 | ngx_feature_path= 67 | ngx_feature_libs= 68 | ngx_feature_test='size_t vl; 69 | size_t sz = sizeof(vl); 70 | if (sysctlbyname("vm.stats.vm.v_free_count", &vl, &sz, NULL, 0) == -1) return 1;' 71 | . auto/feature 72 | 73 | # vi:set ft=sh ts=4 sw=4 et fdm=marker: 74 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 3 | * Copyright (C) YoungJoo Kim (vozlt) 4 | */ 5 | 6 | 7 | #include "ngx_http_sysguard_module.h" 8 | #include "ngx_http_sysguard_variables.h" 9 | 10 | 11 | static void *ngx_http_sysguard_create_conf(ngx_conf_t *cf); 12 | static char *ngx_http_sysguard_merge_conf(ngx_conf_t *cf, void *parent, 13 | void *child); 14 | static char *ngx_http_sysguard_load(ngx_conf_t *cf, ngx_command_t *cmd, 15 | void *conf); 16 | static char *ngx_http_sysguard_mem(ngx_conf_t *cf, ngx_command_t *cmd, 17 | void *conf); 18 | static char *ngx_http_sysguard_rt(ngx_conf_t *cf, 19 | ngx_command_t *cmd, void *conf); 20 | static ngx_int_t ngx_http_sysguard_init(ngx_conf_t *cf); 21 | 22 | 23 | static ngx_conf_enum_t ngx_http_sysguard_log_levels[] = { 24 | { ngx_string("info"), NGX_LOG_INFO }, 25 | { ngx_string("notice"), NGX_LOG_NOTICE }, 26 | { ngx_string("warn"), NGX_LOG_WARN }, 27 | { ngx_string("error"), NGX_LOG_ERR }, 28 | { ngx_null_string, 0 } 29 | }; 30 | 31 | 32 | static ngx_conf_enum_t ngx_http_sysguard_modes[] = { 33 | { ngx_string("or"), NGX_HTTP_SYSGUARD_MODE_OR }, 34 | { ngx_string("and"), NGX_HTTP_SYSGUARD_MODE_AND }, 35 | { ngx_null_string, 0 } 36 | }; 37 | 38 | 39 | static ngx_command_t ngx_http_sysguard_commands[] = { 40 | 41 | { ngx_string("sysguard"), 42 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 43 | ngx_conf_set_flag_slot, 44 | NGX_HTTP_LOC_CONF_OFFSET, 45 | offsetof(ngx_http_sysguard_conf_t, enable), 46 | NULL }, 47 | 48 | { ngx_string("sysguard_mode"), 49 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, 50 | ngx_conf_set_enum_slot, 51 | NGX_HTTP_LOC_CONF_OFFSET, 52 | offsetof(ngx_http_sysguard_conf_t, mode), 53 | &ngx_http_sysguard_modes }, 54 | 55 | { ngx_string("sysguard_load"), 56 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, 57 | ngx_http_sysguard_load, 58 | NGX_HTTP_LOC_CONF_OFFSET, 59 | 0, 60 | NULL }, 61 | 62 | { ngx_string("sysguard_mem"), 63 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, 64 | ngx_http_sysguard_mem, 65 | NGX_HTTP_LOC_CONF_OFFSET, 66 | 0, 67 | NULL }, 68 | 69 | { ngx_string("sysguard_rt"), 70 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, 71 | ngx_http_sysguard_rt, 72 | NGX_HTTP_LOC_CONF_OFFSET, 73 | 0, 74 | NULL }, 75 | 76 | { ngx_string("sysguard_interval"), 77 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 78 | ngx_conf_set_sec_slot, 79 | NGX_HTTP_LOC_CONF_OFFSET, 80 | offsetof(ngx_http_sysguard_conf_t, interval), 81 | NULL }, 82 | 83 | { ngx_string("sysguard_log_level"), 84 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, 85 | ngx_conf_set_enum_slot, 86 | NGX_HTTP_LOC_CONF_OFFSET, 87 | offsetof(ngx_http_sysguard_conf_t, log_level), 88 | &ngx_http_sysguard_log_levels }, 89 | 90 | ngx_null_command 91 | }; 92 | 93 | 94 | static ngx_http_module_t ngx_http_sysguard_module_ctx = { 95 | ngx_http_sysguard_add_variables, /* preconfiguration */ 96 | ngx_http_sysguard_init, /* postconfiguration */ 97 | 98 | NULL, /* create main configuration */ 99 | NULL, /* init main configuration */ 100 | 101 | NULL, /* create server configuration */ 102 | NULL, /* merge server configuration */ 103 | 104 | ngx_http_sysguard_create_conf, /* create location configuration */ 105 | ngx_http_sysguard_merge_conf /* merge location configuration */ 106 | }; 107 | 108 | 109 | ngx_module_t ngx_http_sysguard_module = { 110 | NGX_MODULE_V1, 111 | &ngx_http_sysguard_module_ctx, /* module context */ 112 | ngx_http_sysguard_commands, /* module directives */ 113 | NGX_HTTP_MODULE, /* module type */ 114 | NULL, /* init master */ 115 | NULL, /* init module */ 116 | NULL, /* init process */ 117 | NULL, /* init thread */ 118 | NULL, /* exit thread */ 119 | NULL, /* exit process */ 120 | NULL, /* exit master */ 121 | NGX_MODULE_V1_PADDING 122 | }; 123 | 124 | 125 | static ngx_int_t 126 | ngx_http_sysguard_update_load(ngx_http_request_t *r, time_t exptime) 127 | { 128 | ngx_int_t load, rc; 129 | ngx_http_sysguard_conf_t *glcf; 130 | 131 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 132 | 133 | glcf->sysinfo.cached_load_exptime = ngx_time() + exptime; 134 | 135 | rc = ngx_http_sysguard_getloadavg(&load, 1, r->connection->log); 136 | if (rc == NGX_ERROR) { 137 | glcf->sysinfo.cached_load = 0; 138 | 139 | return NGX_ERROR; 140 | } 141 | 142 | glcf->sysinfo.cached_load = load; 143 | 144 | return NGX_OK; 145 | } 146 | 147 | 148 | static ngx_int_t 149 | ngx_http_sysguard_update_mem(ngx_http_request_t *r, time_t exptime) 150 | { 151 | ngx_int_t rc; 152 | ngx_http_sysguard_meminfo_t m; 153 | ngx_http_sysguard_conf_t *glcf; 154 | 155 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 156 | 157 | glcf->sysinfo.cached_mem_exptime = ngx_time() + exptime; 158 | 159 | rc = ngx_http_sysguard_getmeminfo(&m, r->connection->log); 160 | if (rc == NGX_ERROR) { 161 | glcf->sysinfo.cached_swapstat = 0; 162 | glcf->sysinfo.cached_free = NGX_CONF_UNSET_SIZE; 163 | 164 | return NGX_ERROR; 165 | } 166 | 167 | glcf->sysinfo.meminfo = m; 168 | glcf->sysinfo.cached_swapstat = (m.totalswap == 0) 169 | ? 0 170 | : (m.totalswap - m.freeswap) * 100 / m.totalswap; 171 | glcf->sysinfo.cached_free = m.freeram + m.cachedram + m.bufferram; 172 | 173 | return NGX_OK; 174 | } 175 | 176 | 177 | static ngx_int_t 178 | ngx_http_sysguard_update_rt(ngx_http_request_t *r, time_t exptime) 179 | { 180 | ngx_http_sysguard_conf_t *glcf; 181 | 182 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 183 | 184 | glcf->sysinfo.cached_rt_exptime = ngx_time() + exptime; 185 | 186 | glcf->sysinfo.cached_rt = (glcf->rt_method == NGX_HTTP_SYSGUARD_AVERAGE_AMM) 187 | ? ngx_http_sysguard_node_time_ring_average_amm( 188 | r, &glcf->request_times) 189 | : ngx_http_sysguard_node_time_ring_average_wma( 190 | r, &glcf->request_times); 191 | 192 | return NGX_OK; 193 | } 194 | 195 | 196 | void 197 | ngx_http_sysguard_update_rt_node(ngx_http_request_t *r) 198 | { 199 | ngx_http_sysguard_conf_t *glcf; 200 | 201 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 202 | 203 | if (!glcf->enable) { 204 | return; 205 | } 206 | 207 | if (glcf->rt == NGX_CONF_UNSET) { 208 | return; 209 | } 210 | 211 | ngx_http_sysguard_node_time_ring_insert(&glcf->request_times, 212 | ngx_http_sysguard_request_time(r)); 213 | } 214 | 215 | 216 | static ngx_int_t 217 | ngx_http_sysguard_do_redirect(ngx_http_request_t *r, ngx_str_t *path) 218 | { 219 | if (path->len == 0) { 220 | return NGX_HTTP_SERVICE_UNAVAILABLE; 221 | } else if (path->data[0] == '@') { 222 | (void) ngx_http_named_location(r, path); 223 | } else { 224 | (void) ngx_http_internal_redirect(r, path, &r->args); 225 | } 226 | 227 | ngx_http_finalize_request(r, NGX_DONE); 228 | 229 | return NGX_DONE; 230 | } 231 | 232 | 233 | static ngx_int_t 234 | ngx_http_sysguard_handler(ngx_http_request_t *r) 235 | { 236 | ngx_int_t load_log = 0, swap_log = 0, 237 | free_log = 0, rt_log = 0; 238 | ngx_str_t *action = NULL; 239 | ngx_http_sysguard_conf_t *glcf; 240 | 241 | 242 | /* 243 | * About ignoring the subrequests: 244 | * 245 | * The below is not guaranteed but it works well in general. 246 | * 247 | * if (r->main->count != 1) { 248 | * return NGX_DECLINED; 249 | * } 250 | */ 251 | 252 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 253 | 254 | if (!glcf->enable) { 255 | return NGX_DECLINED; 256 | } 257 | 258 | /* load */ 259 | 260 | if (glcf->load != NGX_CONF_UNSET) { 261 | 262 | if (glcf->sysinfo.cached_load_exptime < ngx_time()) { 263 | ngx_http_sysguard_update_load(r, glcf->interval); 264 | } 265 | 266 | ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 267 | "http sysguard handler load: %1.3f %1.3f %V %V", 268 | glcf->sysinfo.cached_load * 1.0 / 1000, 269 | glcf->load * 1.0 / 1000, 270 | &r->uri, 271 | &glcf->load_action); 272 | 273 | if (glcf->sysinfo.cached_load > glcf->load) { 274 | 275 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_OR) { 276 | 277 | ngx_log_error(glcf->log_level, r->connection->log, 0, 278 | "sysguard load limited, current:%1.3f conf:%1.3f", 279 | glcf->sysinfo.cached_load * 1.0 / 1000, 280 | glcf->load * 1.0 / 1000); 281 | 282 | return ngx_http_sysguard_do_redirect(r, &glcf->load_action); 283 | } else { 284 | action = &glcf->load_action; 285 | load_log = 1; 286 | } 287 | } else { 288 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_AND) { 289 | goto out; 290 | } 291 | } 292 | } 293 | 294 | /* swap */ 295 | 296 | if (glcf->swap != NGX_CONF_UNSET) { 297 | 298 | if (glcf->sysinfo.cached_mem_exptime < ngx_time()) { 299 | ngx_http_sysguard_update_mem(r, glcf->interval); 300 | } 301 | 302 | ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 303 | "http sysguard handler swap: %i %i %V %V", 304 | glcf->sysinfo.cached_swapstat, 305 | glcf->swap, 306 | &r->uri, 307 | &glcf->swap_action); 308 | 309 | if (glcf->sysinfo.cached_swapstat > glcf->swap) { 310 | 311 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_OR) { 312 | 313 | ngx_log_error(glcf->log_level, r->connection->log, 0, 314 | "sysguard swap limited, current:%i conf:%i", 315 | glcf->sysinfo.cached_swapstat, 316 | glcf->swap); 317 | 318 | return ngx_http_sysguard_do_redirect(r, &glcf->swap_action); 319 | } else { 320 | action = &glcf->swap_action; 321 | swap_log = 1; 322 | } 323 | } else { 324 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_AND) { 325 | goto out; 326 | } 327 | } 328 | } 329 | 330 | /* mem free */ 331 | 332 | if (glcf->free != NGX_CONF_UNSET_SIZE) { 333 | 334 | if (glcf->sysinfo.cached_mem_exptime < ngx_time()) { 335 | ngx_http_sysguard_update_mem(r, glcf->interval); 336 | } 337 | 338 | if (glcf->sysinfo.cached_free != NGX_CONF_UNSET_SIZE) { 339 | 340 | ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 341 | "http sysguard handler free: %uz %uz %V %V", 342 | glcf->sysinfo.cached_free, 343 | glcf->free, 344 | &r->uri, 345 | &glcf->free_action); 346 | 347 | if (glcf->sysinfo.cached_free < glcf->free) { 348 | 349 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_OR) { 350 | 351 | ngx_log_error(glcf->log_level, r->connection->log, 0, 352 | "sysguard free limited, " 353 | "current:%uzM conf:%uzM", 354 | glcf->sysinfo.cached_free / 1024 / 1024, 355 | glcf->free / 1024 / 1024); 356 | 357 | return ngx_http_sysguard_do_redirect(r, &glcf->free_action); 358 | } else { 359 | action = &glcf->free_action; 360 | free_log = 1; 361 | } 362 | } else { 363 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_AND) { 364 | goto out; 365 | } 366 | } 367 | } 368 | } 369 | 370 | /* response time */ 371 | 372 | if (glcf->rt != NGX_CONF_UNSET) { 373 | 374 | if (glcf->sysinfo.cached_rt_exptime < ngx_time()) { 375 | ngx_http_sysguard_update_rt(r, glcf->interval); 376 | } 377 | 378 | ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 379 | "http sysguard handler rt: %1.3f %1.3f", 380 | glcf->sysinfo.cached_rt * 1.0 / 1000, 381 | glcf->rt * 1.0 / 1000); 382 | 383 | if (glcf->sysinfo.cached_rt > glcf->rt) { 384 | 385 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_OR) { 386 | 387 | ngx_log_error(glcf->log_level, r->connection->log, 0, 388 | "sysguard rt limited, current:%1.3f conf:%1.3f", 389 | glcf->sysinfo.cached_rt * 1.0 / 1000, 390 | glcf->rt * 1.0 / 1000); 391 | 392 | return ngx_http_sysguard_do_redirect(r, &glcf->rt_action); 393 | } else { 394 | action = &glcf->rt_action; 395 | rt_log = 1; 396 | } 397 | } else { 398 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_AND) { 399 | goto out; 400 | } 401 | } 402 | } 403 | 404 | if (glcf->mode == NGX_HTTP_SYSGUARD_MODE_AND && action) { 405 | 406 | if (load_log) { 407 | ngx_log_error(glcf->log_level, r->connection->log, 0, 408 | "sysguard load limited, current:%1.3f conf:%1.3f", 409 | glcf->sysinfo.cached_load * 1.0 / 1000, 410 | glcf->load * 1.0 / 1000); 411 | } 412 | 413 | if (swap_log) { 414 | ngx_log_error(glcf->log_level, r->connection->log, 0, 415 | "sysguard swap limited, current:%i conf:%i", 416 | glcf->sysinfo.cached_swapstat, 417 | glcf->swap); 418 | } 419 | 420 | if (free_log) { 421 | ngx_log_error(glcf->log_level, r->connection->log, 0, 422 | "sysguard free limited, current:%uzM conf:%uzM", 423 | glcf->sysinfo.cached_free / 1024 / 1024, 424 | glcf->free / 1024 / 1024); 425 | } 426 | 427 | if (rt_log) { 428 | ngx_log_error(glcf->log_level, r->connection->log, 0, 429 | "sysguard rt limited, current:%1.3f conf:%1.3f", 430 | glcf->sysinfo.cached_rt * 1.0 / 1000, 431 | glcf->rt * 1.0 / 1000); 432 | } 433 | 434 | return ngx_http_sysguard_do_redirect(r, action); 435 | } 436 | 437 | out: 438 | return NGX_DECLINED; 439 | } 440 | 441 | 442 | ngx_msec_int_t 443 | ngx_http_sysguard_request_time(ngx_http_request_t *r) 444 | { 445 | ngx_time_t *tp; 446 | ngx_msec_int_t ms; 447 | 448 | tp = ngx_timeofday(); 449 | 450 | ms = (ngx_msec_int_t) 451 | ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec)); 452 | return ngx_max(ms, 0); 453 | } 454 | 455 | 456 | static void * 457 | ngx_http_sysguard_create_conf(ngx_conf_t *cf) 458 | { 459 | ngx_http_sysguard_conf_t *conf; 460 | 461 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sysguard_conf_t)); 462 | if (conf == NULL) { 463 | return NGX_CONF_ERROR; 464 | } 465 | 466 | /* 467 | * set by ngx_pcalloc(): 468 | * 469 | * conf->load_action = {0, NULL}; 470 | * conf->swap_action = {0, NULL}; 471 | * conf->rt_action = {0, NULL}; 472 | * conf->ring = NULL; 473 | */ 474 | 475 | conf->enable = NGX_CONF_UNSET; 476 | conf->load = NGX_CONF_UNSET; 477 | conf->swap = NGX_CONF_UNSET; 478 | conf->free = NGX_CONF_UNSET_SIZE; 479 | conf->rt = NGX_CONF_UNSET; 480 | conf->rt_period = NGX_CONF_UNSET; 481 | conf->rt_number = NGX_CONF_UNSET; 482 | conf->rt_method = NGX_CONF_UNSET; 483 | conf->interval = NGX_CONF_UNSET; 484 | conf->log_level = NGX_CONF_UNSET_UINT; 485 | conf->mode = NGX_CONF_UNSET_UINT; 486 | 487 | return conf; 488 | } 489 | 490 | 491 | static char * 492 | ngx_http_sysguard_merge_conf(ngx_conf_t *cf, void *parent, void *child) 493 | { 494 | ngx_http_sysguard_conf_t *prev = parent; 495 | ngx_http_sysguard_conf_t *conf = child; 496 | 497 | ngx_conf_merge_value(conf->enable, prev->enable, 0); 498 | 499 | ngx_conf_merge_str_value(conf->load_action, prev->load_action, ""); 500 | ngx_conf_merge_str_value(conf->swap_action, prev->swap_action, ""); 501 | ngx_conf_merge_str_value(conf->free_action, prev->free_action, ""); 502 | ngx_conf_merge_str_value(conf->rt_action, prev->rt_action, ""); 503 | 504 | ngx_conf_merge_value(conf->load, prev->load, NGX_CONF_UNSET); 505 | ngx_conf_merge_value(conf->swap, prev->swap, NGX_CONF_UNSET); 506 | ngx_conf_merge_size_value(conf->free, prev->free, NGX_CONF_UNSET_SIZE); 507 | ngx_conf_merge_value(conf->rt, prev->rt, NGX_CONF_UNSET); 508 | 509 | ngx_conf_merge_value(conf->rt_period, prev->rt_period, 1); 510 | ngx_conf_merge_value(conf->rt_number, prev->rt_number, conf->rt_period); 511 | ngx_conf_merge_value(conf->rt_method, prev->rt_method, NGX_HTTP_SYSGUARD_AVERAGE_AMM); 512 | 513 | ngx_conf_merge_value(conf->interval, prev->interval, 1); 514 | ngx_conf_merge_uint_value(conf->log_level, prev->log_level, NGX_LOG_ERR); 515 | ngx_conf_merge_uint_value(conf->mode, prev->mode, NGX_HTTP_SYSGUARD_MODE_OR); 516 | 517 | ngx_memzero(&conf->sysinfo, sizeof(conf->sysinfo)); 518 | 519 | if (conf->rt != NGX_CONF_UNSET) { 520 | ngx_http_sysguard_node_time_ring_init(&conf->request_times, conf->rt_number); 521 | 522 | conf->request_times.times = ngx_pcalloc(cf->pool, 523 | sizeof(ngx_http_sysguard_node_time_t) * conf->rt_number); 524 | 525 | if (conf->request_times.times == NULL) { 526 | return NGX_CONF_ERROR; 527 | } 528 | } 529 | 530 | return NGX_CONF_OK; 531 | } 532 | 533 | 534 | static char * 535 | ngx_http_sysguard_load(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 536 | { 537 | ngx_http_sysguard_conf_t *glcf = conf; 538 | 539 | ngx_str_t *value; 540 | ngx_uint_t i, scale; 541 | 542 | value = cf->args->elts; 543 | i = 1; 544 | scale = 1; 545 | 546 | if (ngx_strncmp(value[i].data, "load=", 5) == 0) { 547 | 548 | if (glcf->load != NGX_CONF_UNSET) { 549 | return "is duplicate"; 550 | } 551 | 552 | if (value[i].len == 5) { 553 | goto invalid; 554 | } 555 | 556 | value[i].data += 5; 557 | value[i].len -= 5; 558 | 559 | if (ngx_strncmp(value[i].data, "ncpu*", 5) == 0) { 560 | value[i].data += 5; 561 | value[i].len -= 5; 562 | scale = ngx_ncpu; 563 | } 564 | 565 | glcf->load = ngx_atofp(value[i].data, value[i].len, 3); 566 | if (glcf->load == NGX_ERROR) { 567 | goto invalid; 568 | } 569 | 570 | glcf->load = glcf->load * scale; 571 | 572 | if (cf->args->nelts == 2) { 573 | return NGX_CONF_OK; 574 | } 575 | 576 | i++; 577 | 578 | if (ngx_strncmp(value[i].data, "action=", 7) != 0) { 579 | goto invalid; 580 | } 581 | 582 | if (value[i].len == 7) { 583 | goto invalid; 584 | } 585 | 586 | if (value[i].data[7] != '/' && value[i].data[7] != '@') { 587 | goto invalid; 588 | } 589 | 590 | glcf->load_action.data = value[i].data + 7; 591 | glcf->load_action.len = value[i].len - 7; 592 | 593 | return NGX_CONF_OK; 594 | } 595 | 596 | invalid: 597 | 598 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 599 | "invalid parameter \"%V\"", &value[i]); 600 | 601 | return NGX_CONF_ERROR; 602 | } 603 | 604 | 605 | static char * 606 | ngx_http_sysguard_mem(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 607 | { 608 | ngx_http_sysguard_conf_t *glcf = conf; 609 | 610 | ngx_str_t *value, ss; 611 | ngx_uint_t i; 612 | 613 | value = cf->args->elts; 614 | i = 1; 615 | 616 | if (ngx_strncmp(value[i].data, "swapratio=", 10) == 0) { 617 | 618 | if (glcf->swap != NGX_CONF_UNSET) { 619 | return "is duplicate"; 620 | } 621 | 622 | if (value[i].data[value[i].len - 1] != '%') { 623 | goto invalid; 624 | } 625 | 626 | glcf->swap = ngx_atofp(value[i].data + 10, value[i].len - 11, 2); 627 | if (glcf->swap == NGX_ERROR) { 628 | goto invalid; 629 | } 630 | 631 | if (cf->args->nelts == 2) { 632 | return NGX_CONF_OK; 633 | } 634 | 635 | i++; 636 | 637 | if (ngx_strncmp(value[i].data, "action=", 7) != 0) { 638 | goto invalid; 639 | } 640 | 641 | if (value[i].len == 7) { 642 | goto invalid; 643 | } 644 | 645 | if (value[i].data[7] != '/' && value[i].data[7] != '@') { 646 | goto invalid; 647 | } 648 | 649 | glcf->swap_action.data = value[i].data + 7; 650 | glcf->swap_action.len = value[i].len - 7; 651 | 652 | return NGX_CONF_OK; 653 | 654 | } else if (ngx_strncmp(value[i].data, "free=", 5) == 0) { 655 | 656 | if (glcf->free != NGX_CONF_UNSET_SIZE) { 657 | return "is duplicate"; 658 | } 659 | 660 | ss.data = value[i].data + 5; 661 | ss.len = value[i].len - 5; 662 | 663 | glcf->free = ngx_parse_size(&ss); 664 | if (glcf->free == (size_t) NGX_ERROR) { 665 | goto invalid; 666 | } 667 | 668 | if (cf->args->nelts == 2) { 669 | return NGX_CONF_OK; 670 | } 671 | 672 | i++; 673 | 674 | if (ngx_strncmp(value[i].data, "action=", 7) != 0) { 675 | goto invalid; 676 | } 677 | 678 | if (value[i].len == 7) { 679 | goto invalid; 680 | } 681 | 682 | if (value[i].data[7] != '/' && value[i].data[7] != '@') { 683 | goto invalid; 684 | } 685 | 686 | glcf->free_action.data = value[i].data + 7; 687 | glcf->free_action.len = value[i].len - 7; 688 | 689 | return NGX_CONF_OK; 690 | } 691 | 692 | invalid: 693 | 694 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 695 | "invalid parameter \"%V\"", &value[i]); 696 | 697 | return NGX_CONF_ERROR; 698 | } 699 | 700 | 701 | static char * 702 | ngx_http_sysguard_rt(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 703 | { 704 | ngx_http_sysguard_conf_t *glcf = conf; 705 | 706 | u_char *p; 707 | ngx_str_t *value, ss; 708 | ngx_uint_t i; 709 | 710 | value = cf->args->elts; 711 | 712 | for (i = 1; i < cf->args->nelts; i++) { 713 | if (ngx_strncmp(value[i].data, "rt=", 3) == 0) { 714 | 715 | if (glcf->rt != NGX_CONF_UNSET) { 716 | return "is duplicate"; 717 | } 718 | 719 | glcf->rt = ngx_atofp(value[i].data + 3, value[i].len - 3, 3); 720 | if (glcf->rt == NGX_ERROR) { 721 | goto invalid; 722 | } 723 | 724 | continue; 725 | } 726 | 727 | if (ngx_strncmp(value[i].data, "period=", 7) == 0) { 728 | 729 | ss.data = value[i].data + 7; 730 | ss.len = value[i].len - 7; 731 | 732 | glcf->rt_period = ngx_parse_time(&ss, 1); 733 | if (glcf->rt_period == NGX_ERROR) { 734 | goto invalid; 735 | } 736 | 737 | continue; 738 | } 739 | 740 | if (ngx_strncmp(value[i].data, "method=", 7) == 0) { 741 | 742 | ss.data = value[i].data + 7; 743 | ss.len = value[i].len - 7; 744 | 745 | if (ngx_strncmp(ss.data, "WMA", 3) == 0) { 746 | glcf->rt_method = NGX_HTTP_SYSGUARD_AVERAGE_WMA; 747 | 748 | } else if (ngx_strncmp(ss.data, "AMM", 3) == 0) { 749 | glcf->rt_method = NGX_HTTP_SYSGUARD_AVERAGE_AMM; 750 | 751 | } else { 752 | goto invalid; 753 | } 754 | 755 | p = (u_char *) ngx_strchr(ss.data, ':'); 756 | if (p == NULL) { 757 | continue; 758 | } 759 | 760 | ss.data = p + 1; 761 | ss.len = value[i].data + value[i].len - ss.data; 762 | glcf->rt_number = ngx_atoi(ss.data, ss.len); 763 | if (glcf->rt_number == NGX_ERROR) { 764 | goto invalid; 765 | } 766 | 767 | continue; 768 | } 769 | 770 | if (ngx_strncmp(value[i].data, "action=", 7) == 0) { 771 | 772 | if (value[i].len == 7) { 773 | goto invalid; 774 | } 775 | 776 | if (value[i].data[7] != '/' && value[i].data[7] != '@') { 777 | goto invalid; 778 | } 779 | 780 | glcf->rt_action.data = value[i].data + 7; 781 | glcf->rt_action.len = value[i].len - 7; 782 | 783 | continue; 784 | } 785 | } 786 | 787 | return NGX_CONF_OK; 788 | 789 | invalid: 790 | 791 | ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 792 | "invalid parameter \"%V\"", &value[i]); 793 | 794 | return NGX_CONF_ERROR; 795 | } 796 | 797 | 798 | static ngx_int_t 799 | ngx_http_sysguard_log_handler(ngx_http_request_t *r) 800 | { 801 | ngx_http_sysguard_update_rt_node(r); 802 | 803 | return NGX_OK; 804 | } 805 | 806 | 807 | static ngx_int_t 808 | ngx_http_sysguard_init(ngx_conf_t *cf) 809 | { 810 | ngx_http_handler_pt *h; 811 | ngx_http_core_main_conf_t *cmcf; 812 | 813 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 814 | 815 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers); 816 | if (h == NULL) { 817 | return NGX_ERROR; 818 | } 819 | 820 | *h = ngx_http_sysguard_handler; 821 | 822 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_LOG_PHASE].handlers); 823 | if (h == NULL) { 824 | return NGX_ERROR; 825 | } 826 | 827 | *h = ngx_http_sysguard_log_handler; 828 | 829 | return NGX_OK; 830 | } 831 | 832 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 833 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_module.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #ifndef _NGX_SYSGUARD_MODULE_H_INCLUDED_ 9 | #define _NGX_SYSGUARD_MODULE_H_INCLUDED_ 10 | 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "ngx_http_sysguard_sysinfo.h" 17 | #include "ngx_http_sysguard_node.h" 18 | 19 | #define NGX_HTTP_SYSGUARD_MODE_OR 0 20 | #define NGX_HTTP_SYSGUARD_MODE_AND 1 21 | 22 | #define ngx_http_sysguard_triangle(n) (unsigned) ( \ 23 | n * (n + 1) / 2 \ 24 | ) 25 | 26 | 27 | typedef struct { 28 | ngx_flag_t enable; 29 | 30 | ngx_int_t load; 31 | ngx_str_t load_action; 32 | 33 | ngx_int_t swap; 34 | ngx_str_t swap_action; 35 | 36 | size_t free; 37 | ngx_str_t free_action; 38 | 39 | ngx_int_t rt; 40 | ngx_int_t rt_period; 41 | ngx_int_t rt_number; 42 | ngx_int_t rt_method; 43 | ngx_str_t rt_action; 44 | 45 | time_t interval; 46 | ngx_uint_t log_level; 47 | ngx_uint_t mode; 48 | 49 | ngx_http_sysguard_sysinfo_t sysinfo; 50 | ngx_http_sysguard_node_time_ring_t request_times; 51 | } ngx_http_sysguard_conf_t; 52 | 53 | 54 | ngx_msec_int_t ngx_http_sysguard_request_time(ngx_http_request_t *r); 55 | 56 | extern ngx_module_t ngx_http_sysguard_module; 57 | 58 | 59 | #endif /* _NGX_SYSGUARD_MODULE_H_INCLUDED_ */ 60 | 61 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 62 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_node.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #include "ngx_http_sysguard_module.h" 9 | 10 | 11 | void 12 | ngx_http_sysguard_node_time_ring_zero( 13 | ngx_http_sysguard_node_time_ring_t *q) 14 | { 15 | ngx_memzero(q, sizeof(ngx_http_sysguard_node_time_ring_t)); 16 | } 17 | 18 | 19 | void 20 | ngx_http_sysguard_node_time_ring_init( 21 | ngx_http_sysguard_node_time_ring_t *q, 22 | size_t len) 23 | { 24 | ngx_http_sysguard_node_time_ring_zero(q); 25 | q->rear = len - 1; 26 | q->len = len; 27 | } 28 | 29 | 30 | ngx_int_t 31 | ngx_http_sysguard_node_time_ring_push( 32 | ngx_http_sysguard_node_time_ring_t *q, 33 | ngx_msec_int_t x) 34 | { 35 | if ((q->rear + 1) % q->len == q->front) { 36 | return NGX_ERROR; 37 | } 38 | 39 | q->times[q->rear].time = ngx_current_msec; 40 | q->times[q->rear].msec = x; 41 | q->rear = (q->rear + 1) % q->len; 42 | 43 | return NGX_OK; 44 | } 45 | 46 | 47 | ngx_int_t 48 | ngx_http_sysguard_node_time_ring_pop( 49 | ngx_http_sysguard_node_time_ring_t *q, 50 | ngx_http_sysguard_node_time_t *x) 51 | { 52 | if (q->front == q->rear) { 53 | return NGX_ERROR; 54 | } 55 | 56 | *x = q->times[q->front]; 57 | q->front = (q->front + 1) % q->len; 58 | 59 | return NGX_OK; 60 | } 61 | 62 | 63 | void 64 | ngx_http_sysguard_node_time_ring_insert( 65 | ngx_http_sysguard_node_time_ring_t *q, 66 | ngx_msec_int_t x) 67 | { 68 | ngx_int_t rc; 69 | ngx_http_sysguard_node_time_t rx; 70 | rc = ngx_http_sysguard_node_time_ring_pop(q, &rx) 71 | | ngx_http_sysguard_node_time_ring_push(q, x); 72 | 73 | if (rc != NGX_OK) { 74 | ngx_http_sysguard_node_time_ring_init(q, q->len); 75 | } 76 | } 77 | 78 | 79 | ngx_msec_t 80 | ngx_http_sysguard_node_time_ring_average_amm( 81 | ngx_http_request_t *r, 82 | ngx_http_sysguard_node_time_ring_t *q) 83 | { 84 | ngx_int_t i, j, k; 85 | ngx_http_sysguard_conf_t *glcf; 86 | 87 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 88 | 89 | for (i = q->front, j = 1, k = 0; i != q->rear; i = (i + 1) % q->len, j++) { 90 | if (q->times[i].time + (glcf->rt_period * 1000) > ngx_current_msec) { 91 | k += (ngx_int_t) q->times[i].msec; 92 | } 93 | } 94 | 95 | if (j != q->len) { 96 | ngx_http_sysguard_node_time_ring_init(q, q->len); 97 | } 98 | 99 | return (ngx_msec_t) (k / (q->len - 1)); 100 | } 101 | 102 | 103 | ngx_msec_t 104 | ngx_http_sysguard_node_time_ring_average_wma( 105 | ngx_http_request_t *r, 106 | ngx_http_sysguard_node_time_ring_t *q) 107 | { 108 | ngx_int_t i, j, k; 109 | ngx_http_sysguard_conf_t *glcf; 110 | 111 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 112 | 113 | for (i = q->front, j = 1, k = 0; i != q->rear; i = (i + 1) % q->len, j++) { 114 | if (q->times[i].time + (glcf->rt_period * 1000) > ngx_current_msec) { 115 | k += (ngx_int_t) q->times[i].msec * j; 116 | } 117 | } 118 | 119 | if (j != q->len) { 120 | ngx_http_sysguard_node_time_ring_init(q, q->len); 121 | } 122 | 123 | return (ngx_msec_t) (k / (ngx_int_t) ngx_http_sysguard_triangle((q->len - 1))); 124 | } 125 | 126 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 127 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_node.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #ifndef _NGX_SYSGUARD_NODE_H_INCLUDED_ 9 | #define _NGX_SYSGUARD_NODE_H_INCLUDED_ 10 | 11 | 12 | #define NGX_HTTP_SYSGUARD_AVERAGE_AMM 0 13 | #define NGX_HTTP_SYSGUARD_AVERAGE_WMA 1 14 | 15 | 16 | typedef struct { 17 | ngx_msec_t time; 18 | ngx_msec_int_t msec; 19 | } ngx_http_sysguard_node_time_t; 20 | 21 | 22 | typedef struct { 23 | ngx_http_sysguard_node_time_t *times; 24 | ngx_int_t front; 25 | ngx_int_t rear; 26 | ngx_int_t len; 27 | } ngx_http_sysguard_node_time_ring_t; 28 | 29 | 30 | void ngx_http_sysguard_node_time_ring_zero( 31 | ngx_http_sysguard_node_time_ring_t *q); 32 | void ngx_http_sysguard_node_time_ring_init( 33 | ngx_http_sysguard_node_time_ring_t *q, 34 | size_t len); 35 | void ngx_http_sysguard_node_time_ring_insert( 36 | ngx_http_sysguard_node_time_ring_t *q, 37 | ngx_msec_int_t x); 38 | ngx_int_t ngx_http_sysguard_node_time_ring_push( 39 | ngx_http_sysguard_node_time_ring_t *q, 40 | ngx_msec_int_t x); 41 | ngx_int_t ngx_http_sysguard_node_time_ring_pop( 42 | ngx_http_sysguard_node_time_ring_t *q, 43 | ngx_http_sysguard_node_time_t *x); 44 | ngx_msec_t ngx_http_sysguard_node_time_ring_average_amm( 45 | ngx_http_request_t *r, 46 | ngx_http_sysguard_node_time_ring_t *q); 47 | ngx_msec_t ngx_http_sysguard_node_time_ring_average_wma( 48 | ngx_http_request_t *r, 49 | ngx_http_sysguard_node_time_ring_t *q); 50 | 51 | 52 | #endif /* _NGX_SYSGUARD_NODE_H_INCLUDED_ */ 53 | 54 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 55 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_sysinfo.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #include "ngx_http_sysguard_module.h" 9 | 10 | 11 | ngx_int_t 12 | ngx_http_sysguard_getloadavg(ngx_int_t avg[], ngx_int_t nelem, ngx_log_t *log) 13 | { 14 | #if (NGX_HAVE_GETLOADAVG) 15 | double loadavg[3]; 16 | ngx_int_t i; 17 | 18 | if (getloadavg(loadavg, nelem) == -1) { 19 | return NGX_ERROR; 20 | } 21 | 22 | for (i = 0; i < nelem; i ++) { 23 | avg[i] = loadavg[i] * 1000; 24 | } 25 | 26 | return NGX_OK; 27 | 28 | #elif (NGX_HAVE_SYSINFO) 29 | 30 | struct sysinfo s; 31 | ngx_int_t i; 32 | 33 | if (sysinfo(&s)) { 34 | return NGX_ERROR; 35 | } 36 | 37 | for (i = 0; i < nelem; i ++) { 38 | avg[i] = s.loads[i] * 1000 / 65536; 39 | } 40 | 41 | return NGX_OK; 42 | 43 | #else 44 | 45 | ngx_log_error(NGX_LOG_EMERG, log, 0, 46 | "getloadavg is unsupported under current os"); 47 | 48 | return NGX_ERROR; 49 | #endif 50 | } 51 | 52 | #if (NGX_HAVE_PROC_MEMINFO) 53 | 54 | static ngx_file_t ngx_meminfo_file; 55 | 56 | #define NGX_MEMINFO_FILE "/proc/meminfo" 57 | #define NGX_MEMINFO_MAX_NAME_LEN 16 58 | 59 | 60 | ngx_int_t 61 | ngx_http_sysguard_getmeminfo(ngx_http_sysguard_meminfo_t *meminfo, ngx_log_t *log) 62 | { 63 | u_char buf[2048]; 64 | u_char *p, *start, *last; 65 | size_t *sz = NULL; 66 | ssize_t n, len; 67 | ngx_fd_t fd; 68 | enum { 69 | sw_name = 0, 70 | sw_value_start, 71 | sw_value, 72 | sw_skipline, 73 | sw_newline, 74 | } state; 75 | 76 | ngx_memzero(meminfo, sizeof(ngx_http_sysguard_meminfo_t)); 77 | 78 | if (ngx_meminfo_file.fd == 0) { 79 | 80 | fd = ngx_open_file(NGX_MEMINFO_FILE, NGX_FILE_RDONLY, 81 | NGX_FILE_OPEN, 82 | NGX_FILE_DEFAULT_ACCESS); 83 | 84 | if (fd == NGX_INVALID_FILE) { 85 | ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, 86 | ngx_open_file_n " \"%s\" failed", 87 | NGX_MEMINFO_FILE); 88 | 89 | return NGX_ERROR; 90 | } 91 | 92 | ngx_meminfo_file.name.data = (u_char *) NGX_MEMINFO_FILE; 93 | ngx_meminfo_file.name.len = ngx_strlen(NGX_MEMINFO_FILE); 94 | 95 | ngx_meminfo_file.fd = fd; 96 | } 97 | 98 | ngx_meminfo_file.log = log; 99 | n = ngx_read_file(&ngx_meminfo_file, buf, sizeof(buf) - 1, 0); 100 | if (n == NGX_ERROR) { 101 | ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, 102 | ngx_read_file_n " \"%s\" failed", 103 | NGX_MEMINFO_FILE); 104 | 105 | return NGX_ERROR; 106 | } 107 | 108 | p = buf; 109 | start = buf; 110 | last = buf + n; 111 | state = sw_name; 112 | 113 | for (; p < last; p++) { 114 | 115 | if (*p == '\n') { 116 | state = sw_newline; 117 | } 118 | 119 | switch (state) { 120 | 121 | case sw_name: 122 | if (*p != ':') { 123 | continue; 124 | } 125 | 126 | len = p - start; 127 | sz = NULL; 128 | 129 | switch (len) { 130 | case 6: 131 | /* Cached */ 132 | if (meminfo->cachedram == 0 && 133 | ngx_strncmp(start, "Cached", len) == 0) 134 | { 135 | sz = &meminfo->cachedram; 136 | } 137 | break; 138 | case 7: 139 | /* Buffers MemFree */ 140 | if (meminfo->bufferram == 0 && 141 | ngx_strncmp(start, "Buffers", len) == 0) 142 | { 143 | sz = &meminfo->bufferram; 144 | } else if (meminfo->freeram == 0 && 145 | ngx_strncmp(start, "MemFree", len) == 0) 146 | { 147 | sz = &meminfo->freeram; 148 | } 149 | break; 150 | case 8: 151 | /* MemTotal SwapFree */ 152 | if (meminfo->totalram == 0 && 153 | ngx_strncmp(start, "MemTotal", len) == 0) 154 | { 155 | sz = &meminfo->totalram; 156 | } else if (meminfo->freeswap == 0 && 157 | ngx_strncmp(start, "SwapFree", len) == 0) 158 | { 159 | sz = &meminfo->freeswap; 160 | } 161 | break; 162 | case 9: 163 | /* SwapTotal */ 164 | if (meminfo->totalswap == 0 && 165 | ngx_strncmp(start, "SwapTotal", len) == 0) 166 | { 167 | sz = &meminfo->totalswap; 168 | } 169 | break; 170 | } 171 | 172 | if (sz == NULL) { 173 | state = sw_skipline; 174 | continue; 175 | } 176 | 177 | state = sw_value_start; 178 | 179 | continue; 180 | 181 | case sw_value_start: 182 | 183 | if (*p == ' ') { 184 | continue; 185 | } 186 | 187 | start = p; 188 | state = sw_value; 189 | 190 | continue; 191 | 192 | case sw_value: 193 | 194 | if (*p >= '0' && *p <= '9') { 195 | continue; 196 | } 197 | 198 | *(sz) = ngx_atosz(start, p - start) * 1024; 199 | 200 | state = sw_skipline; 201 | 202 | continue; 203 | 204 | case sw_skipline: 205 | 206 | continue; 207 | 208 | case sw_newline: 209 | 210 | state = sw_name; 211 | start = p + 1; 212 | 213 | continue; 214 | } 215 | } 216 | 217 | return NGX_OK; 218 | } 219 | 220 | #elif (NGX_HAVE_VM_STATS) 221 | 222 | static ngx_int_t 223 | ngx_http_sysguard_vm_stats(const char *name, size_t *res, ngx_log_t *log) 224 | { 225 | size_t val; 226 | size_t reslen = sizeof(size_t); 227 | *res = 0; 228 | 229 | if (sysctlbyname(name, &val, &reslen, NULL, 0) == -1) { 230 | ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, 231 | "sysctl \"%s\" failed", name); 232 | return NGX_ERROR; 233 | } 234 | 235 | *res = val; 236 | 237 | return NGX_OK; 238 | } 239 | 240 | ngx_int_t 241 | ngx_http_sysguard_getmeminfo(ngx_http_sysguard_meminfo_t *meminfo, ngx_log_t *log) 242 | { 243 | ngx_memzero(meminfo, sizeof(ngx_http_sysguard_meminfo_t)); 244 | 245 | if (ngx_http_sysguard_vm_stats("vfs.bufspace", 246 | &meminfo->bufferram, log) != NGX_OK) { 247 | return NGX_ERROR; 248 | } 249 | if (ngx_http_sysguard_vm_stats("vm.stats.vm.v_cache_count", 250 | &meminfo->cachedram, log) != NGX_OK) { 251 | return NGX_ERROR; 252 | } 253 | if (ngx_http_sysguard_vm_stats("vm.stats.vm.v_free_count", 254 | &meminfo->freeram, log) != NGX_OK) { 255 | return NGX_ERROR; 256 | } 257 | if (ngx_http_sysguard_vm_stats("hw.usermem", 258 | &meminfo->totalram, log) != NGX_OK) { 259 | return NGX_ERROR; 260 | } 261 | 262 | return NGX_OK; 263 | } 264 | #else 265 | 266 | ngx_int_t 267 | ngx_http_sysguard_getmeminfo(ngx_http_sysguard_meminfo_t *meminfo, ngx_log_t *log) 268 | { 269 | ngx_log_error(NGX_LOG_EMERG, log, 0, 270 | "getmeminfo is unsupported under current os"); 271 | 272 | return NGX_ERROR; 273 | } 274 | 275 | #endif 276 | 277 | 278 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 279 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_sysinfo.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #ifndef _NGX_SYSGUARD_SYSINFO_H_INCLUDED_ 9 | #define _NGX_SYSGUARD_SYSINFO_H_INCLUDED_ 10 | 11 | 12 | #if (NGX_HAVE_SYSINFO) 13 | #include 14 | #endif 15 | 16 | #if (NGX_HAVE_VM_STATS) 17 | #include 18 | #endif 19 | 20 | /* in bytes */ 21 | typedef struct { 22 | size_t totalram; 23 | size_t freeram; 24 | size_t bufferram; 25 | size_t cachedram; 26 | size_t totalswap; 27 | size_t freeswap; 28 | } ngx_http_sysguard_meminfo_t; 29 | 30 | 31 | typedef struct { 32 | time_t cached_load_exptime; 33 | time_t cached_mem_exptime; 34 | time_t cached_rt_exptime; 35 | 36 | ngx_int_t cached_load; 37 | ngx_int_t cached_swapstat; 38 | size_t cached_free; 39 | ngx_int_t cached_rt; 40 | 41 | ngx_http_sysguard_meminfo_t meminfo; 42 | } ngx_http_sysguard_sysinfo_t; 43 | 44 | 45 | ngx_int_t ngx_http_sysguard_getloadavg(ngx_int_t avg[], ngx_int_t nelem, ngx_log_t *log); 46 | ngx_int_t ngx_http_sysguard_getmeminfo(ngx_http_sysguard_meminfo_t *meminfo, ngx_log_t *log); 47 | 48 | 49 | #endif /* _NGX_SYSGUARD_SYSINFO_H_INCLUDED_ */ 50 | 51 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 52 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_variables.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #include "ngx_http_sysguard_module.h" 9 | #include "ngx_http_sysguard_variables.h" 10 | 11 | 12 | static ngx_http_variable_t ngx_http_sysguard_vars[] = { 13 | 14 | { ngx_string("sysguard_load"), NULL, 15 | ngx_http_sysguard_sysinfo_variable, 16 | offsetof(ngx_http_sysguard_sysinfo_t, cached_load), 17 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 18 | 19 | { ngx_string("sysguard_swapstat"), NULL, 20 | ngx_http_sysguard_sysinfo_variable, 21 | offsetof(ngx_http_sysguard_sysinfo_t, cached_swapstat), 22 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 23 | 24 | { ngx_string("sysguard_free"), NULL, 25 | ngx_http_sysguard_sysinfo_variable, 26 | offsetof(ngx_http_sysguard_sysinfo_t, cached_free), 27 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 28 | 29 | { ngx_string("sysguard_rt"), NULL, 30 | ngx_http_sysguard_sysinfo_variable, 31 | offsetof(ngx_http_sysguard_sysinfo_t, cached_rt), 32 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 33 | 34 | { ngx_string("sysguard_meminfo_totalram"), NULL, 35 | ngx_http_sysguard_sysinfo_variable, 36 | offsetof(ngx_http_sysguard_sysinfo_t, meminfo) 37 | + offsetof(ngx_http_sysguard_meminfo_t, totalram), 38 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 39 | 40 | { ngx_string("sysguard_meminfo_freeram"), NULL, 41 | ngx_http_sysguard_sysinfo_variable, 42 | offsetof(ngx_http_sysguard_sysinfo_t, meminfo) 43 | + offsetof(ngx_http_sysguard_meminfo_t, freeram), 44 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 45 | 46 | { ngx_string("sysguard_meminfo_bufferram"), NULL, 47 | ngx_http_sysguard_sysinfo_variable, 48 | offsetof(ngx_http_sysguard_sysinfo_t, meminfo) 49 | + offsetof(ngx_http_sysguard_meminfo_t, bufferram), 50 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 51 | 52 | { ngx_string("sysguard_meminfo_cachedram"), NULL, 53 | ngx_http_sysguard_sysinfo_variable, 54 | offsetof(ngx_http_sysguard_sysinfo_t, meminfo) 55 | + offsetof(ngx_http_sysguard_meminfo_t, cachedram), 56 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 57 | 58 | { ngx_string("sysguard_meminfo_totalswap"), NULL, 59 | ngx_http_sysguard_sysinfo_variable, 60 | offsetof(ngx_http_sysguard_sysinfo_t, meminfo) 61 | + offsetof(ngx_http_sysguard_meminfo_t, totalswap), 62 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 63 | 64 | { ngx_string("sysguard_meminfo_freeswap"), NULL, 65 | ngx_http_sysguard_sysinfo_variable, 66 | offsetof(ngx_http_sysguard_sysinfo_t, meminfo) 67 | + offsetof(ngx_http_sysguard_meminfo_t, freeswap), 68 | NGX_HTTP_VAR_NOCACHEABLE, 0 }, 69 | 70 | { ngx_null_string, NULL, NULL, 0, 0, 0 } 71 | }; 72 | 73 | 74 | ngx_int_t 75 | ngx_http_sysguard_sysinfo_variable(ngx_http_request_t *r, 76 | ngx_http_variable_value_t *v, uintptr_t data) 77 | { 78 | 79 | u_char *p; 80 | ngx_http_sysguard_conf_t *glcf; 81 | 82 | glcf = ngx_http_get_module_loc_conf(r, ngx_http_sysguard_module); 83 | 84 | p = ngx_pnalloc(r->pool, NGX_INT_T_LEN); 85 | if (p == NULL) { 86 | goto not_found; 87 | } 88 | 89 | v->len = ngx_sprintf(p, "%i", *((ngx_int_t *) ((char *) &glcf->sysinfo + data))) - p; 90 | v->valid = 1; 91 | v->no_cacheable = 0; 92 | v->not_found = 0; 93 | v->data = p; 94 | 95 | goto done; 96 | 97 | not_found: 98 | 99 | v->not_found = 1; 100 | 101 | done: 102 | 103 | return NGX_OK; 104 | } 105 | 106 | 107 | ngx_int_t 108 | ngx_http_sysguard_add_variables(ngx_conf_t *cf) 109 | { 110 | ngx_http_variable_t *var, *v; 111 | 112 | for (v = ngx_http_sysguard_vars; v->name.len; v++) { 113 | var = ngx_http_add_variable(cf, &v->name, v->flags); 114 | if (var == NULL) { 115 | return NGX_ERROR; 116 | } 117 | 118 | var->get_handler = v->get_handler; 119 | var->data = v->data; 120 | } 121 | 122 | return NGX_OK; 123 | } 124 | 125 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 126 | -------------------------------------------------------------------------------- /src/ngx_http_sysguard_variables.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) 2010-2015 Alibaba Group Holding Limited 4 | * Copyright (C) YoungJoo Kim (vozlt) 5 | */ 6 | 7 | 8 | #ifndef _NGX_SYSGUARD_VARIABLES_H_INCLUDED_ 9 | #define _NGX_SYSGUARD_VARIABLES_H_INCLUDED_ 10 | 11 | 12 | ngx_int_t ngx_http_sysguard_sysinfo_variable(ngx_http_request_t *r, 13 | ngx_http_variable_value_t *v, uintptr_t data); 14 | ngx_int_t ngx_http_sysguard_load_variable(ngx_http_request_t *r, 15 | ngx_http_variable_value_t *v, uintptr_t data); 16 | ngx_int_t ngx_http_sysguard_add_variables(ngx_conf_t *cf); 17 | 18 | 19 | #endif /* _NGX_SYSGUARD_VARIABLES_H_INCLUDED_ */ 20 | 21 | /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ 22 | --------------------------------------------------------------------------------