Skip to content

Commit 1ba4a85

Browse files
authored
Merge pull request #228 from chobits/for_pull_request
Feature: get the time to receive the first byte of data from proxy server
2 parents 5671010 + 076a748 commit 1ba4a85

3 files changed

+118
-1
lines changed

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Table of Contents
3838
* [$proxy_connect_send_timeout](#proxy_connect_send_timeout-1)
3939
* [$proxy_connect_resolve_time](#proxy_connect_resolve_time)
4040
* [$proxy_connect_connect_time](#proxy_connect_connect_time)
41+
* [$proxy_connect_first_byte_time](#proxy_connect_first_byte_time)
4142
* [$proxy_connect_response](#proxy_connect_response-1)
4243
* [Compatibility](#compatibility)
4344
* [Nginx Compatibility](#nginx-compatibility)
@@ -480,6 +481,15 @@ Keeps time spent on establishing a connection with the upstream server; the time
480481
* Value of "-" means name resolving or connecting failed.
481482

482483

484+
$proxy_connect_first_byte_time
485+
---------------------------
486+
487+
Keeps time to receive the first byte of data from the upstream server; the time is kept in seconds with millisecond resolution.
488+
489+
* Value of "" means this module does not work on this request.
490+
* Value of "-" means name resolving, connecting or receving failed.
491+
492+
483493
$proxy_connect_response
484494
---------------------------
485495

ngx_http_proxy_connect_module.c

+72
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ typedef struct {
4545
typedef struct {
4646
ngx_msec_t resolve_time;
4747
ngx_msec_t connect_time;
48+
ngx_msec_t first_byte_time;
4849

4950
/* TODO:
5051
off_t bytes_received;
@@ -133,6 +134,8 @@ static ngx_int_t ngx_http_proxy_connect_resolve_time_variable(ngx_http_request_t
133134
ngx_http_variable_value_t *v, uintptr_t data);
134135
static ngx_int_t ngx_http_proxy_connect_connect_time_variable(ngx_http_request_t *r,
135136
ngx_http_variable_value_t *v, uintptr_t data);
137+
static ngx_int_t ngx_http_proxy_connect_first_byte_time_variable(ngx_http_request_t *r,
138+
ngx_http_variable_value_t *v, uintptr_t data);
136139
static ngx_int_t ngx_http_proxy_connect_variable_get_response(ngx_http_request_t *r,
137140
ngx_http_variable_value_t *v, uintptr_t data);
138141
static void ngx_http_proxy_connect_variable_set_response(ngx_http_request_t *r,
@@ -277,6 +280,10 @@ static ngx_http_variable_t ngx_http_proxy_connect_vars[] = {
277280
ngx_http_proxy_connect_connect_time_variable, 0,
278281
NGX_HTTP_VAR_NOCACHEABLE, 0 },
279282

283+
{ ngx_string("proxy_connect_first_byte_time"), NULL,
284+
ngx_http_proxy_connect_first_byte_time_variable, 0,
285+
NGX_HTTP_VAR_NOCACHEABLE, 0 },
286+
280287
{ ngx_string("proxy_connect_response"),
281288
ngx_http_proxy_connect_variable_set_response,
282289
ngx_http_proxy_connect_variable_get_response,
@@ -722,6 +729,13 @@ ngx_http_proxy_connect_tunnel(ngx_http_request_t *r,
722729
do_write = 1;
723730
b->last += n;
724731

732+
if (from_upstream) {
733+
if (u->state.first_byte_time == (ngx_msec_t) -1) {
734+
u->state.first_byte_time = ngx_current_msec
735+
- u->start_time;
736+
}
737+
}
738+
725739
continue;
726740
}
727741

@@ -1042,6 +1056,7 @@ ngx_http_proxy_connect_process_connect(ngx_http_request_t *r,
10421056

10431057
u->start_time = ngx_current_msec;
10441058
u->state.connect_time = (ngx_msec_t) -1;
1059+
u->state.first_byte_time = (ngx_msec_t) -1;
10451060

10461061
rc = ngx_event_connect_peer(&u->peer);
10471062

@@ -2194,6 +2209,63 @@ ngx_http_proxy_connect_connect_time_variable(ngx_http_request_t *r,
21942209
}
21952210

21962211

2212+
static ngx_int_t
2213+
ngx_http_proxy_connect_first_byte_time_variable(ngx_http_request_t *r,
2214+
ngx_http_variable_value_t *v, uintptr_t data)
2215+
{
2216+
u_char *p;
2217+
size_t len;
2218+
ngx_msec_int_t ms;
2219+
ngx_http_proxy_connect_ctx_t *ctx;
2220+
ngx_http_proxy_connect_upstream_t *u;
2221+
2222+
if (r->method != NGX_HTTP_CONNECT) {
2223+
return NGX_OK;
2224+
}
2225+
2226+
v->valid = 1;
2227+
v->no_cacheable = 0;
2228+
v->not_found = 0;
2229+
2230+
ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_connect_module);
2231+
2232+
if (ctx == NULL) {
2233+
v->not_found = 1;
2234+
return NGX_OK;
2235+
}
2236+
2237+
u = ctx->u;
2238+
2239+
if (u == NULL || !u->connected) {
2240+
v->not_found = 1;
2241+
return NGX_OK;
2242+
}
2243+
2244+
len = NGX_TIME_T_LEN + 4;
2245+
2246+
p = ngx_pnalloc(r->pool, len);
2247+
if (p == NULL) {
2248+
return NGX_ERROR;
2249+
}
2250+
2251+
v->data = p;
2252+
2253+
ms = u->state.first_byte_time;
2254+
2255+
if (ms != -1) {
2256+
ms = ngx_max(ms, 0);
2257+
p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000);
2258+
2259+
} else {
2260+
*p++ = '-';
2261+
}
2262+
2263+
v->len = p - v->data;
2264+
2265+
return NGX_OK;
2266+
}
2267+
2268+
21972269
static ngx_int_t
21982270
ngx_http_proxy_connect_variable_get_response(ngx_http_request_t *r,
21992271
ngx_http_variable_value_t *v, uintptr_t data)

t/http_proxy_connect_resolve_variables.t

+36-1
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,13 @@ events {
7878
http {
7979
%%TEST_GLOBALS_HTTP%%
8080
81+
# lua_load_resty_core off;
82+
8183
log_format connect '$remote_addr - $remote_user [$time_local] "$request" '
8284
'$status $body_bytes_sent var:$connect_host-$connect_port-$connect_addr '
83-
'resolve:$proxy_connect_resolve_time,connect:$proxy_connect_connect_time,';
85+
'resolve:$proxy_connect_resolve_time,'
86+
'connect:$proxy_connect_connect_time,'
87+
'fbt:$proxy_connect_first_byte_time,';
8488
8589
access_log %%TESTDIR%%/connect.log connect;
8690
error_log %%TESTDIR%%/connect_error.log error;
@@ -139,6 +143,27 @@ http {
139143
access_log off;
140144
return 200 "8081 server";
141145
}
146+
147+
# for $proxy_connect_first_byte_time testing
148+
server {
149+
access_log off;
150+
listen 8082;
151+
rewrite_by_lua '
152+
ngx.sleep(1)
153+
ngx.say("8082 server fbt")
154+
';
155+
156+
}
157+
server {
158+
access_log off;
159+
listen 8083;
160+
rewrite_by_lua '
161+
ngx.sleep(0.5)
162+
ngx.say("8083 server fbt")
163+
';
164+
165+
}
166+
142167
}
143168
144169
EOF
@@ -197,6 +222,16 @@ like($log, qr/"CONNECT non-existent-domain.com:8081 HTTP\/1.1" 502 .+ resolve:-,
197222
$errlog = http_get('/connect_error.log');
198223
like($errlog, qr/proxy_connect: non-existent-domain.com could not be resolved .+Host not found/, 'test error.log for 502 respsone');
199224

225+
# test first byte time
226+
# fbt:~1s
227+
http_connect_request('127.0.0.1', '8082', '/');
228+
$log = http_get('/connect.log');
229+
like($log, qr/"CONNECT 127.0.0.1:8082 HTTP\/1.1" 200 .+ resolve:0\....,connect:0\....,fbt:1\....,/, 'test first byte time: 1s');
230+
# fbt:~0.5s
231+
http_connect_request('127.0.0.1', '8083', '/');
232+
$log = http_get('/connect.log');
233+
like($log, qr/"CONNECT 127.0.0.1:8083 HTTP\/1.1" 200 .+ resolve:0\....,connect:0\....,fbt:0\.5..,/, 'test first byte time: 0.5s');
234+
200235
$t->stop();
201236

202237

0 commit comments

Comments
 (0)