diff --git a/.github/workflows/webserver.yml b/.github/workflows/webserver.yml index 4b8977255..5cf6746f1 100644 --- a/.github/workflows/webserver.yml +++ b/.github/workflows/webserver.yml @@ -49,11 +49,9 @@ jobs: 'cd /otel-webserver-module; rm -rf build; \ cp -r /dependencies /otel-webserver-module/; \ cp -r /build-dependencies /otel-webserver-module/; \ + ./gradlew assembleWebServerModule -DtargetSystem=ubuntu' - - name: unit test - run: | - docker exec apache_ubuntu_container bash -c \ - 'cd /otel-webserver-module; ./gradlew runUnitTest -DtargetSystem=ubuntu' + - name: update cache run: | rm -rf /tmp/buildx-cache/apache_ubuntu diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index 028cc18fc..c227a5384 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -39,6 +39,15 @@ class RequestPayload std::unordered_map http_headers; /* HTTP Request headers: Cookie, Referer, SM_USER*/ + std::string server_name; + std::string scheme; + std::string host; + std::string target; + std::string flavor; + std::string client_ip; + long port; + long status_code; + public: void set_http_headers(const std::string& key, const std::string& value) { @@ -49,6 +58,15 @@ class RequestPayload void set_http_get_parameter(const char* httpGetParameter) {http_get_parameter = httpGetParameter; } void set_http_post_parameter(const char* httpPostParameter) {http_post_parameter = httpPostParameter; } void set_http_request_method(const char* httpRequestMethod) {http_request_method = httpRequestMethod; } + void set_server_name(const char* serverName) {server_name = serverName; } + void set_scheme(const char* aScheme) {scheme = aScheme; } + void set_host(const char* aHost) {host = aHost; } + void set_target(const char* aTarget) {target = aTarget; } + void set_flavor(const char* aflavor) {flavor = aflavor; } + void set_client_ip(const char* clientIp) {client_ip = clientIp; } + void set_port(long aPort) {port = aPort; } + void set_status_code(long statusCode) {status_code = statusCode; } + std::string get_uri() { return uri; } std::string get_request_protocol() { return request_protocol; } @@ -56,6 +74,14 @@ class RequestPayload std::string get_http_post_parameter() { return http_post_parameter; } std::string get_http_request_method() { return http_request_method; } std::unordered_map get_http_headers() { return http_headers; } + std::string get_server_name() { return server_name; } + std::string get_scheme() {return scheme; } + std::string get_host() {return host; } + std::string get_target() {return target; } + std::string get_flavor() {return flavor; } + std::string get_client_ip() {return client_ip; } + long get_port() {return port; } + long get_status_code() {return status_code; } }; struct InteractionPayload diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h index b7c436379..2d4e3006b 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h @@ -25,9 +25,26 @@ const std::string kServiceInstanceId = "service.instance.id"; const std::string kOtelLibraryName = "telemetry.sdk.language"; const std::string kOtelLibraryVersion = "telemetry.sdk.version"; const std::string kHttpErrorCode = "HTTP ERROR CODE:"; +const std::string kAttrHTTPServerName = "http.server_name"; +const std::string kAttrHTTPMethod = "http.method"; +const std::string kAttrHTTPScheme = "http.scheme"; +const std::string kAttrNetHostName = "net.host.name"; +const std::string kAttrHTTPTarget = "http.target"; +const std::string kAttrHTTPUrl = "http.url"; +const std::string kAttrHTTPFlavor = "http.flavor"; +const std::string kAttrHTTPClientIP = "http.client_ip"; +const std::string kAttrHTTPStatusCode = "http.status_code"; +const std::string kAttrNETHostPort = "net.host.port"; +const std::string kAttrRequestProtocol = "request_protocol"; +const std::string kHTTPFlavor1_0 = "1.0"; +const std::string kHTTPFlavor1_1 = "1.1"; + + constexpr int HTTP_ERROR_1XX = 100; constexpr int HTTP_ERROR_4XX = 400; constexpr int HTTP_ERROR_5XX = 500; +constexpr int HTTP_PROTO_1000 = 1000; +constexpr int HTTP_PROTO_1001 = 1001; } // sdkwrapper } // core diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index efd004efb..a792ac15b 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -34,6 +34,8 @@ #include "ApacheTracing.h" #include "ApacheConfig.h" +#include "sdkwrapper/SdkConstants.h" + std::string ApacheHooks::m_aggregatorCommDir = ""; bool ApacheHooks::m_reportAllStages = false; const std::initializer_list ApacheHooks::httpHeaders = { @@ -49,6 +51,8 @@ const char* APPD_OUTPUT_FILTER_NAME = "APPD_EUM_AUTOINJECT"; appd::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic +using namespace appd::core::sdkwrapper; + void ApacheHooks::registerHooks(apr_pool_t *p) { // Place a hook that executes when a child process is spawned @@ -516,6 +520,46 @@ void fillRequestPayload(request_rec* request, appd::core::RequestPayload* payloa val = request->method ? request->method: " "; payload->set_http_request_method(val); + // websrv-698 Setting server span attributes + payload->set_status_code(request->status); + + if (request->server) + { + payload->set_server_name(request->server->server_hostname); + } + payload->set_scheme(ap_run_http_scheme(request)); + + if (request->hostname) + { + payload->set_host(request->hostname); + } + + if (request->unparsed_uri) + { + payload->set_target(request->unparsed_uri); + } + + switch (request->proto_num) + { // TODO: consider using ap_get_protocol for other flavors + case HTTP_PROTO_1000: + payload->set_flavor(kHTTPFlavor1_0.c_str()); + break; + case HTTP_PROTO_1001: + payload->set_flavor(kHTTPFlavor1_1.c_str()); + break; + } + +#ifdef APLOG_USE_MODULE + payload->set_client_ip(request->useragent_ip); +#else + if (request->connection) + { + payload->set_client_ip(request->connection->remote_ip); + } + +#endif + + payload->set_port(ap_default_port(request)); } // We have to use this hook if we want to use directory level configuration. // post_read_request is too early in the cycle to get the config parameters for a diff --git a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp index 24652d3e4..8d4f3cfc0 100644 --- a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp @@ -63,7 +63,16 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startRequest( std::string spanName = m_spanNamer->getSpanName(payload->get_uri()); appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; - keyValueMap["request_protocol"] = payload->get_request_protocol(); + keyValueMap[kAttrRequestProtocol] = payload->get_request_protocol(); + keyValueMap[kAttrHTTPServerName] = payload->get_server_name(); + keyValueMap[kAttrHTTPMethod] = payload->get_http_request_method(); + keyValueMap[kAttrHTTPScheme] = payload->get_scheme(); + keyValueMap[kAttrNetHostName] = payload->get_host(); + keyValueMap[kAttrNETHostPort] = payload->get_port(); + keyValueMap[kAttrHTTPTarget] =payload->get_target(); + keyValueMap[kAttrHTTPFlavor] = payload->get_flavor(); + keyValueMap[kAttrHTTPStatusCode] = payload->get_status_code(); + keyValueMap[kAttrHTTPClientIP] = payload->get_client_ip(); auto span = m_sdkWrapper->CreateSpan(spanName, sdkwrapper::SpanKind::SERVER, keyValueMap, payload->get_http_headers()); LOG4CXX_TRACE(mLogger, "Span started for context: [" << wscontext diff --git a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp index c8207fbba..1651c3664 100644 --- a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp @@ -19,9 +19,12 @@ #include "mocks/mock_sdkwrapper.h" #include "api/TenantConfig.h" #include "api/Payload.h" +#include "sdkwrapper/SdkConstants.h" #include +using namespace appd::core::sdkwrapper; + class FakeRequestProcessingEngine : appd::core::RequestProcessingEngine { public: using Base = appd::core::RequestProcessingEngine; @@ -125,14 +128,32 @@ TEST(TestRequestProcessingEngine, StartRequest) std::string wscontext = "ws_context"; appd::core::RequestPayload payload; payload.set_http_headers("key", "value"); - payload.set_uri("dummy_span"); payload.set_request_protocol("GET"); + payload.set_uri("dummy_span"); + payload.set_server_name("localhost"); + payload.set_status_code(200); + payload.set_host("host"); + payload.set_http_request_method("GET"); + payload.set_scheme("http"); + payload.set_target("target"); + payload.set_flavor("1.1"); + payload.set_client_ip("clientip"); + payload.set_port(80); - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; - keyValueMap["request_protocol"] = (opentelemetry::nostd::string_view)"GET"; - std::shared_ptr span; - span.reset(new MockScopedSpan); + appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + keyValueMap[kAttrRequestProtocol] = (opentelemetry::nostd::string_view)"GET"; + keyValueMap[kAttrHTTPServerName] = (opentelemetry::nostd::string_view)"localhost"; + keyValueMap[kAttrHTTPMethod] = (opentelemetry::nostd::string_view)"GET"; + keyValueMap[kAttrNetHostName] =(opentelemetry::nostd::string_view)"host"; + keyValueMap[kAttrHTTPStatusCode] = (long) 200; + keyValueMap[kAttrNETHostPort] = (long)80; + keyValueMap[kAttrHTTPScheme] = (opentelemetry::nostd::string_view)"http"; + keyValueMap[kAttrHTTPTarget] = (opentelemetry::nostd::string_view)"target"; + keyValueMap[kAttrHTTPFlavor] = (opentelemetry::nostd::string_view)"1.1"; + keyValueMap[kAttrHTTPClientIP] = (opentelemetry::nostd::string_view)"clientip"; + std::shared_ptr span; + span.reset(new MockScopedSpan); // sdkwrapper's create span function should be called EXPECT_CALL(*sdkWrapper, CreateSpan("dummy_span", @@ -148,7 +169,7 @@ TEST(TestRequestProcessingEngine, StartRequest) auto* reqContext = (appd::core::RequestContext*)(reqHandle); ASSERT_TRUE(reqContext); - EXPECT_TRUE(reqContext->rootSpan()); + EXPECT_TRUE(reqContext->rootSpan().get() != nullptr); EXPECT_EQ(reqContext->getContextName(), "ws_context"); EXPECT_FALSE(reqContext->hasActiveInteraction());