diff --git a/.github/workflows/httpd.yml b/.github/workflows/httpd.yml index d446c10d9..f0536ea64 100644 --- a/.github/workflows/httpd.yml +++ b/.github/workflows/httpd.yml @@ -37,6 +37,32 @@ jobs: name: ${{ matrix.os }}_mod-otel.so path: /tmp/mod-otel.so + build_cmake: + name: Build module with CMake + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-18.04, ubuntu-20.04] + steps: + - name: Checkout Repo + uses: actions/checkout@v2 + - name: Setup buildtools + run: | + sudo ./instrumentation/httpd/setup-buildtools.sh + sudo ./instrumentation/httpd/setup-environment.sh + - name: Compile prerequisites + run: | + cd instrumentation/httpd + sudo ./setup-cmake.sh + - name: Compile + run: | + cd instrumentation/httpd + mkdir -p build + cd build + cmake .. + make -j2 + clang_format: name: Check code formatting runs-on: ubuntu-latest diff --git a/instrumentation/httpd/CMakeLists.txt b/instrumentation/httpd/CMakeLists.txt new file mode 100644 index 000000000..d16be741e --- /dev/null +++ b/instrumentation/httpd/CMakeLists.txt @@ -0,0 +1,63 @@ +cmake_minimum_required(VERSION 3.12) + +project(opentelemetry-httpd) + +find_package(opentelemetry-cpp REQUIRED) +find_package(Threads REQUIRED) +find_package(protobuf REQUIRED) +find_package(gRPC REQUIRED) +find_package(CURL REQUIRED) +find_package(Thrift REQUIRED) + +find_path(APR_INCLUDE_DIR + NAMES apr.h + PATHS /opt/homebrew/opt/apr/include/apr-1 + /usr/local/include/apr-1 + /usr/local/include/apr-1.0 + /usr/include/apr-1 + /usr/include/apr-1.0 + /usr/local/apr/include/apr-1 +) + +IF(NOT EXISTS "${APR_INCLUDE_DIR}/apr.h") + MESSAGE(FATAL_ERROR "APR include directory ${APR_INCLUDE_DIR} is not correct.") +ENDIF() + +find_path(APACHE_INCLUDE_DIR + NAMES httpd.h + PATHS /usr/include/apache2 + /usr/local/include/apache2 +) + +IF(NOT EXISTS "${APACHE_INCLUDE_DIR}/httpd.h") + MESSAGE(FATAL_ERROR "APACHE_INCLUDE_DIR include directory ${APACHE_INCLUDE_DIR} is not correct.") +ENDIF() + +add_library(otel_httpd_module SHARED + src/otel/mod_otel.cpp + src/otel/opentelemetry.cpp +) + +target_compile_options(otel_httpd_module + PRIVATE -Wall -Wextra +) + +install(TARGETS otel_httpd_module DESTINATION ".") + +set_target_properties(otel_httpd_module PROPERTIES + PREFIX "" +) + +target_include_directories(otel_httpd_module + PRIVATE + ${OPENTELEMETRY_CPP_INCLUDE_DIRS} + ${APACHE_INCLUDE_DIR} + ${APR_INCLUDE_DIR} +) + +target_link_libraries(otel_httpd_module + PRIVATE + ${OPENTELEMETRY_CPP_LIBRARIES} + gRPC::grpc++ +# Thrift::thrift +) diff --git a/instrumentation/httpd/Dockerfile.cmake b/instrumentation/httpd/Dockerfile.cmake new file mode 100644 index 000000000..fc5a9d80a --- /dev/null +++ b/instrumentation/httpd/Dockerfile.cmake @@ -0,0 +1,37 @@ +FROM ubuntu:18.04 + +######################################### +# copy setup stuff from opentelemetry-cpp +######################################### + +WORKDIR /setup-ci + +ADD setup-buildtools.sh /setup-ci/setup-buildtools.sh + +RUN /setup-ci/setup-buildtools.sh + +ADD setup-environment.sh /setup/setup-environment.sh + +RUN /setup/setup-environment.sh + +COPY .clang-format /root + +WORKDIR /root + +# build with CMake +COPY setup-cmake.sh . +# RUN ls +RUN /root/setup-cmake.sh + +COPY CMakeLists.txt /root +COPY src /root/src + +RUN mkdir -p build \ + && cd build \ + && cmake .. \ + && make -j2 + +COPY tools /root/tools +COPY create-otel-load.sh /root +COPY opentelemetry.conf /root +COPY httpd_install_otel.sh /root diff --git a/instrumentation/httpd/Makefile b/instrumentation/httpd/Makefile index d5407a615..d909123b6 100644 --- a/instrumentation/httpd/Makefile +++ b/instrumentation/httpd/Makefile @@ -1,7 +1,9 @@ -BUILD_IMAGE=opentelemetry-httpd-mod-dev +BUILD_IMAGE_BZL=opentelemetry-httpd-mod-dev +BUILD_IMAGE_CMAKE=opentelemetry-httpd-mod-dev-cmake CONTAINER_NAME=otel-httpd +CONTAINER_NAME_CMAKE=otel-httpd-cmake .PHONY: help build clean devsh rmcnt rming start stop @@ -11,22 +13,28 @@ help: @echo Possible targets are: @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' -build: ## build docker image with development tools - docker build -t $(BUILD_IMAGE) . +build-bazel: ## build docker image with development tools + docker build -t $(BUILD_IMAGE_BZL) . -start: build ## start new docker container - docker run -v "$(PWD)/src":/mnt/host --network host --privileged --name "$(CONTAINER_NAME)" -it $(BUILD_IMAGE) /bin/bash -l +build-cmake: ## build docker image with development tools (cmake version) + docker build -t $(BUILD_IMAGE_CMAKE) -f Dockerfile.cmake . -startifnotrunning: +start-bazel: build-bazel ## start new docker container + docker run -v "$(PWD)/src":/mnt/host --network host --privileged --name "$(CONTAINER_NAME)" -it $(BUILD_IMAGE_BZL) /bin/bash -l +start-cmake: build-cmake ## start new docker container (cmake version) + docker run -v "$(PWD)/src":/mnt/host --network host --privileged --name "$(CONTAINER_NAME_CMAKE)" -it $(BUILD_IMAGE_CMAKE) /bin/bash -l -# stop: ## stop docker image +start: start-bazel rmcnt: ## remove docker container docker container rm $(CONTAINER_NAME) || true +rmcnt-cmake: ## remove docker container (cmake version) + docker container rm $(CONTAINER_NAME_CMAKE) || true + rmimg: ## remove docker image - docker image rm $(BUILD_IMAGE) + docker image rm $(BUILD_IMAGE_BZL) clean: rmcnt rmimg ## clean both docker container and image @@ -36,3 +44,10 @@ devsh: ## attach to existing container with shell (developer shell) else \ $(MAKE) start; \ fi; + +devsh-cmake: ## attach to existing container with shell (developer shell, cmake) + if [ "docker container inspect (CONTAINER_NAME_CMAKE)" ]; then \ + docker exec -it $(CONTAINER_NAME_CMAKE) bash; \ + else \ + $(MAKE) start; \ + fi; diff --git a/instrumentation/httpd/setup-cmake.sh b/instrumentation/httpd/setup-cmake.sh new file mode 100755 index 000000000..21dee6dea --- /dev/null +++ b/instrumentation/httpd/setup-cmake.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +set -euxo pipefail + +export DEBIAN_FRONTEND=noninteractive + +apt-get update + +apt-get install --no-install-recommends --no-install-suggests -y \ + build-essential autoconf libtool pkg-config ca-certificates gcc g++ git libcurl4-openssl-dev libpcre3-dev gnupg2 lsb-release curl apt-transport-https software-properties-common zlib1g-dev +curl -o /etc/apt/trusted.gpg.d/kitware.asc https://apt.kitware.com/keys/kitware-archive-latest.asc \ + && apt-add-repository "deb https://apt.kitware.com/ubuntu/ `lsb_release -cs` main" + +apt-get install --no-install-recommends --no-install-suggests -y \ +cmake libboost-all-dev + +git clone --shallow-submodules --depth 1 --recurse-submodules -b v1.36.4 \ + https://github.com/grpc/grpc \ + && cd grpc \ + && mkdir -p cmake/build \ + && cd cmake/build \ + && cmake \ + -DgRPC_INSTALL=ON \ + -DgRPC_BUILD_TESTS=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DgRPC_BUILD_GRPC_NODE_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF \ + -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF \ + ../.. \ + && make -j2 \ + && make install + +wget https://github.com/libevent/libevent/releases/download/release-2.1.12-stable/libevent-2.1.12-stable.tar.gz \ + && tar zxf libevent-2.1.12-stable.tar.gz \ + && cd libevent-2.1.12-stable \ + && mkdir -p build \ + && cd build \ + && cmake .. \ + && make -j2 \ + && make install + +git clone --shallow-submodules --depth 1 --recurse-submodules -b v0.14.0 \ + https://github.com/apache/thrift.git \ + && cd thrift \ + && mkdir -p cmake-build \ + && cd cmake-build \ + && cmake -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING=OFF \ + -DBUILD_COMPILER=OFF \ + -DBUILD_C_GLIB=OFF \ + -DBUILD_JAVA=OFF \ + -DBUILD_JAVASCRIPT=OFF \ + -DBUILD_NODEJS=OFF \ + -DBUILD_PYTHON=OFF \ + .. \ + && make -j2 \ + && make install + +git clone --shallow-submodules --depth 1 --recurse-submodules -b "v1.0.0-rc1" \ + https://github.com/open-telemetry/opentelemetry-cpp.git \ + && cd opentelemetry-cpp \ + && mkdir build \ + && cd build \ + && cmake -DCMAKE_BUILD_TYPE=Release \ + -DWITH_OTLP=ON \ + -DWITH_JAEGER=ON \ + -DBUILD_TESTING=OFF \ + -DWITH_EXAMPLES=OFF \ + -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ + .. \ + && make -j2 \ + && make install diff --git a/instrumentation/httpd/src/otel/BUILD b/instrumentation/httpd/src/otel/BUILD index 8251b73d9..044cb1745 100644 --- a/instrumentation/httpd/src/otel/BUILD +++ b/instrumentation/httpd/src/otel/BUILD @@ -9,7 +9,6 @@ cc_library( copts = [ "-I/usr/include/apache2", "-I/usr/include/apr-1.0", - "-fpermissive", ], deps = [ "@io_opentelemetry_cpp//api", diff --git a/instrumentation/httpd/src/otel/mod_otel.cpp b/instrumentation/httpd/src/otel/mod_otel.cpp index 2485f336b..a8c85f0bd 100644 --- a/instrumentation/httpd/src/otel/mod_otel.cpp +++ b/instrumentation/httpd/src/otel/mod_otel.cpp @@ -42,12 +42,12 @@ class HttpdCarrier : public opentelemetry::context::propagation::TextMapCarrier public: apr_table_t& hdrs; HttpdCarrier(apr_table_t& headers):hdrs(headers){} - virtual nostd::string_view Get(nostd::string_view key) const noexcept override + virtual opentelemetry::v0::nostd::string_view Get(opentelemetry::v0::nostd::string_view key) const noexcept override { auto fnd = apr_table_get(&hdrs, std::string(key).c_str()); return fnd ? fnd : ""; } - virtual void Set(nostd::string_view key, nostd::string_view value) noexcept override + virtual void Set(opentelemetry::v0::nostd::string_view key, opentelemetry::v0::nostd::string_view value) noexcept override { apr_table_set(&hdrs, std::string(key).c_str(), std::string(value).c_str()); @@ -94,7 +94,7 @@ HttpdStartSpanAttributes GetAttrsFromRequest(request_rec *r) // main function // TODO: fix this for scenarios where apache configuration is just updated (apachectl -k graceful) -static void opentel_child_created(apr_pool_t *p, server_rec *s) +static void opentel_child_created(apr_pool_t*, server_rec*) { initTracer(); } @@ -277,7 +277,7 @@ static int proxy_end_handler(int *status, request_rec *r) // PARSING CONFIGURATION OPTIONS ///////////////////////////////////////////////// -static const char *otel_set_exporter(cmd_parms *cmd, void *cfg, const char *arg) +const char *otel_set_exporter(cmd_parms* /* cmd */, void */* cfg */, const char *arg) { if (!strcasecmp(arg, "file")) config.type = OtelExporterType::OSTREAM; @@ -289,7 +289,7 @@ static const char *otel_set_exporter(cmd_parms *cmd, void *cfg, const char *arg) return NULL; } -const char *otel_set_propagator(cmd_parms *cmd, void *cfg, const char *arg) +const char *otel_set_propagator(cmd_parms* /* cmd */, void* /* cfg */, const char *arg) { if (!strcasecmp(arg, "trace-context")) config.propagation = OtelPropagation::TRACE_CONTEXT; @@ -303,38 +303,38 @@ const char *otel_set_propagator(cmd_parms *cmd, void *cfg, const char *arg) return NULL; } -const char *otel_set_ignoreInbound(cmd_parms *cmd, void *cfg, int flag) +const char *otel_set_ignoreInbound(cmd_parms* /* cmd */, void* /* cfg */, int flag) { config.ignore_inbound = flag; return NULL; } -const char *otel_set_path(cmd_parms *cmd, void *cfg, const char *arg) +const char *otel_set_path(cmd_parms* /* cmd */, void* /* cfg */, const char *arg) { config.fname = arg; return NULL; } -const char *otel_set_endpoint(cmd_parms *cmd, void *cfg, const char *arg) +const char *otel_set_endpoint(cmd_parms* /* cmd */, void* /* cfg */, const char *arg) { config.endpoint = arg; return NULL; } -const char *otel_set_attribute(cmd_parms *cmd, void *cfg, const char *attrName, const char *attrValue) +const char *otel_set_attribute(cmd_parms* /* cmd */, void* /* cfg */, const char *attrName, const char *attrValue) { config.attributes[attrName] = attrValue; return NULL; } -const char *otel_set_resource(cmd_parms *cmd, void *cfg, const char *attrName, const char *attrValue) +const char *otel_set_resource(cmd_parms* /* cmd */, void* /* cfg */, const char *attrName, const char *attrValue) { config.resources[attrName] = attrValue; return NULL; } -const char *otel_cfg_batch(cmd_parms *cmd, - void *cfg, +const char *otel_cfg_batch(cmd_parms* /* cmd */, + void* /* cfg */, const char *max_queue_size, const char *schedule_delay_millis, const char *max_export_batch_size) @@ -349,7 +349,7 @@ const char *otel_cfg_batch(cmd_parms *cmd, extern "C" { -static void opentel_register_hooks(apr_pool_t *p) +static void opentel_register_hooks(apr_pool_t* /* p */) { ap_hook_child_init(opentel_child_created, NULL, NULL, APR_HOOK_MIDDLE); ap_hook_quick_handler(opentel_handler, NULL, NULL, APR_HOOK_FIRST); @@ -364,38 +364,38 @@ static void opentel_register_hooks(apr_pool_t *p) static const command_rec opentel_directives[] = { AP_INIT_TAKE1("OpenTelemetryExporter", - otel_set_exporter, + reinterpret_cast(otel_set_exporter), NULL, RSRC_CONF, "Set specific exporter type"), - AP_INIT_TAKE1("OpenTelemetryPath", otel_set_path, NULL, RSRC_CONF, "Set path for exporter"), + AP_INIT_TAKE1("OpenTelemetryPath", reinterpret_cast(otel_set_path), NULL, RSRC_CONF, "Set path for exporter"), AP_INIT_TAKE1("OpenTelemetryEndpoint", - otel_set_endpoint, + reinterpret_cast(otel_set_endpoint), NULL, RSRC_CONF, "Set endpoint for exporter"), AP_INIT_TAKE2("OpenTelemetrySetAttribute", - otel_set_attribute, + reinterpret_cast(otel_set_attribute), NULL, RSRC_CONF, "Set additional attribute for each span"), AP_INIT_TAKE2("OpenTelemetrySetResource", - otel_set_resource, + reinterpret_cast(otel_set_resource), NULL, RSRC_CONF, "Set resource"), AP_INIT_TAKE3("OpenTelemetryBatch", - otel_cfg_batch, + reinterpret_cast(otel_cfg_batch), NULL, RSRC_CONF, "Configure batch processing"), AP_INIT_FLAG("OpenTelemetryIgnoreInbound", - otel_set_ignoreInbound, + reinterpret_cast(otel_set_ignoreInbound), NULL, RSRC_CONF, "Enable or disable context propagation from incoming requests."), AP_INIT_TAKE1("OpenTelemetryPropagators", - otel_set_propagator, + reinterpret_cast(otel_set_propagator), NULL, RSRC_CONF, "Configure propagators"), diff --git a/instrumentation/httpd/src/otel/opentelemetry.cpp b/instrumentation/httpd/src/otel/opentelemetry.cpp index ec9ca635c..0f98bd2c4 100644 --- a/instrumentation/httpd/src/otel/opentelemetry.cpp +++ b/instrumentation/httpd/src/otel/opentelemetry.cpp @@ -93,7 +93,7 @@ void initTracer() resAttrs[it.first] = it.second; } - auto provider = nostd::shared_ptr( + auto provider = opentelemetry::v0::nostd::shared_ptr( new sdktrace::TracerProvider(std::move(processor), opentelemetry::sdk::resource::Resource::Create(resAttrs)) ); @@ -102,7 +102,7 @@ void initTracer() opentelemetry::trace::Provider::SetTracerProvider(provider); } -nostd::shared_ptr get_tracer() +opentelemetry::v0::nostd::shared_ptr get_tracer() { auto provider = opentelemetry::trace::Provider::GetTracerProvider(); return provider->GetTracer(KHTTPDOTelTracerName); diff --git a/instrumentation/httpd/src/otel/opentelemetry.h b/instrumentation/httpd/src/otel/opentelemetry.h index 8b5c59b59..7282150b4 100644 --- a/instrumentation/httpd/src/otel/opentelemetry.h +++ b/instrumentation/httpd/src/otel/opentelemetry.h @@ -20,14 +20,15 @@ #include #include -#include "opentelemetry/exporters/ostream/span_exporter.h" +#include "opentelemetry/context/context.h" +#include "opentelemetry/nostd/string_view.h" #include "opentelemetry/sdk/trace/batch_span_processor.h" #include "opentelemetry/trace/provider.h" namespace httpd_otel { -const nostd::string_view KHTTPDOTelTracerName = "httpd"; +const opentelemetry::nostd::string_view KHTTPDOTelTracerName = "httpd"; enum class OtelExporterType { @@ -85,8 +86,8 @@ struct HttpdEndSpanAttributes // to be called explictly inside Destruct method struct ExtraRequestData { // context which we pass - nostd::unique_ptr token; - nostd::shared_ptr span; + opentelemetry::nostd::unique_ptr token; + opentelemetry::nostd::shared_ptr span; HttpdStartSpanAttributes startAttrs; HttpdEndSpanAttributes endAttrs; // Sets attributes for HTTP request. @@ -113,7 +114,7 @@ struct ExtraRequestData // Initializes OpenTelemetry module. void initTracer(); // Returns default (global) tracer. -nostd::shared_ptr get_tracer(); +opentelemetry::nostd::shared_ptr get_tracer(); } // namespace httpd_otel