Skip to content

Commit 24dd995

Browse files
authored
Add appengine's nginx latency status module. (#810)
* Add appengine's nginx latency status module. * Update the commit used for appengine's nginx modules. * Update the appengine commit in WORKSPACE. * Update the appengine repo version to include a bug fix. Also improves the formatting of appengine's latency status modules's output json. * Add appengine nginx module test. Note that this involves adding a gitmodule. * Revert "Add appengine nginx module test." This reverts commit cd5abfa. * Copy test for appengine's nginx latency module. * Move the http_latency_status test to its own directory. * Add a README for the appengine nginx test directory. Co-authored-by: Isabel McCarten <imccarten@google.com>
1 parent a4d7455 commit 24dd995

File tree

7 files changed

+252
-7
lines changed

7 files changed

+252
-7
lines changed

WORKSPACE

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ nginx_repositories(
5757

5858
# Needs to come after nginx
5959
git_repository(
60-
name = "iap_jwt_verify_nginx",
61-
commit = "cbdfb7aa74897230c23a46162e3fbe0209cb659a", # Jan 8, 2018
60+
name = "appengine_nginx",
61+
commit = "6e2854c62b9c456e3ac42b78981fa374373a519f", # Aug 21, 2020
6262
remote = "https://github.com/GoogleCloudPlatform/appengine-sidecars-docker",
6363
)
6464

65-
load("@iap_jwt_verify_nginx//:iap_jwt_verify_nginx.bzl", "iap_jwt_verify_nginx_repositories")
65+
load("@appengine_nginx//:appengine_nginx.bzl", "appengine_nginx_repositories")
6666

67-
iap_jwt_verify_nginx_repositories(True)
67+
appengine_nginx_repositories(True)
6868

6969
git_repository(
7070
name = "com_github_grpc_grpc",

src/nginx/main/BUILD

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ cc_binary(
102102
deps = [
103103
"//src/nginx:ngx_esp",
104104
"//src/nginx:version_header",
105-
"@iap_jwt_verify_nginx//third_party/iap_jwt_verify_nginx/src:ngx_iap_jwt_verify",
105+
"@appengine_nginx//third_party/iap_jwt_verify_nginx/src:ngx_iap_jwt_verify",
106+
"@appengine_nginx//third_party/nginx_latency_status_module/src:ngx_latency_status_module",
106107
"@nginx//:http",
107108
"@nginx//:http_access",
108109
"@nginx//:http_addition",

src/nginx/main/ngx_modules.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ extern ngx_module_t ngx_http_stub_status_module;
198198
#if (NGX_IAP_JWT_VERIFY)
199199
extern ngx_module_t ngx_iap_jwt_verify_module;
200200
#endif
201+
#if (NGX_LATENCY_STATUS)
202+
extern ngx_module_t ngx_http_latency_stub_status_module;
203+
#endif
201204
#if (NGX_HTTP_ENDPOINTS_RUNTIME)
202205
extern ngx_module_t ngx_esp_module;
203206
#endif
@@ -498,6 +501,9 @@ ngx_module_t *ngx_modules[] = {
498501
#if (NGX_IAP_JWT_VERIFY)
499502
&ngx_iap_jwt_verify_module,
500503
#endif
504+
#if (NGX_LATENCY_STATUS)
505+
&ngx_http_latency_stub_status_module,
506+
#endif
501507
#if (NGX_HTTP_ENDPOINTS_RUNTIME)
502508
&ngx_esp_module,
503509
#endif
@@ -799,6 +805,9 @@ char *ngx_module_names[] = {
799805
#if (NGX_IAP_JWT_VERIFY)
800806
"ngx_iap_jwt_verify_module",
801807
#endif
808+
#if (NGX_LATENCY_STATUS)
809+
"ngx_http_latency_stub_status_module",
810+
#endif
802811
#if (NGX_HTTP_ENDPOINTS_RUNTIME)
803812
"ngx_esp_module",
804813
#endif

third_party/BUILD

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ perl_library(
4141
nginx_suite(
4242
nginx = "//src/nginx/main:nginx-esp",
4343
tags = ["exclusive"],
44-
tests = glob(
45-
["nginx-tests/*.t"],
44+
tests = glob([
45+
"nginx-tests/*.t",
46+
],
4647
exclude = [
4748
# ssl.t, ssl_certificates.t, ssl_stapling are excluded from the
4849
# test suite because boring ssl does not support renegotiation
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright (C) Extensible Service Proxy Authors
2+
# All rights reserved.
3+
#
4+
# Redistribution and use in source and binary forms, with or without
5+
# modification, are permitted provided that the following conditions
6+
# are met:
7+
# 1. Redistributions of source code must retain the above copyright
8+
# notice, this list of conditions and the following disclaimer.
9+
# 2. Redistributions in binary form must reproduce the above copyright
10+
# notice, this list of conditions and the following disclaimer in the
11+
# documentation and/or other materials provided with the distribution.
12+
#
13+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23+
# SUCH DAMAGE.
24+
#
25+
################################################################################
26+
#
27+
load("@io_bazel_rules_perl//perl:perl.bzl", "perl_library")
28+
load("//:nginx.bzl", "nginx_suite")
29+
30+
licenses(["notice"])
31+
32+
nginx_suite(
33+
nginx = "//src/nginx/main:nginx-esp",
34+
tests = ["http_latency_status.t"],
35+
deps = [
36+
"//third_party:nginx_test",
37+
],
38+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Appengine Nginx Module Test #
2+
3+
This directory contains a test of ESP's integration with
4+
[AppEngine's Nginx Latency Status Module](https://github.com/GoogleCloudPlatform/appengine-sidecars-docker/tree/master/third_party/nginx_latency_status_module),
5+
and is a copy of a test from the
6+
[GoogleCloudPlatform/appengine-sidecars-docker](https://github.com/GoogleCloudPlatform/appengine-sidecars-docker/tree/master/third_party/nginx_latency_status_module)
7+
repository.
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/perl
2+
3+
# Copyright (C) 2002-2016 Igor Sysoev
4+
# Copyright (C) 2011-2016 Nginx, Inc.
5+
# Copyright (C) 2020 Google Inc.
6+
# All rights reserved.
7+
#
8+
# Redistribution and use in source and binary forms, with or without
9+
# modification, are permitted provided that the following conditions
10+
# are met:
11+
# 1. Redistributions of source code must retain the above copyright
12+
# notice, this list of conditions and the following disclaimer.
13+
# 2. Redistributions in binary form must reproduce the above copyright
14+
# notice, this list of conditions and the following disclaimer in the
15+
# documentation and/or other materials provided with the distribution.
16+
#
17+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21+
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23+
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24+
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25+
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26+
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27+
# SUCH DAMAGE.
28+
29+
# tests for the nginx latency status module
30+
# run with TEST_NGINX_BINARY={path to nginx binary} prove http_latency_status.t
31+
32+
###############################################################################
33+
34+
use warnings;
35+
use strict;
36+
37+
use Test::More;
38+
39+
BEGIN { use FindBin; chdir($FindBin::Bin); }
40+
41+
use lib "../nginx-tests/lib";
42+
use Test::Nginx;
43+
use JSON::PP qw(decode_json);
44+
###############################################################################
45+
46+
select STDERR; $| = 1;
47+
select STDOUT; $| = 1;
48+
49+
my $t = Test::Nginx->new()->has(qw/http proxy rewrite/)->plan(17);
50+
51+
$t->write_file_expand('nginx.conf', <<'EOF');
52+
%%TEST_GLOBALS%%
53+
daemon off;
54+
events {
55+
}
56+
http {
57+
%%TEST_GLOBALS_HTTP%%
58+
store_latency 2 100 1;
59+
upstream u {
60+
server 127.0.0.1:8082;
61+
}
62+
server {
63+
listen 127.0.0.1:8080;
64+
server_name localhost;
65+
location /status {
66+
latency_stub_status;
67+
}
68+
location /success {
69+
return 200 "TEST\n";
70+
record_latency on;
71+
}
72+
location /pass {
73+
proxy_pass http://u/;
74+
record_latency on;
75+
}
76+
location /error {
77+
return 404;
78+
record_latency on;
79+
}
80+
location /pass-to-monitored {
81+
proxy_pass http://localhost:8081;
82+
}
83+
}
84+
server {
85+
listen 127.0.0.1:8082;
86+
server_name localhost;
87+
location / {
88+
return 200 "TEST\n";
89+
}
90+
}
91+
server {
92+
listen 127.0.0.1:8081;
93+
server_name localhost;
94+
record_latency on;
95+
location / {
96+
return 200 "TEST\n";
97+
}
98+
}
99+
}
100+
EOF
101+
102+
$t->run();
103+
104+
my $initial_status = "{\n \"accepted_connections\": 1,\n".
105+
" \"handled_connections\": 1,\n".
106+
" \"active_connections\": 1,\n".
107+
" \"requests\": 1,\n".
108+
" \"reading_connections\": 0,\n".
109+
" \"writing_connections\": 1,\n".
110+
" \"waiting_connections\": 0,\n".
111+
" \"request_latency\":{\n".
112+
" \"latency_sum\": 0,\n".
113+
" \"request_count\": 0,\n".
114+
" \"sum_squares\": 0,\n".
115+
" \"distribution\": [0, 0, 0]\n".
116+
" },\n".
117+
" \"upstream_latency\":{\n".
118+
" \"latency_sum\": 0,\n".
119+
" \"request_count\": 0,\n".
120+
" \"sum_squares\": 0,\n".
121+
" \"distribution\": [0, 0, 0]\n".
122+
" },\n".
123+
" \"websocket_latency\":{\n".
124+
" \"latency_sum\": 0,\n".
125+
" \"request_count\": 0,\n".
126+
" \"sum_squares\": 0,\n".
127+
" \"distribution\": [0, 0, 0]\n".
128+
" },\n".
129+
" \"latency_bucket_bounds\": [ 100, 200]\n".
130+
"}\n";
131+
132+
like(http_get('/status'), qr/\Q${initial_status}\E/, 'check initial stats twice');
133+
134+
http_get('/success');
135+
my $status = decode_json(http_get_body('/status'));
136+
137+
is($status->{'request_latency'}{'request_count'}, 1, 'request count after 1 monitored request');
138+
is(get_distribution_sum($status, 'request_latency'), 1, 'The sum of the distribution bucket counts after 1 monitored request');
139+
is($status->{'upstream_latency'}{'request_count'}, 0, 'upstream request count when there have been no proxied requests');
140+
is(get_distribution_sum($status, 'upstream_latency'), 0, 'sum of upstream distribution bucket counts when there haven been no proxied requests');
141+
is($status->{'websocket_latency'}{'request_count'}, 0, 'websocket request count when there have been no websocket requests');
142+
is(get_distribution_sum($status, 'websocket_latency'), 0, 'sum of websocket distribution bucket counts when there have been no websocket requests');
143+
144+
http_get('/error');
145+
$status = decode_json(http_get_body('/status'));
146+
147+
is($status->{'request_latency'}{'request_count'}, 2, 'erroring requests add to the request count');
148+
is(get_distribution_sum($status, 'request_latency'), 2, 'erroring requests add to distribution bucket counts');
149+
150+
http_get('/pass');
151+
$status = decode_json(http_get_body('/status'));
152+
153+
is($status->{'request_latency'}{'request_count'}, 3, 'proxied requests add to the request count');
154+
is(get_distribution_sum($status, 'request_latency'), 3, 'proxied requests add to the distribution bucket counts');
155+
is($status->{'upstream_latency'}{'request_count'}, 1, 'proxied requests add to the upstream request count');
156+
is(get_distribution_sum($status, 'upstream_latency'), 1, 'proxied requests add to the upstream distribution bucket counts');
157+
is($status->{'websocket_latency'}{'request_count'}, 0, 'a non-websocket proxied request does not add to the websocket request count');
158+
is(get_distribution_sum($status, 'websocket_latency'), 0, 'non-websocket proxied request does not add to websocket distribution bucket counts');
159+
160+
http_get('/pass-to-monitored');
161+
$status = decode_json(http_get_body('/status'));
162+
163+
is($status->{'request_latency'}{'request_count'}, 4, 'record_latency set at the server level adds to the request count');
164+
is(get_distribution_sum($status, 'request_latency'), 4, 'record_latency set at the server level adds to the distribution bucket counts');
165+
166+
sub get_distribution_sum {
167+
my ($status, $distribution_name) = @_;
168+
169+
my $latency_count = 0;
170+
my @distribution = $status->{$distribution_name}{'distribution'};
171+
for(my $i = 0; $i < @distribution; $i++) {
172+
$latency_count += $status->{$distribution_name}{'distribution'}[$i];
173+
}
174+
return $latency_count;
175+
}
176+
177+
sub http_get_body {
178+
my ($uri) = @_;
179+
180+
return undef if !defined $uri;
181+
182+
my $text = http_get($uri);
183+
184+
if ($text !~ /(.*?)\x0d\x0a?\x0d\x0a?(.*)/ms) {
185+
return undef;
186+
}
187+
188+
return $2;
189+
}

0 commit comments

Comments
 (0)