From c9136f2ec8d76751c35487ba4139e1986074a577 Mon Sep 17 00:00:00 2001 From: Eugene <54681898+jimf5@users.noreply.github.com> Date: Thu, 19 Dec 2024 17:53:38 -0800 Subject: [PATCH 1/8] Verify custom resource attributes support (#32). Co-authored-by: p-pautov <37922380+p-pautov@users.noreply.github.com> --- tests/test_otel.py | 32 +++++++++++++++++++++++++++++--- tests/trace_service.py | 14 +++++++++----- 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/tests/test_otel.py b/tests/test_otel.py index 10ce2fe..11caa85 100644 --- a/tests/test_otel.py +++ b/tests/test_otel.py @@ -28,7 +28,7 @@ http { } otel_trace on; - otel_service_name test_service; + {{ resource_attrs }} server { listen 127.0.0.1:18443 ssl; @@ -240,7 +240,7 @@ def test_context(client, trace_service, parent, path): @pytest.mark.parametrize( "nginx_config", - [({"interval": "200ms", "scheme": "http://"})], + [{"interval": "200ms", "scheme": "http://"}], indirect=True, ) @pytest.mark.parametrize("batch_count", [1, 3]) @@ -257,8 +257,34 @@ def test_batches(client, trace_service, batch_count): assert len(trace_service.batches) == batch_count for batch in trace_service.batches: - assert get_attr(batch[0].resource, "service.name") == "test_service" + assert ( + get_attr(batch[0].resource, "service.name") + == "unknown_service:nginx" + ) assert len(batch[0].scope_spans[0].spans) == batch_size time.sleep(0.3) # wait for +1 request to be flushed trace_service.batches.clear() + + +@pytest.mark.parametrize( + "nginx_config", + [ + { + "resource_attrs": """ + otel_service_name "test_service"; + otel_resource_attr my.name "my name"; + otel_resource_attr my.service "my service"; + """, + } + ], + indirect=True, +) +def test_custom_resource_attributes(client, trace_service): + assert client.get("http://127.0.0.1:18080/ok").status_code == 200 + + batch = trace_service.get_batch() + + assert get_attr(batch.resource, "service.name") == "test_service" + assert get_attr(batch.resource, "my.name") == "my name" + assert get_attr(batch.resource, "my.service") == "my service" diff --git a/tests/trace_service.py b/tests/trace_service.py index 9f094f9..3b191a1 100644 --- a/tests/trace_service.py +++ b/tests/trace_service.py @@ -14,16 +14,20 @@ class TraceService(trace_service_pb2_grpc.TraceServiceServicer): self.batches.append(request.resource_spans) return trace_service_pb2.ExportTracePartialSuccess() - def get_span(self): + def get_batch(self): for _ in range(10): if len(self.batches): break time.sleep(0.001) + assert len(self.batches) == 1 + assert len(self.batches[0]) == 1 + return self.batches.pop()[0] - assert len(self.batches) == 1, "No spans received" - span = self.batches[0][0].scope_spans[0].spans.pop() - self.batches.clear() - return span + def get_span(self): + batch = self.get_batch() + assert len(batch.scope_spans) == 1 + assert len(batch.scope_spans[0].spans) == 1 + return batch.scope_spans[0].spans.pop() @pytest.fixture(scope="module") From f633a8eef23cdc5f4c4e980605b981cf75595a14 Mon Sep 17 00:00:00 2001 From: Pavel Pautov Date: Thu, 21 Nov 2024 13:57:43 -0800 Subject: [PATCH 2/8] Fail early if "trusted_certificate" is a directory. Previously, the error was caused by enormous std::string allocation. --- src/http_module.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/http_module.cpp b/src/http_module.cpp index df5702e..bc08b23 100644 --- a/src/http_module.cpp +++ b/src/http_module.cpp @@ -711,7 +711,8 @@ char* addResourceAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) return NGX_CONF_OK; } -char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) { +char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) +{ auto path = ((ngx_str_t*)cf->args->elts)[1]; auto mcf = getMainConf(cf); @@ -727,11 +728,13 @@ char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) { return (char*)NGX_CONF_ERROR; } file.exceptions(std::ios::failbit | std::ios::badbit); - file.seekg(0, std::ios::end); - size_t size = file.tellg(); - mcf->trustedCert.resize(size); + file.peek(); // trigger early error for dirs + + size_t size = file.seekg(0, std::ios::end).tellg(); file.seekg(0); - file.read(&mcf->trustedCert[0], mcf->trustedCert.size()); + + mcf->trustedCert.resize(size); + file.read(&mcf->trustedCert[0], size); } catch (const std::exception& e) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to read \"%V\": %s", &path, e.what()); From 88a64bb2c3027be87057efedaa84d0c75d68610e Mon Sep 17 00:00:00 2001 From: Pavel Pautov Date: Thu, 21 Nov 2024 21:46:01 -0800 Subject: [PATCH 3/8] Consolidate transport related parameters into a struct. Also, replace leftover cast with getMainConf(). --- src/batch_exporter.hpp | 4 ++-- src/http_module.cpp | 11 +++++++---- src/trace_service_client.hpp | 16 +++++++++++----- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/batch_exporter.hpp b/src/batch_exporter.hpp index cb3e075..a2e65b1 100644 --- a/src/batch_exporter.hpp +++ b/src/batch_exporter.hpp @@ -111,10 +111,10 @@ public: int attrSize{0}; }; - BatchExporter(StrView target, bool ssl, const std::string& trustedCert, + BatchExporter(const Target& target, size_t batchSize, size_t batchCount, const std::map& resourceAttrs) : - batchSize(batchSize), client(std::string(target), ssl, trustedCert) + batchSize(batchSize), client(target) { free.reserve(batchCount); while (batchCount-- > 0) { diff --git a/src/http_module.cpp b/src/http_module.cpp index bc08b23..93898b1 100644 --- a/src/http_module.cpp +++ b/src/http_module.cpp @@ -576,10 +576,13 @@ ngx_int_t initWorkerProcess(ngx_cycle_t* cycle) } try { + Target target; + target.endpoint = std::string(toStrView(mcf->endpoint)); + target.ssl = mcf->ssl; + target.trustedCert = mcf->trustedCert; + gExporter.reset(new BatchExporter( - toStrView(mcf->endpoint), - mcf->ssl, - mcf->trustedCert, + target, mcf->batchSize, mcf->batchCount, mcf->resourceAttrs)); @@ -772,7 +775,7 @@ void* createMainConf(ngx_conf_t* cf) char* initMainConf(ngx_conf_t* cf, void* conf) { - auto mcf = (MainConf*)conf; + auto mcf = getMainConf(cf); ngx_conf_init_msec_value(mcf->interval, 5000); ngx_conf_init_size_value(mcf->batchSize, 512); diff --git a/src/trace_service_client.hpp b/src/trace_service_client.hpp index d248f00..485143c 100644 --- a/src/trace_service_client.hpp +++ b/src/trace_service_client.hpp @@ -8,6 +8,12 @@ namespace otel_proto_trace = opentelemetry::proto::collector::trace::v1; +struct Target { + std::string endpoint; + bool ssl; + std::string trustedCert; +}; + class TraceServiceClient { public: typedef otel_proto_trace::ExportTraceServiceRequest Request; @@ -17,18 +23,18 @@ public: typedef std::function ResponseCb; - TraceServiceClient(const std::string& target, bool ssl, - const std::string& trustedCert) + TraceServiceClient(const Target& target) { std::shared_ptr creds; - if (ssl) { + if (target.ssl) { grpc::SslCredentialsOptions options; - options.pem_root_certs = trustedCert; + options.pem_root_certs = target.trustedCert; + creds = grpc::SslCredentials(options); } else { creds = grpc::InsecureChannelCredentials(); } - auto channel = grpc::CreateChannel(target, creds); + auto channel = grpc::CreateChannel(target.endpoint, creds); channel->GetState(true); // trigger 'connecting' state stub = TraceService::NewStub(channel); From a45a594801fbd57657fd821bdd298a39d4575175 Mon Sep 17 00:00:00 2001 From: Pavel Pautov Date: Mon, 2 Dec 2024 21:07:38 -0800 Subject: [PATCH 4/8] Support sending custom headers to export endpoint (fix #62). The headers are configured by "header" directive in "otel_exporter" block, e.g. otel_exporter { endpoint localhost:4317; header X-API-Token "token value"; } --- src/http_module.cpp | 36 +++++++++++++++++++++++++++++++++++- src/trace_service_client.hpp | 23 ++++++++++++++++++++++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/http_module.cpp b/src/http_module.cpp index 93898b1..ef77ffb 100644 --- a/src/http_module.cpp +++ b/src/http_module.cpp @@ -30,6 +30,7 @@ struct MainConf : MainConfBase { std::map resourceAttrs; bool ssl; std::string trustedCert; + Target::HeaderVec headers; }; struct SpanAttr { @@ -49,6 +50,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf); char* addResourceAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf); char* addSpanAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf); char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf); +char* addExporterHeader(ngx_conf_t* cf, ngx_command_t* cmd, void* conf); namespace Propagation { @@ -120,6 +122,10 @@ ngx_command_t gExporterCommands[] = { NGX_CONF_TAKE1, setTrustedCertificate }, + { ngx_string("header"), + NGX_CONF_TAKE2, + addExporterHeader }, + { ngx_string("interval"), NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -580,6 +586,7 @@ ngx_int_t initWorkerProcess(ngx_cycle_t* cycle) target.endpoint = std::string(toStrView(mcf->endpoint)); target.ssl = mcf->ssl; target.trustedCert = mcf->trustedCert; + target.headers = mcf->headers; gExporter.reset(new BatchExporter( target, @@ -651,7 +658,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) continue; } - if (cf->args->nelts != 2) { + if (cf->args->nelts != static_cast(ffs(cmd->type))) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number of arguments in \"%V\" " "directive of \"otel_exporter\"", name); @@ -747,6 +754,33 @@ char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) return NGX_CONF_OK; } +char* addExporterHeader(ngx_conf_t* cf, ngx_command_t* cmd, void* conf) +{ + auto args = (ngx_str_t*)cf->args->elts; + + // don't force on users lower case name requirement of gRPC + ngx_strlow(args[1].data, args[1].data, args[1].len); + + try { + // validate header here to avoid runtime assert failure in gRPC + auto name = toStrView(args[1]); + if (!Target::validateHeaderName(name)) { + return (char*)"has invalid header name"; + } + auto value = toStrView(args[2]); + if (!Target::validateHeaderValue(value)) { + return (char*)"has invalid header value"; + } + + getMainConf(cf)->headers.emplace_back(name, value); + } catch (const std::exception& e) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "OTel: %s", e.what()); + return (char*)NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + void* createMainConf(ngx_conf_t* cf) { auto cln = ngx_pool_cleanup_add(cf->pool, sizeof(MainConf)); diff --git a/src/trace_service_client.hpp b/src/trace_service_client.hpp index 485143c..4ed92e7 100644 --- a/src/trace_service_client.hpp +++ b/src/trace_service_client.hpp @@ -9,9 +9,24 @@ namespace otel_proto_trace = opentelemetry::proto::collector::trace::v1; struct Target { + typedef std::vector> HeaderVec; + std::string endpoint; bool ssl; std::string trustedCert; + HeaderVec headers; + + static bool validateHeaderName(StrView name) + { + return grpc_header_key_is_legal( + grpc_slice_from_static_buffer(name.data(), name.size())); + } + + static bool validateHeaderValue(StrView value) + { + return grpc_header_nonbin_value_is_legal( + grpc_slice_from_static_buffer(value.data(), value.size())); + } }; class TraceServiceClient { @@ -23,7 +38,7 @@ public: typedef std::function ResponseCb; - TraceServiceClient(const Target& target) + TraceServiceClient(const Target& target) : headers(target.headers) { std::shared_ptr creds; if (target.ssl) { @@ -44,6 +59,10 @@ public: { std::unique_ptr call{new ActiveCall{}}; + for (auto& header : headers) { + call->context.AddMetadata(header.first, header.second); + } + call->request = std::move(req); call->cb = std::move(cb); @@ -113,6 +132,8 @@ private: ResponseCb cb; }; + Target::HeaderVec headers; + std::unique_ptr stub; grpc::CompletionQueue queue; From 9dc4dc2803cc2e7e37f5c73fee7f8d342101aa41 Mon Sep 17 00:00:00 2001 From: Pavel Pautov Date: Thu, 19 Dec 2024 21:28:17 -0800 Subject: [PATCH 5/8] Verify custom exporter headers support (#62). --- tests/test_otel.py | 25 +++++++++++++++++++++++++ tests/trace_service.py | 11 ++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/tests/test_otel.py b/tests/test_otel.py index 11caa85..513c1f1 100644 --- a/tests/test_otel.py +++ b/tests/test_otel.py @@ -25,6 +25,8 @@ http { interval {{ interval or "1ms" }}; batch_size 3; batch_count 3; + + {{ exporter_opts }} } otel_trace on; @@ -288,3 +290,26 @@ def test_custom_resource_attributes(client, trace_service): assert get_attr(batch.resource, "service.name") == "test_service" assert get_attr(batch.resource, "my.name") == "my name" assert get_attr(batch.resource, "my.service") == "my service" + + +@pytest.mark.parametrize( + "nginx_config", + [ + { + "exporter_opts": """ + header X-API-TOKEN api.value; + header Authorization "Basic value"; + """, + } + ], + indirect=True, +) +@pytest.mark.parametrize("trace_service", ["skip_otelcol"], indirect=True) +def test_exporter_headers(client, trace_service): + assert client.get("http://127.0.0.1:18080/ok").status_code == 200 + + assert trace_service.get_span().name == "/ok" + + headers = dict(trace_service.last_metadata) + assert headers["x-api-token"] == "api.value" + assert headers["authorization"] == "Basic value" diff --git a/tests/trace_service.py b/tests/trace_service.py index 3b191a1..f47b104 100644 --- a/tests/trace_service.py +++ b/tests/trace_service.py @@ -12,6 +12,7 @@ class TraceService(trace_service_pb2_grpc.TraceServiceServicer): def Export(self, request, context): self.batches.append(request.resource_spans) + self.last_metadata = context.invocation_metadata() return trace_service_pb2.ExportTracePartialSuccess() def get_batch(self): @@ -31,13 +32,17 @@ class TraceService(trace_service_pb2_grpc.TraceServiceServicer): @pytest.fixture(scope="module") -def trace_service(pytestconfig, logger): +def trace_service(request, pytestconfig, logger): server = grpc.server(concurrent.futures.ThreadPoolExecutor()) trace_service = TraceService() trace_service_pb2_grpc.add_TraceServiceServicer_to_server( trace_service, server ) - listen_addr = f"127.0.0.1:{24317 if pytestconfig.option.otelcol else 14317}" + trace_service.use_otelcol = ( + pytestconfig.option.otelcol + and getattr(request, "param", "") != "skip_otelcol" + ) + listen_addr = f"127.0.0.1:{24317 if trace_service.use_otelcol else 14317}" server.add_insecure_port(listen_addr) logger.info(f"Starting trace service at {listen_addr}...") server.start() @@ -48,7 +53,7 @@ def trace_service(pytestconfig, logger): @pytest.fixture(scope="module") def otelcol(pytestconfig, testdir, logger, trace_service): - if pytestconfig.option.otelcol is None: + if not trace_service.use_otelcol: yield return From f578402f196499edd2a65c31020570fc37e1bdbf Mon Sep 17 00:00:00 2001 From: Eugene Grebenschikov Date: Fri, 20 Dec 2024 17:24:27 -0800 Subject: [PATCH 6/8] Verify export via TLS (#12). Co-authored-by: Pavel Pautov --- tests/conftest.py | 19 ++++++++++--------- tests/test_otel.py | 20 ++++++++++++++++++-- tests/trace_service.py | 20 ++++++++++++++++---- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 7978759..25933e4 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,7 +19,7 @@ def pytest_addoption(parser): parser.addoption("--globals", default="") -def self_signed_cert(test_dir, name): +def self_signed_cert(name): k = crypto.PKey() k.generate_key(crypto.TYPE_RSA, 2048) cert = crypto.X509() @@ -29,11 +29,9 @@ def self_signed_cert(test_dir, name): cert.gmtime_adj_notAfter(365 * 86400) # 365 days cert.set_pubkey(k) cert.sign(k, "sha512") - (test_dir / f"{name}.key").write_text( - crypto.dump_privatekey(crypto.FILETYPE_PEM, k).decode("utf-8") - ) - (test_dir / f"{name}.crt").write_text( - crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8") + return ( + crypto.dump_privatekey(crypto.FILETYPE_PEM, k), + crypto.dump_certificate(crypto.FILETYPE_PEM, cert), ) @@ -66,7 +64,7 @@ def nginx_config(request, pytestconfig, testdir, logger): @pytest.fixture(scope="module") -def nginx(testdir, pytestconfig, nginx_config, certs, logger, otelcol): +def nginx(testdir, pytestconfig, nginx_config, cert, logger, otelcol): (testdir / "nginx.conf").write_text(nginx_config) logger.info("Starting nginx...") proc = subprocess.Popen( @@ -96,5 +94,8 @@ def nginx(testdir, pytestconfig, nginx_config, certs, logger, otelcol): @pytest.fixture(scope="module") -def certs(testdir): - self_signed_cert(testdir, "localhost") +def cert(testdir): + key, cert = self_signed_cert("localhost") + (testdir / "localhost.key").write_text(key.decode("utf-8")) + (testdir / "localhost.crt").write_text(cert.decode("utf-8")) + yield (key, cert) diff --git a/tests/test_otel.py b/tests/test_otel.py index 513c1f1..fef771a 100644 --- a/tests/test_otel.py +++ b/tests/test_otel.py @@ -21,7 +21,7 @@ http { ssl_certificate_key localhost.key; otel_exporter { - endpoint {{ scheme }}127.0.0.1:14317; + endpoint {{ endpoint or "127.0.0.1:14317" }}; interval {{ interval or "1ms" }}; batch_size 3; batch_count 3; @@ -242,7 +242,7 @@ def test_context(client, trace_service, parent, path): @pytest.mark.parametrize( "nginx_config", - [{"interval": "200ms", "scheme": "http://"}], + [{"interval": "200ms", "endpoint": "http://127.0.0.1:14317"}], indirect=True, ) @pytest.mark.parametrize("batch_count", [1, 3]) @@ -313,3 +313,19 @@ def test_exporter_headers(client, trace_service): headers = dict(trace_service.last_metadata) assert headers["x-api-token"] == "api.value" assert headers["authorization"] == "Basic value" + + +@pytest.mark.parametrize( + "nginx_config", + [ + { + "endpoint": "https://localhost:14318", + "exporter_opts": "trusted_certificate localhost.crt;", + } + ], + indirect=True, +) +def test_tls_export(client, trace_service): + assert client.get("http://127.0.0.1:18080/ok").status_code == 200 + + assert trace_service.get_span().name == "/ok" diff --git a/tests/trace_service.py b/tests/trace_service.py index f47b104..5ef2bc6 100644 --- a/tests/trace_service.py +++ b/tests/trace_service.py @@ -32,7 +32,7 @@ class TraceService(trace_service_pb2_grpc.TraceServiceServicer): @pytest.fixture(scope="module") -def trace_service(request, pytestconfig, logger): +def trace_service(request, pytestconfig, logger, cert): server = grpc.server(concurrent.futures.ThreadPoolExecutor()) trace_service = TraceService() trace_service_pb2_grpc.add_TraceServiceServicer_to_server( @@ -44,6 +44,10 @@ def trace_service(request, pytestconfig, logger): ) listen_addr = f"127.0.0.1:{24317 if trace_service.use_otelcol else 14317}" server.add_insecure_port(listen_addr) + if not trace_service.use_otelcol: + creds = grpc.ssl_server_credentials([cert]) + server.add_secure_port("127.0.0.1:14318", creds) + listen_addr += " and 127.0.0.1:14318" logger.info(f"Starting trace service at {listen_addr}...") server.start() yield trace_service @@ -52,18 +56,26 @@ def trace_service(request, pytestconfig, logger): @pytest.fixture(scope="module") -def otelcol(pytestconfig, testdir, logger, trace_service): +def otelcol(pytestconfig, testdir, logger, trace_service, cert): if not trace_service.use_otelcol: yield return (testdir / "otel-config.yaml").write_text( - """receivers: + f"""receivers: otlp: protocols: grpc: endpoint: 127.0.0.1:14317 + otlp/tls: + protocols: + grpc: + endpoint: 127.0.0.1:14318 + tls: + cert_file: {testdir}/localhost.crt + key_file: {testdir}/localhost.key + exporters: otlp: endpoint: 127.0.0.1:24317 @@ -73,7 +85,7 @@ exporters: service: pipelines: traces: - receivers: [otlp] + receivers: [otlp, otlp/tls] exporters: [otlp] telemetry: metrics: From 72d8eed53af4c2cd6f3e30a2efe0e38d66f5e176 Mon Sep 17 00:00:00 2001 From: Pavel Pautov Date: Tue, 21 Jan 2025 23:02:39 -0800 Subject: [PATCH 7/8] Fix build against Nginx 1.22 (fix #85). --- src/http_module.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/http_module.cpp b/src/http_module.cpp index ef77ffb..78a5e89 100644 --- a/src/http_module.cpp +++ b/src/http_module.cpp @@ -296,10 +296,10 @@ ngx_int_t setHeader(ngx_http_request_t* r, StrView name, StrView value) return NGX_ERROR; } + *header = {}; header->hash = hash; header->key = toNgxStr(name); header->lowcase_key = header->key.data; - header->next = NULL; } header->value = toNgxStr(value); From 22d6380458c115b75ec7ed7d759bb47231f3d1f6 Mon Sep 17 00:00:00 2001 From: Pavel Pautov Date: Thu, 27 Mar 2025 19:35:53 -0700 Subject: [PATCH 8/8] Add CI workflow for Alpine Linux. The workflow uses Nginx build system with OS provided gRPC. --- .github/workflows/alpine.yml | 45 ++++++++++++++++++++++++++++++++++++ .github/workflows/ubuntu.yml | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/alpine.yml diff --git a/.github/workflows/alpine.yml b/.github/workflows/alpine.yml new file mode 100644 index 0000000..8dc0cef --- /dev/null +++ b/.github/workflows/alpine.yml @@ -0,0 +1,45 @@ +name: Alpine build + +on: + push: + branches: + - main + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + container: alpine + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Install dependencies + run: | + apk add build-base openssl-dev zlib-dev pcre2-dev \ + cmake git grpc-dev protobuf-dev \ + python3 + - name: Checkout nginx + uses: actions/checkout@v4 + with: + repository: nginx/nginx + path: nginx + - name: Build nginx + working-directory: nginx + run: | + auto/configure --with-compat --with-http_ssl_module \ + --with-http_v2_module --with-http_v3_module + make -j $(nproc) + - name: Build module + working-directory: nginx + run: | + NGX_OTEL_CMAKE_OPTS="-D NGX_OTEL_GRPC=package" \ + auto/configure --with-compat --add-dynamic-module=.. + make -j $(nproc) modules + - name: Install test dependencies + run: | + python -m venv tests-venv + tests-venv/bin/pip install -r tests/requirements.txt + - name: Run tests + run: | + tests-venv/bin/pytest tests --maxfail=10 --nginx=nginx/objs/nginx \ + --module=nginx/objs/ngx_otel_module.so diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 0f328d2..07be30e 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -7,7 +7,7 @@ on: pull_request: jobs: - build-module: + test: runs-on: ubuntu-22.04 steps: - name: Checkout repository