Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions .github/workflows/webserver.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ jobs:
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: /tmp/buildx-cache/
key: apache-ubuntu-20.04-${{ github.sha }}
key: apache-ubuntu-22.04-${{ github.sha }}
restore-keys: |
apache-ubuntu-20.04
apache-ubuntu-22.04
- name: setup docker image
run: |
cd instrumentation/otel-webserver-module
Expand All @@ -60,6 +60,12 @@ jobs:
cp -r /build-dependencies /otel-webserver-module/; \

./gradlew assembleWebServerModule -DtargetSystem=ubuntu'

- name: unit test
run: |
docker exec --workdir /otel-webserver-module apache_ubuntu_container \
./gradlew runTests -DtargetSystem=ubuntu

- name: update cache
run: |
rm -rf /tmp/buildx-cache/apache_ubuntu
Expand Down Expand Up @@ -107,8 +113,8 @@ jobs:
./gradlew assembleWebServerModule'
- name: unit test
run: |
docker exec apache_centos7_container bash -c \
'cd /otel-webserver-module; ./gradlew runUnitTest'
docker exec --workdir /otel-webserver-module apache_centos7_container \
./gradlew runTests
# - name: update cache
# run: |
# rm -rf /tmp/buildx-cache/apache_centos7
Expand Down Expand Up @@ -177,8 +183,8 @@ jobs:
./gradlew assembleWebServerModule'
- name: unit test
run: |
docker exec apache_almalinux8_container bash -c \
'cd /otel-webserver-module; ./gradlew runUnitTest'
docker exec --workdir /otel-webserver-module apache_almalinux8_container \
./gradlew runTests
# - name: update cache
# run: |
# rm -rf /tmp/buildx-cache/apache_almalinux8
Expand Down Expand Up @@ -206,7 +212,6 @@ jobs:
# ./gradlew :test:integration:integrationTests -i
# curl http://localhost:9411/api/v2/spans?serviceName=demoservice


Codeql-build:
permissions:
security-events: write # for github/codeql-action/analyze to upload SARIF results
Expand Down Expand Up @@ -235,4 +240,3 @@ jobs:
./gradlew assembleWebserverModule -DtargetSystem=ubuntu --info
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8

19 changes: 19 additions & 0 deletions instrumentation/otel-webserver-module/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,25 @@ task runApacheServer(type: Exec) {
commandLine './ApacheTesting.sh', "${target_system}"
}

task runNginxIssue474Test(type: Exec) {
group = 'verification'
description = 'Run the NGINX issue #474 User-Agent regression test'

dependsOn assembleNginxModule

workingDir 'test/nginx'
commandLine './issue_474_user_agent_regression_test.sh',
"${buildDir}/opentelemetry-webserver-sdk-${osArch}-${osName}.tgz",
'1.26.0'
}

task runTests {
group = 'verification'
description = 'Run all webserver module tests'

dependsOn runUnitTest, runNginxIssue474Test
}

// Code Coverage

task lcovCapture(type: Exec) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,14 @@ RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-${AUTO
&& cd .. && rm -rf automake-${AUTOMAKE_VERSION}.tar.gz

# install libtool
RUN wget --no-check-certificate https://ftpmirror.gnu.org/libtool/libtool-${LIBTOOL_VERSION}.tar.gz \
RUN wget --no-check-certificate https://ftp.gnu.org/gnu/libtool/libtool-${LIBTOOL_VERSION}.tar.gz \
&& tar xzf libtool-${LIBTOOL_VERSION}.tar.gz \
&& cd libtool-${LIBTOOL_VERSION} \
&& ./configure --prefix=/usr \
&& make -j 6 \
&& make install \
&& libtool --version \
&& cd .. && rm -rf libtool--${LIBTOOL_VERSION}.tar.gz
&& cd .. && rm -rf libtool-${LIBTOOL_VERSION}.tar.gz

#install log4cxx
RUN mkdir -p dependencies/apache-log4cxx/${LOG4CXX_VERSION} \
Expand Down Expand Up @@ -254,9 +254,9 @@ RUN cd /otel-webserver-module/build \


RUN cp /otel-webserver-module/conf/nginx/opentelemetry_module.conf /opt/ \
&& sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.26.2/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \
&& sed -i "8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/${NGINX_VERSION}/ngx_http_opentelemetry_module.so;" /etc/nginx/nginx.conf \
&& sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \
&& cd /

COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
ENTRYPOINT ["entrypoint.sh"]
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@ RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-${AUTO
&& cd .. && rm -rf automake-${AUTOMAKE_VERSION}.tar.gz

# install libtool
RUN wget --no-check-certificate https://ftpmirror.gnu.org/libtool/libtool-${LIBTOOL_VERSION}.tar.gz \
RUN wget --no-check-certificate https://ftp.gnu.org/gnu/libtool/libtool-${LIBTOOL_VERSION}.tar.gz \
&& tar xzf libtool-${LIBTOOL_VERSION}.tar.gz \
&& cd libtool-${LIBTOOL_VERSION} \
&& ./configure --prefix=/usr \
&& make -j 6 \
&& make install \
&& libtool --version \
&& cd .. && rm -rf libtool--${LIBTOOL_VERSION}.tar.gz
&& cd .. && rm -rf libtool-${LIBTOOL_VERSION}.tar.gz

#install log4cxx
RUN mkdir -p dependencies/apache-log4cxx/${LOG4CXX_VERSION} \
Expand Down Expand Up @@ -303,4 +303,4 @@ RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTO
&& rm -f httpd-2.2.31.tar.gz && rm -f httpd-2.4.23.tar.gz

COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
ENTRYPOINT ["entrypoint.sh"]
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ RUN echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
| tee /etc/apt/sources.list.d/nginx.list \
&& echo "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| tee /etc/apt/preferences.d/99nginx \
&& apt update -y && apt install nginx -y
&& apt update -y && apt install "nginx=${NGINX_VERSION}-1~focal" -y

# Build Webserver Module
COPY . /otel-webserver-module
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2056,10 +2056,14 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t*
temp_request_method[(r->method_name).len]='\0';
req_payload->request_method = temp_request_method;

char *temp_user_agent = ngx_pcalloc(r->pool, r->headers_in.user_agent->value.len +1);
strcpy(temp_user_agent,(const char*)(r->headers_in.user_agent->value.data));
temp_user_agent[r->headers_in.user_agent->value.len]='\0';
req_payload->user_agent = temp_user_agent;
ngx_table_elt_t *user_agent = r->headers_in.user_agent;
if (user_agent == NULL) {
req_payload->user_agent = "";
} else {
char *temp_user_agent = ngx_pcalloc(r->pool, user_agent->value.len + 1);
ngx_memcpy(temp_user_agent, user_agent->value.data, user_agent->value.len);
req_payload->user_agent = temp_user_agent;
}

ngx_uint_t remote_port = 0;
if (r->connection != NULL) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
#!/usr/bin/env bash

set -Eeuo pipefail

if [[ $# -ne 2 ]]; then
echo "Usage: $0 <webserver-module-archive> <nginx-version>" >&2
exit 2
fi

archive_path="$1"
nginx_version="$2"
nginx_binary="${NGINX_BINARY:-nginx}"
test_port="${NGINX_ISSUE_474_TEST_PORT:-18080}"

for command in curl ps tar "$nginx_binary"; do
if ! command -v "$command" >/dev/null 2>&1; then
echo "Required command not found: $command" >&2
exit 1
fi
done

if [[ ! -f "$archive_path" ]]; then
echo "Webserver module archive not found: $archive_path" >&2
exit 1
fi

runtime_version="$($nginx_binary -v 2>&1)"
if [[ "$runtime_version" != *"nginx/$nginx_version"* ]]; then
echo "Expected nginx/$nginx_version, but found: $runtime_version" >&2
exit 1
fi

test_root="$(mktemp -d /tmp/otel-nginx-issue-474.XXXXXX)"
nginx_prefix="$test_root/nginx"
nginx_config="$nginx_prefix/nginx.conf"
nginx_error_log="$nginx_prefix/error.log"
nginx_pid_file="$nginx_prefix/nginx.pid"
nginx_pid=""
current_test="startup"

cleanup() {
local exit_code=$?
trap - EXIT

if [[ -n "$nginx_pid" ]] && kill -0 "$nginx_pid" >/dev/null 2>&1; then
"$nginx_binary" -p "$nginx_prefix/" -c "$nginx_config" -s quit >/dev/null 2>&1 || true
for _ in {1..50}; do
if ! kill -0 "$nginx_pid" >/dev/null 2>&1; then
break
fi
sleep 0.1
done
if kill -0 "$nginx_pid" >/dev/null 2>&1; then
kill "$nginx_pid" >/dev/null 2>&1 || true
fi
fi

if [[ $exit_code -ne 0 ]]; then
echo "FAILED: $current_test" >&2
if [[ -f "$nginx_error_log" ]]; then
echo "NGINX error log:" >&2
cat "$nginx_error_log" >&2
fi
fi

case "$test_root" in
/tmp/otel-nginx-issue-474.*)
rm -rf -- "$test_root"
;;
esac

exit "$exit_code"
}
trap cleanup EXIT

mkdir -p "$nginx_prefix"
tar -xzf "$archive_path" -C "$test_root"

sdk_root="$test_root/opentelemetry-webserver-sdk"
module_path="$sdk_root/WebServerModule/Nginx/$nginx_version/ngx_http_opentelemetry_module.so"
sdk_library_path="$sdk_root/sdk_lib/lib"

if [[ ! -f "$module_path" ]]; then
echo "NGINX module not found in archive: $module_path" >&2
exit 1
fi

if [[ ! -x "$sdk_root/install.sh" ]]; then
echo "SDK installer not found in archive: $sdk_root/install.sh" >&2
exit 1
fi

"$sdk_root/install.sh" --ignore-permissions

export LD_LIBRARY_PATH="$sdk_library_path${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export OTEL_SDK_LOG_CONFIG_PATH="$sdk_root/conf/opentelemetry_sdk_log4cxx.xml"

cat >"$nginx_config" <<EOF
load_module $module_path;

user root;
worker_processes 1;
pid $nginx_pid_file;
error_log $nginx_error_log notice;

events {
worker_connections 64;
}

http {
access_log off;

NginxModuleEnabled ON;
NginxModuleOtelSpanExporter osstream;
NginxModuleOtelSpanProcessor simple;
NginxModuleOtelSampler always_on;
NginxModuleServiceName issue-474;
NginxModuleServiceNamespace regression-test;
NginxModuleServiceInstanceId ci;
NginxModuleResolveBackends OFF;
NginxModuleTraceAsError OFF;

server {
listen 127.0.0.1:$test_port;
server_name localhost;

location = /issue-474 {
return 200 "ok\n";
}
}
}
EOF

"$nginx_binary" -t -p "$nginx_prefix/" -c "$nginx_config"
"$nginx_binary" -p "$nginx_prefix/" -c "$nginx_config"

for _ in {1..50}; do
if [[ -s "$nginx_pid_file" ]]; then
nginx_pid="$(<"$nginx_pid_file")"
if curl --silent --fail --max-time 1 --http1.1 \
-H 'User-Agent: issue-474-readiness-check' \
"http://127.0.0.1:$test_port/issue-474" >/dev/null; then
break
fi
fi
sleep 0.1
done

if [[ -z "$nginx_pid" ]] || ! kill -0 "$nginx_pid" >/dev/null 2>&1; then
echo "NGINX did not start" >&2
exit 1
fi

worker_pid() {
ps -eo pid=,ppid= | awk -v parent="$nginx_pid" '$2 == parent { print $1; exit }'
}

assert_no_worker_crash() {
if grep -Eiq 'worker process .*exited on signal|segmentation fault|core dumped' "$nginx_error_log"; then
echo "NGINX worker crash detected" >&2
return 1
fi
}

run_test_case() {
local test_name="$1"
shift

current_test="$test_name"
echo "RUN: $test_name"

local worker_before
local worker_after
local http_status

worker_before="$(worker_pid)"
if [[ -z "$worker_before" ]]; then
echo "Unable to find the NGINX worker before $test_name" >&2
return 1
fi

if ! http_status="$(curl --silent --show-error --output /dev/null \
--write-out '%{http_code}' --max-time 5 --http1.1 \
"$@" "http://127.0.0.1:$test_port/issue-474")"; then
echo "Request failed for $test_name" >&2
return 1
fi

if [[ "$http_status" != "200" ]]; then
echo "Expected HTTP 200 for $test_name, received $http_status" >&2
return 1
fi

worker_after="$(worker_pid)"
if [[ "$worker_after" != "$worker_before" ]]; then
echo "NGINX worker changed during $test_name: $worker_before -> ${worker_after:-missing}" >&2
return 1
fi

assert_no_worker_crash
echo "PASS: $test_name"
}

test_non_empty_user_agent() {
run_test_case "non-empty User-Agent" -H 'User-Agent: otel-regression-test'
}

test_omitted_user_agent() {
run_test_case "omitted User-Agent" -H 'User-Agent:'
}

test_empty_user_agent() {
run_test_case "empty User-Agent" -H 'User-Agent;'
}

test_non_empty_user_agent
test_omitted_user_agent
test_empty_user_agent

current_test="complete"
echo "All NGINX issue #474 regression tests passed"
Loading