From 42d82523e162ee1adacaf9e6485926063fa8900e Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Mon, 27 Jun 2022 13:24:23 +0530 Subject: [PATCH 01/77] Added CI for otel-webserver-module (#182) * test-ci * update docker * adding docker * Fix * testing ubuntu * testing ubuntu docker * added build command * Added test step * Fixed unit test build command * Added centos7 * Added buildx for caching * Added cache * Added artifacts * Corrected artifacts path * Updated centos7 with artifacts * Added correction * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Corrected path * Final check * Added final changes * Added ci for centos6 --- .github/workflows/webserver.yml | 165 ++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 .github/workflows/webserver.yml diff --git a/.github/workflows/webserver.yml b/.github/workflows/webserver.yml new file mode 100644 index 000000000..525d77305 --- /dev/null +++ b/.github/workflows/webserver.yml @@ -0,0 +1,165 @@ +name: webserver instrumentation CI + +on: + push: + branches: [ main ] + paths: + - 'instrumentation/otel-webserver-module/**' + - '.github/workflows/webserver.yml' + pull_request: + branches: [ main ] + paths: + - 'instrumentation/otel-webserver-module/**' + - '.github/workflows/webserver.yml' + +jobs: + webserver-build-test-ubuntu: + name: apache-ubuntu + runs-on: ubuntu-20.04 + steps: + - name: checkout otel webserver + uses: actions/checkout@v3 + - name: setup buildx + id: buildx + uses: docker/setup-buildx-action@master + with: + install: true + - name: cache docker layers + uses: actions/cache@v3 + with: + path: /tmp/buildx-cache/ + key: apache-ubuntu-20.04-${{ github.sha }} + restore-keys: | + apache-ubuntu-20.04 + - name: setup docker image + run: | + cd instrumentation/otel-webserver-module + docker buildx build -t apache_ubuntu -f docker/ubuntu20.04/Dockerfile \ + --cache-from type=local,src=/tmp/buildx-cache/apache_ubuntu \ + --cache-to type=local,dest=/tmp/buildx-cache/apache_ubuntu-new \ + --load . + - name: build + run: | + docker run -idt --name apache_ubuntu_container apache_ubuntu /bin/bash + cd instrumentation/otel-webserver-module + docker exec apache_ubuntu_container bash -c \ + 'cd /otel-webserver-module; rm -rf *;' + docker cp . $(docker inspect --format="{{.Id}}" apache_ubuntu_container):/otel-webserver-module/ + docker exec apache_ubuntu_container bash -c \ + 'cd /otel-webserver-module; rm -rf build; \ + cp -r /dependencies /otel-webserver-module/; \ + cp -r /build-dependencies /otel-webserver-module/; \ + ./gradlew assembleApacheModule -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 + mv /tmp/buildx-cache/apache_ubuntu-new /tmp/buildx-cache/apache_ubuntu + + webserver-build-test-centos7: + name: apache-centos7 + runs-on: ubuntu-20.04 + steps: + - name: checkout otel webserver + uses: actions/checkout@v3 + - name: setup buildx + id: buildx + uses: docker/setup-buildx-action@master + with: + install: true + - name: cache docker layers + uses: actions/cache@v3 + with: + path: /tmp/buildx-cache/ + key: apache-centos7-${{ github.sha }} + restore-keys: | + apache-centos7 + - name: setup docker image + run: | + cd instrumentation/otel-webserver-module + docker buildx build -t apache_centos7 -f docker/centos7/Dockerfile \ + --cache-from type=local,src=/tmp/buildx-cache/apache_centos7 \ + --cache-to type=local,dest=/tmp/buildx-cache/apache_centos7-new \ + --load . + - name: build + run: | + docker run -idt --name apache_centos7_container apache_centos7 /bin/bash + cd instrumentation/otel-webserver-module + docker exec apache_centos7_container bash -c \ + 'cd /otel-webserver-module; rm -rf *;' + docker cp . $(docker inspect --format="{{.Id}}" apache_centos7_container):/otel-webserver-module/ + docker exec apache_centos7_container bash -c \ + 'cd /otel-webserver-module; rm -rf build; \ + cp -r /dependencies /otel-webserver-module/; \ + cp -r /build-dependencies /otel-webserver-module/; \ + ./gradlew assembleApacheModule' + - name: unit test + run: | + docker exec apache_centos7_container bash -c \ + 'cd /otel-webserver-module; ./gradlew runUnitTest' + - name: update cache + run: | + rm -rf /tmp/buildx-cache/apache_centos7 + mv /tmp/buildx-cache/apache_centos7-new /tmp/buildx-cache/apache_centos7 + - name: copy artifacts + id: artifacts + run: | + cd instrumentation/otel-webserver-module + mkdir -p /tmp/apache_centos7/ + docker cp apache_centos7_container:/otel-webserver-module/build/opentelemetry-webserver-sdk-x64-linux.tgz \ + /tmp/apache_centos7/ + - name: upload artifacts + uses: actions/upload-artifact@v3 + with: + name: opentelemetry-webserver-sdk-x64-linux.tgz + path: /tmp/apache_centos7/opentelemetry-webserver-sdk-x64-linux.tgz + + webserver-build-test-centos6: + name: apache-centos6 + runs-on: ubuntu-20.04 + steps: + - name: checkout otel webserver + uses: actions/checkout@v3 + - name: setup buildx + id: buildx + uses: docker/setup-buildx-action@master + with: + install: true + - name: cache docker layers + uses: actions/cache@v3 + with: + path: /tmp/buildx-cache/ + key: apache-centos6-${{ github.sha }} + restore-keys: | + apache-centos6 + - name: setup docker image + run: | + cd instrumentation/otel-webserver-module + docker buildx build -t apache_centos6 -f Dockerfile \ + --cache-from type=local,src=/tmp/buildx-cache/apache_centos6 \ + --cache-to type=local,dest=/tmp/buildx-cache/apache_centos6-new \ + --load . + - name: build + run: | + docker run -idt --name apache_centos6_container apache_centos6 /bin/bash + cd instrumentation/otel-webserver-module + docker exec apache_centos6_container bash -c \ + 'cd /otel-webserver-module; rm -rf *;' + docker cp . $(docker inspect --format="{{.Id}}" apache_centos6_container):/otel-webserver-module/ + docker exec apache_centos6_container bash -c \ + 'cd /otel-webserver-module; rm -rf build; \ + cp -r /dependencies /otel-webserver-module/; \ + cp -r /build-dependencies /otel-webserver-module/; \ + ./gradlew assembleApacheModule' + - name: unit test + run: | + docker exec apache_centos6_container bash -c \ + 'cd /otel-webserver-module; ./gradlew runUnitTest' + - name: update cache + run: | + rm -rf /tmp/buildx-cache/apache_centos6 + mv /tmp/buildx-cache/apache_centos6-new /tmp/buildx-cache/apache_centos6 + From 9fba217227c26f05f9c94db390fa22996ba989e8 Mon Sep 17 00:00:00 2001 From: Max Golovanov Date: Thu, 30 Jun 2022 13:51:49 -0700 Subject: [PATCH 02/77] Address spec compliance issue (SetName method is deprecated and removed) (#183) * Address spec compliance issue (SetName method is deprecated and removed in the base class) * Update version to 1.1.2 to reflect the log recordable API change * Update to latest OpenTelemetry C++ SDK release tag --- exporters/fluentd/CMakeLists.txt | 92 ++++++++++--------- .../fluentd/cmake/opentelemetry-cpp.cmake | 2 +- exporters/fluentd/example/log/main.cc | 3 + exporters/fluentd/example/trace/main.cc | 2 + .../exporters/fluentd/log/recordable.h | 2 +- 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/exporters/fluentd/CMakeLists.txt b/exporters/fluentd/CMakeLists.txt index ec8d39092..7dc94de16 100644 --- a/exporters/fluentd/CMakeLists.txt +++ b/exporters/fluentd/CMakeLists.txt @@ -14,20 +14,28 @@ cmake_minimum_required(VERSION 3.12) -project(opentelemetry-fluentd) - +# MAIN_PROJECT CHECK +## determine if fluentd exporter is built as a subproject (using add_subdirectory) or if it is the main project +## +set(MAIN_PROJECT OFF) +if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + project(opentelemetry-fluentd) + set(MAIN_PROJECT ON) +endif() add_definitions(-DHAVE_CONSOLE_LOG) add_definitions(-DENABLE_LOGS_PREVIEW) -find_package(opentelemetry-cpp QUIET) -if(opentelemetry_cpp_FOUND) - message("Using external opentelemetry-cpp") -else() - include(cmake/opentelemetry-cpp.cmake) - build_opentelemetry() - set(OPENTELEMETRY_CPP_INCLUDE_DIRS "") - set(OPENTELEMETRY_CPP_LIBRARIES "opentelemetry::libopentelemetry") - message("\nopentelemetry-cpp package was not found. Cloned from github") +if (MAIN_PROJECT) + find_package(opentelemetry-cpp QUIET) + if(opentelemetry_cpp_FOUND) + message("Using external opentelemetry-cpp") + else() + include(cmake/opentelemetry-cpp.cmake) + build_opentelemetry() + set(OPENTELEMETRY_CPP_INCLUDE_DIRS "") + set(OPENTELEMETRY_CPP_LIBRARIES "opentelemetry::libopentelemetry") + message("\nopentelemetry-cpp package was not found. Cloned from github") + endif() endif() find_package(nlohmann_json QUIET) @@ -151,36 +159,38 @@ if(BUILD_TESTING) TEST_LIST fluentd_recordable_logs_test) endif() # BUILD_TESTING -# config file for find_packages(opentelemetry-cpp-fluentd CONFIG) -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) - -set(OPENTELEMETRY_CPP_FLUENTD_VERSION "1.1.1") -set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") -configure_package_config_file( - "${CMAKE_CURRENT_LIST_DIR}/cmake/opentelemetry-cpp-fluentd-config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake" - INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" - # PATH_VARS OPENTELEMETRY_CPP_FLUENTD_VERSION PROJECT_NAME INCLUDE_INSTALL_DIR - # CMAKE_INSTALL_LIBDIR - PATH_VARS PROJECT_NAME INCLUDE_INSTALL_DIR CMAKE_INSTALL_LIBDIR - NO_CHECK_REQUIRED_COMPONENTS_MACRO) - -# Write version file for find_packages(opentelemetry-cpp-fluentd CONFIG) -write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake" - VERSION ${OPENTELEMETRY_CPP_FLUENTD_VERSION} - COMPATIBILITY ExactVersion) +if (MAIN_PROJECT) + # config file for find_packages(opentelemetry-cpp-fluentd CONFIG) + include(GNUInstallDirs) + include(CMakePackageConfigHelpers) -install( - FILES + set(OPENTELEMETRY_CPP_FLUENTD_VERSION "1.1.2") + set(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") + configure_package_config_file( + "${CMAKE_CURRENT_LIST_DIR}/cmake/opentelemetry-cpp-fluentd-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" + # PATH_VARS OPENTELEMETRY_CPP_FLUENTD_VERSION PROJECT_NAME INCLUDE_INSTALL_DIR + # CMAKE_INSTALL_LIBDIR + PATH_VARS PROJECT_NAME INCLUDE_INSTALL_DIR CMAKE_INSTALL_LIBDIR + NO_CHECK_REQUIRED_COMPONENTS_MACRO) + + # Write version file for find_packages(opentelemetry-cpp-fluentd CONFIG) + write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") - -# Export all components -export( - EXPORT "${PROJECT_NAME}-target" - NAMESPACE "${PROJECT_NAME}::" - FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-target.cmake" -) + VERSION ${OPENTELEMETRY_CPP_FLUENTD_VERSION} + COMPATIBILITY ExactVersion) + + install( + FILES + "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + # Export all components + export( + EXPORT "${PROJECT_NAME}-target" + NAMESPACE "${PROJECT_NAME}::" + FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-target.cmake" + ) +endif() diff --git a/exporters/fluentd/cmake/opentelemetry-cpp.cmake b/exporters/fluentd/cmake/opentelemetry-cpp.cmake index 2b1911649..af4e6a20e 100644 --- a/exporters/fluentd/cmake/opentelemetry-cpp.cmake +++ b/exporters/fluentd/cmake/opentelemetry-cpp.cmake @@ -1,5 +1,5 @@ if("${opentelemetry-cpp-tag}" STREQUAL "") - set(opentelemetry-cpp-tag "75c2a8f7a6bf81d9799e76804473609cc236b7be") #to incorporate PR#1325 + set(opentelemetry-cpp-tag "96534a7c2370099ada8bd9dcdc7236c76adf47d9") # OpenTelemetry C++ v1.4.1 endif() function(target_create _target _lib) add_library(${_target} STATIC IMPORTED) diff --git a/exporters/fluentd/example/log/main.cc b/exporters/fluentd/example/log/main.cc index b030c1be5..e9eb4d9b3 100644 --- a/exporters/fluentd/example/log/main.cc +++ b/exporters/fluentd/example/log/main.cc @@ -11,7 +11,10 @@ namespace sdk_logs = opentelemetry::sdk::logs; namespace nostd = opentelemetry::nostd; + +#ifndef HAVE_CONSOLE_LOG #define HAVE_CONSOLE_LOG +#endif namespace { void initLogger() { diff --git a/exporters/fluentd/example/trace/main.cc b/exporters/fluentd/example/trace/main.cc index 217865b93..4726143f3 100644 --- a/exporters/fluentd/example/trace/main.cc +++ b/exporters/fluentd/example/trace/main.cc @@ -12,7 +12,9 @@ namespace sdktrace = opentelemetry::sdk::trace; namespace nostd = opentelemetry::nostd; +#ifndef HAVE_CONSOLE_LOG #define HAVE_CONSOLE_LOG +#endif namespace { void initTracer() { diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h index 3c8c70e82..6d26f4d33 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h @@ -33,7 +33,7 @@ class Recordable final : public opentelemetry::sdk::logs::Recordable { * Set name for this log * @param name the name to set */ - void SetName(nostd::string_view name) noexcept override; + void SetName(nostd::string_view name) noexcept; /** * Set body field for this log. From f9a3ed229e845597a0ec87960e473eb949b86904 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Mon, 4 Jul 2022 16:46:21 +0530 Subject: [PATCH 03/77] Nginx contrib (#178) * Added dependencies of Nginx Build (#158) * updated nginx build directory (#159) * nginx source code (#160) * Add license (#162) * Add license * removing Ubuntu condition * Nomenclature changes from Appdynamics to OpenTelemetry (#163) * Changed appd to otel * Added build command for Nginx Module * Added a missing file to be built * Incorporated Review comments * Nginx docker (#167) * Changing docker compose * centos7 * Updated README for Nginx instrumentation (#168) * Updated README for Nginx instrumentation * Updated README.md * Updated README.md * Set span status according to Semantic Conventions of Http (#164) (#169) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine Co-authored-by: Narasimha * Updated error codes (#170) * Merged from Main branch (#172) * Set span status according to Semantic Conventions of Http (#164) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed UT failure (#171) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed unit test failure Co-authored-by: Narasimha * Merge from main (#181) * Set span status according to Semantic Conventions of Http (#164) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed UT failure (#171) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed unit test failure Co-authored-by: Narasimha Co-authored-by: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Co-authored-by: Narasimha --- .../otel-webserver-module/Dockerfile | 15 + .../otel-webserver-module/README.md | 90 +- .../otel-webserver-module/build.gradle | 103 ++ .../conf/nginx/opentelemetry_module.conf | 21 + .../otel-webserver-module/docker-compose.yml | 33 + .../docker/centos7/Dockerfile | 15 + .../docker/nginx/centos/Dockerfile | 283 ++++ .../docker/nginx/centos7/Dockerfile | 301 ++++ .../docker/ubuntu20.04/Dockerfile | 16 + .../include/core/api/opentelemetry_ngx_api.h | 72 + .../otel-webserver-module/src/build.gyp | 1 + .../src/core/api/ApiUtils.cpp | 2 +- .../src/core/api/opentelemetry_ngx_api.cpp | 112 ++ .../otel-webserver-module/src/nginx/Makefile | 1306 ++++++++++++++++ .../otel-webserver-module/src/nginx/config | 16 + .../src/nginx/ngx_http_opentelemetry_log.c | 52 + .../src/nginx/ngx_http_opentelemetry_log.h | 29 + .../src/nginx/ngx_http_opentelemetry_module.c | 1358 +++++++++++++++++ .../src/nginx/ngx_http_opentelemetry_module.h | 151 ++ .../test/NginxTesting.sh | 93 ++ 20 files changed, 4067 insertions(+), 2 deletions(-) create mode 100644 instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf create mode 100644 instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile create mode 100644 instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile create mode 100644 instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h create mode 100644 instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp create mode 100644 instrumentation/otel-webserver-module/src/nginx/Makefile create mode 100644 instrumentation/otel-webserver-module/src/nginx/config create mode 100644 instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c create mode 100644 instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h create mode 100644 instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c create mode 100644 instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h create mode 100755 instrumentation/otel-webserver-module/test/NginxTesting.sh diff --git a/instrumentation/otel-webserver-module/Dockerfile b/instrumentation/otel-webserver-module/Dockerfile index 417668d5b..f94801d21 100644 --- a/instrumentation/otel-webserver-module/Dockerfile +++ b/instrumentation/otel-webserver-module/Dockerfile @@ -23,6 +23,8 @@ ARG LIBTOOL_VERSION="2.4.6" ARG LOG4CXX_VERSION="0.11.0" ARG GTEST_VERSION="1.10.0" ARG AUTOMAKE_VERSION="1.16.3" +ARG PCRE_VERSION="8.44" +ARG NGINX_VERSION="1.18.0" # create default non-root user @@ -214,6 +216,14 @@ RUN mkdir -p dependencies/googletest/${GTEST_VERSION}/ \ && make install \ && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ +# install pcre +RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ + && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ + && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ + && cd pcre-${PCRE_VERSION} \ + && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ + && make && make install \ + && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} #Installing Apache and apr source code RUN mkdir build-dependencies \ @@ -230,6 +240,11 @@ RUN mkdir build-dependencies \ && tar -xf httpd-2.4.23.tar.gz \ && mv -f httpd-2.4.23 build-dependencies +# install nginx +RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ + && rm -rf nginx-${NGINX_VERSION}.tar.gz + # Build Webserver Module COPY . /otel-webserver-module diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 7deddea8b..43f7a4886 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -95,8 +95,96 @@ After going inside the container run the following commands ```cd \otel-webserve The build file can be copied at a suitable location in User's system by running the command ```docker cp :/otel-webserver-module/build/opentelemetry-webserver-sdk-x64-linux.tgz ```. The installation steps can be inferred from ```install.sh``` script. +## Nginx Webserver Module + +Similar to Apache, Nginx Webserver Module also enables tracing of incoming requests to the server by injecting instrumentation into the Nginx server at runtime. It also captures the response time of the individual modules involved in the request processing. + +### Module Wise Monitoring + +Currently, Nginx Webserver module monitores some fixed set of modules, which gets involved in the request processing. Following are the set of modules monitored: +* ngx_http_realip_module +* ngx_http_rewrite_module +* ngx_http_limit_conn_module +* ngx_http_limit_req_module +* ngx_http_auth_request_module +* ngx_http_auth_basic_module +* ngx_http_access_module +* ngx_http_static_module +* ngx_http_gzip_static_module +* ngx_http_dav_module +* ngx_http_autoindex_module +* ngx_http_index_module +* ngx_http_random_index_module +* ngx_http_log_module + +### Third Party Dependencies + +| Library | Present Version | +| ---------------------------------------------- | ----------- | +| Apache-log4cxx | 0.11.0 | +| Apr | 1.7.0 | +| Apr-util | 1.6.1 | +| Expat | 2.3.0 | +| Boost | 1.75.0 | +| Opentelemetry - C++ SDK | 1.2.0 | +| Googletest | 1.10.0 | +| Pcre | 8.44 | + +*There are some libraries which are just used to generate Apache Header files + +| Library | Present Version | +| ---------------------------------------------- | ----------- | +| Nginx | 1.18.0 | +| Apr | 1.7.0 | +| Apr-util | 1.6.1 | + +### Configuration +| Configuration Directives | Default Values | Remarks | +| ---------------------------------------------- | --------------- | ------------------------------------------ | +|*NginxModuleEnabled* | ON | OPTIONAL: Needed for instrumenting Nginx Webserver | +|*NginxModuleOtelSpanExporter* | otlp | OPTIONAL: Specify the span exporter to be used. Supported values are "otlp" and "ostream". All other supported values would be added in future. | +|*NginxModuleOtelExporterEndpoint:* | | REQUIRED: The endpoint otel exporter exports to. Example "docker.for.mac.localhost:4317" | +|*NginxModuleOtelSpanProcessor* | batch | OPTIONAL: Specify the processor to select to. Supported values are "simple" and "batch".| +|*NginxModuleOtelSampler* | AlwaysOn | OPTIONAL: Supported values are "AlwaysOn" and "AlwaysOff" | +|*NginxModuleOtelMaxQueueSize* | 2048 | OPTIONAL: The maximum queue size. After the size is reached spans are dropped| +|*NginxModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports| +|*NginxModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled| +|*NginxModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | +|*NginxModuleServiceName* | | REQUIRED: A namespace for the ServiceName| +|*NginxModuleServiceNamespace* | | REQUIRED: Logical name of the service | +|*NginxModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | +|*NginxModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log| +|*NginxModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| +|*NginxModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation| +|*NginxModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| + + +### Build and Installation +#### Prerequisites +- Docker Desktop should be installed on the system + +#### Platform Supported +- The build is supported for **x86-64** platforms. +- Currently, the build is supported on **Centos6** and **Centos7** + +#### Automatic build and Installation + +We will use Docker to run the Module. First, it is to be made sure that the Docker is up and running. +Then execute the following commands -: +``` +docker-compose --profile centos_nginx build +docker-compose --profile centos_nginx up +``` +Alternatively, replace the value of *centos_nginx* from **'centos_nginx'** to **'centos7_nginx'** to build in respective supported platforms. + +This would start the container alongwith the the Opentelemetry Collector and Zipkin. You can check the traces on Zipkin dashboard by checking the port number of Zipkin using ```docker ps``` command. Multiple requests can be sent using the browser. + +#### Manual build and Installation + +TBD + + ### Maintainers * [Kumar Pratyush](https://github.com/kpratyus), Cisco -* [Lakshay Gaba](https://github.com/lakshay141), Cisco * [Debajit Das](https://github.com/DebajitDas), Cisco diff --git a/instrumentation/otel-webserver-module/build.gradle b/instrumentation/otel-webserver-module/build.gradle index b18d9963b..08a72cb5b 100644 --- a/instrumentation/otel-webserver-module/build.gradle +++ b/instrumentation/otel-webserver-module/build.gradle @@ -49,9 +49,11 @@ project.ext { apache22Version = "2.2.31" apache24Version = "2.4.23" + nginxVersion = '1.18.0' libraryStageDir = "${platBuildDir}/opentelemetry-webserver-sdk" apacheStageDir = "${libraryStageDir}/WebServerModule/Apache" + nginxStageDir = "${libraryStageDir}/WebServerModule/Nginx" coverageCompilerFlags = '-g -fprofile-arcs -ftest-coverage' coverageLinkerFlags = '-lgcov --coverage' @@ -360,6 +362,107 @@ task assembleApacheModule(type: Tar) { compression Compression.GZIP } +// NGINX +task extractNginx(type: Copy) { + from "build-dependencies" + into buildDir +} + +task configureNginx(type: Exec){ + group = 'OpenTelemetry module for Nginx' + description = 'Run configure to generate the build files for OpenTelemetry Module for Nginx' + + dependsOn extractNginx + + workingDir "${buildDir}/nginx-${nginxVersion}" + commandLine './configure', "--with-compat", "--with-cc-opt=-Wno-error -Wno-unused-variable -Wno-unused-but-set-variable", "--with-ld-opt=-L${libraryStageDir}/sdk_lib/lib", "--add-dynamic-module=${projectDir}/src/nginx" +} + +task delMakefile(type: Exec){ + group = 'OpenTelemetry module for Nginx' + description = 'Deleting old Makefile' + + workingDir "${buildDir}/nginx-${nginxVersion}/objs" + commandLine 'rm', '-rf', 'Makefile' +} + +task copyMakefile(type: Copy){ + group = 'OpenTelemetry module for Nginx' + description = 'Copying Makefile for compiling Nginx Web Server Agent' + + dependsOn delMakefile + + from "src/nginx/Makefile" + into "${buildDir}/nginx-${nginxVersion}/objs/" +} + +task buildNginxModule(type: Exec) { + group = 'OpenTelemetry module for Nginx' + description = 'Build the Nginx Web Server Agent' + + dependsOn configureNginx + dependsOn stageLibrary + dependsOn copyMakefile + + outputs.file "${buildDir}/nginx-${nginxVersion}/objs/ngx_http_opentelemetry_module.so" + + workingDir "${buildDir}/nginx-${nginxVersion}" + commandLine 'make', 'modules' +} + +task stageNginxModule(type: Copy) { + group = 'OpenTelemetry module for Nginx' + description = 'Stage the Nginx Web Server Agent distribution directory' + +// dependsOn stageLibrary + + from buildNginxModule + into nginxStageDir +} + +task stripNginxModule(type: Exec){ + group = 'OpenTelemetry module for Nginx' + description = 'Strip the production Nginx Web Server Agent' + + dependsOn stageNginxModule + + onlyIf { !debug } + + inputs.dir stageNginxModule + outputs.file "${nginxStageDir}/ngx_http_opentelemetry_module.${sharedLibraryExt}" + + workingDir nginxStageDir + commandLine 'strip', '-x', "ngx_http_opentelemetry_module.${sharedLibraryExt}" +} + +task assembleNginxModule(type: Tar) { + group = 'Nginx Web Server Module' + description = 'Assemble the Nginx Web Server module artifact (tgz)' + + dependsOn stripNginxModule + + from libraryStageDir + baseName "opentelemetry-webserver-sdk-${osArch}-${osName}" + into 'opentelemetry-webserver-sdk' + destinationDir file(buildDir) + compression Compression.GZIP +} + +// Packages the complete Web Server Agent +task assembleWebServerModule(type: Tar) { + group = 'Web Server Agent' + description = 'Assemble the Web Server agent artifact (tgz)' + + dependsOn stripApacheModule + dependsOn stripNginxModule + + from libraryStageDir + baseName "opentelemetry-webserver-sdk-${osArch}-${osName}" + into 'opentelemetry-webserver-sdk' + destinationDir file(buildDir) + compression Compression.GZIP +} + // Tests task gypUnitTest(type: Exec) { diff --git a/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf b/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf new file mode 100644 index 000000000..27532995d --- /dev/null +++ b/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf @@ -0,0 +1,21 @@ +NginxModuleEnabled ON; +#NginxModule Otel Exporter details +NginxModuleOtelSpanExporter otlp; +NginxModuleOtelExporterEndpoint docker.for.mac.localhost:4317; +# SSL Certificates +#NginxModuleOtelSslEnabled ON +#NginxModuleOtelSslCertificatePath +#NginxModuleOtelSpanProcessor Batch +#NginxModuleOtelSampler AlwaysOn +#NginxModuleOtelMaxQueueSize 1024 +#NginxModuleOtelScheduledDelayMillis 3000 +#NginxModuleOtelExportTimeoutMillis 30000 +#NginxModuleOtelMaxExportBatchSize 1024 +NginxModuleServiceName DemoService; +NginxModuleServiceNamespace DemoServiceNamespace; +NginxModuleServiceInstanceId DemoInstanceId; +NginxModuleResolveBackends ON; +NginxModuleTraceAsError ON; +#NginxModuleWebserverContext DemoService DemoServiceNamespace DemoInstanceId +#NginxModuleSegmentType custom +#NginxModuleSegmentParameter 15,1,6,7 \ No newline at end of file diff --git a/instrumentation/otel-webserver-module/docker-compose.yml b/instrumentation/otel-webserver-module/docker-compose.yml index be31bb2fa..7d191c080 100644 --- a/instrumentation/otel-webserver-module/docker-compose.yml +++ b/instrumentation/otel-webserver-module/docker-compose.yml @@ -43,6 +43,35 @@ services: - "9000:80" depends_on: - otel-collector + nginx_centos: + build: + context: . + dockerfile: docker/nginx/centos/Dockerfile + image: nginx_centos + hostname: webserver + container_name: nginx_centos + command: bash -c "export LD_LIBRARY_PATH=/opt/opentelemetry-webserver-sdk/sdk_lib/lib && nginx && tail -f /dev/null" + profiles: + - centos_nginx + ports: + - "8008:80" + depends_on: + - otel-collector + nginx_centos7: + build: + context: . + dockerfile: docker/nginx/centos7/Dockerfile + image: nginx_centos7 + hostname: webserver + container_name: nginx_centos7 + command: bash -c "export LD_LIBRARY_PATH=/opt/opentelemetry-webserver-sdk/sdk_lib/lib && nginx && tail -f /dev/null" + profiles: + - centos7_nginx + ports: + - "8012:80" + depends_on: + - otel-collector + # Collector otel-collector: @@ -52,6 +81,8 @@ services: - default - ubuntu20.04 - centos7 + - centos_nginx + - centos7_nginx command: ["--config=/etc/otel-config.yml", "--log-level=DEBUG", "${OTELCOL_ARGS}"] volumes: - ./otel-config.yml:/etc/otel-config.yml @@ -70,6 +101,8 @@ services: - default - ubuntu20.04 - centos7 + - centos_nginx + - centos7_nginx ports: - "9411:9411" - "9410:9410" diff --git a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile index 8a26149d5..66fe742d3 100644 --- a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile @@ -25,6 +25,8 @@ ARG GTEST_VERSION="1.10.0" ARG AUTOMAKE_VERSION="1.16.3" ARG PERL_VERSION="5.20.2" ARG PERL_CPANVERSION="5.0" +ARG PCRE_VERSION="8.44" +ARG NGINX_VERSION="1.18.0" # create default non-root user RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser @@ -232,6 +234,14 @@ RUN mkdir -p dependencies/googletest/${GTEST_VERSION}/ \ && make install \ && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ +# install pcre +RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ + && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ + && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ + && cd pcre-${PCRE_VERSION} \ + && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ + && make && make install \ + && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} #Installing Apache and apr source code RUN mkdir build-dependencies \ @@ -248,6 +258,11 @@ RUN mkdir build-dependencies \ && tar -xf httpd-2.4.23.tar.gz \ && mv -f httpd-2.4.23 build-dependencies +# install nginx +RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ + && rm -rf nginx-${NGINX_VERSION}.tar.gz + # Build Webserver Module COPY . /otel-webserver-module diff --git a/instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile b/instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile new file mode 100644 index 000000000..486ba8641 --- /dev/null +++ b/instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile @@ -0,0 +1,283 @@ +FROM centos:6.9 + +ARG BUILD_NUMBER + +LABEL NAME=apm/build-image-webserver-agent-centos6-x64 VERSION=$BUILD_NUMBER + +ENV GOSU_ARCH amd64 +ENV JDK_ARCH x64 + +ARG PYTHON_VERSION="2.7.8" +ARG CMAKE_VERSION="3.20" +ARG CMAKE_0VERSION="3.20.0" +ARG GRPC_VERSION="1.36.4" +ARG OPENTELEMETRY_VERSION="1.2.0" +ARG BOOST_VERSION="1.75.0" +ARG BOOST_FILENAME="boost_1_75_0" +ARG APR_VERSION="1.7.0" +ARG EXPAT_VERSION="2.3.0" +ARG EXPAT_RVERSION="R_2_3_0" +ARG APRUTIL_VERSION="1.6.1" +ARG AUTOCONF_VERSION="2.68" +ARG LIBTOOL_VERSION="2.4.6" +ARG LOG4CXX_VERSION="0.11.0" +ARG GTEST_VERSION="1.10.0" +ARG AUTOMAKE_VERSION="1.16.3" +ARG PCRE_VERSION="8.44" +ARG NGINX_VERSION="1.18.0" + + +# create default non-root user +RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser + +RUN chmod -R 777 /opt + +RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo + +# install required packages +RUN yum update -y \ + && yum install -y \ + yum install wget -y \ + yum install -y zlib-devel \ + yum install -y openssl-devel \ + yum install java-1.8.0-openjdk -y \ + yum install pcre-devel -y \ + yum install xz -y \ + yum install httpd -y \ + && yum clean all + +# install lcov package +RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ + && yum install ./epel-release-latest-*.noarch.rpm -y \ + && yum install lcov -y \ + && yum clean all + +# install devtoolset toolchain +RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo \ + && curl https://www.getpagespeed.com/files/centos6-epel-eol.repo --output /etc/yum.repos.d/epel.repo \ + && yum -y install centos-release-scl \ + && curl https://www.getpagespeed.com/files/centos6-scl-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl.repo \ + && curl https://www.getpagespeed.com/files/centos6-scl-rh-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo \ + && yum install yum-utils -y \ + && yum-config-manager --enable rhel-server-rhscl-7-rpms -y \ + && yum install devtoolset-7 -y \ + && yum clean all +ENV PATH="/opt/rh/devtoolset-7/root/usr/bin:${PATH}" + +# install python +RUN wget http://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \ + && unxz Python-${PYTHON_VERSION}.tar.xz \ + && tar -xf Python-${PYTHON_VERSION}.tar \ + && cd Python-${PYTHON_VERSION} && ./configure --prefix=/usr/local && make && make install \ + && cd .. \ + && rm -rf Python-${PYTHON_VERSION}.tar.xz && rm -rf Python-${PYTHON_VERSION}.tar + +# install gosu for easy step-down from root (from https://github.com/tianon/gosu/blob/master/INSTALL.md#from-centos) +ENV GOSU_VERSION=1.10 + +RUN curl -o /usr/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" \ + && chmod +x /usr/bin/gosu \ + # Verify that the binary works + && gosu nobody true + +# install git required for grpc +RUN yum install git -y \ + && yum clean all + +# install cmake +RUN wget https://cmake.org/files/v${CMAKE_VERSION}/cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ + && tar -xvf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ + && cd cmake-${CMAKE_0VERSION}-linux-x86_64 \ + && cp -rf * /usr/local/ \ + && cd .. && rm -rf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz + +# install grpc. If planning to upgrade, make sure sed command works +RUN git clone https://github.com/grpc/grpc \ + && cd grpc \ + && git checkout tags/v${GRPC_VERSION} -b v${GRPC_VERSION} \ + && git submodule update --init \ + && sed -i "s/target_link_libraries(bssl ssl crypto)/target_link_libraries(bssl ssl crypto rt)/g" third_party/boringssl-with-bazel/CMakeLists.txt \ + && mkdir -p cmake/build \ + && cd cmake/build \ + && cmake ../.. -DgRPC_INSTALL=ON -DCMAKE_BUILD_TYPE=Release -DgRPC_ABSL_PROVIDER=module -DgRPC_CARES_PROVIDER=module -DgRPC_PROTOBUF_PROVIDER=module -DgRPC_RE2_PROVIDER=module -DgRPC_SSL_PROVIDER=module -DgRPC_ZLIB_PROVIDER=module \ + && make \ + && make install \ + && cd ../../.. + +# Create dependencies folder to store all dependencies. +RUN mkdir -p dependencies + +# install boost version +RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/${BOOST_FILENAME}_rc1.tar.gz \ + && tar -xvf ${BOOST_FILENAME}_rc1.tar.gz \ + && cd ${BOOST_FILENAME} \ + && ./bootstrap.sh --with-libraries=filesystem,system --prefix=/dependencies/boost/${BOOST_VERSION}/ \ + && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC" cflags="-fvisibility=hidden -fPIC" \ + && cd .. && rm -rf ${BOOST_FILENAME} && rm ${BOOST_FILENAME}_rc1.tar.gz + +#install Apr +RUN mkdir -p dependencies/apr/${APR_VERSION} \ + && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apr-${APR_VERSION}.tar.gz \ + && cd apr-${APR_VERSION} \ + && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf apr-${APR_VERSION} && rm -rf apr-${APR_VERSION}.tar.gz + +# install libexpat +RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ + && wget https://github.com/libexpat/libexpat/releases/download/${EXPAT_RVERSION}/expat-${EXPAT_VERSION}.tar.gz --no-check-certificate \ + && tar -xf expat-${EXPAT_VERSION}.tar.gz \ + && cd expat-${EXPAT_VERSION} \ + && ./configure --prefix=/dependencies/expat/${EXPAT_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf expat-${EXPAT_VERSION} && rm -rf expat-${EXPAT_VERSION}.tar.gz + +# install Apr-util +RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ + && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ + && cd apr-util-${APRUTIL_VERSION} \ + && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION} --with-expat=/dependencies/expat/${EXPAT_VERSION} && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf apr-util-${APRUTIL_VERSION} && rm -rf apr-util-${APRUTIL_VERSION}.tar.gz + +# install m4 +RUN yum install m4 -y + +# install autoconf +RUN wget --no-check-certificate https://ftp.gnu.org/gnu/autoconf/autoconf-${AUTOCONF_VERSION}.tar.gz \ + && tar xzf autoconf-${AUTOCONF_VERSION}.tar.gz \ + && cd autoconf-${AUTOCONF_VERSION} \ + && ./configure --prefix=/usr/ && make -j && make install && autoconf -V \ + && cd .. && rm -rf autoconf-${AUTOCONF_VERSION}.tar.gz + +# install automake +RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-${AUTOMAKE_VERSION}.tar.gz \ + && tar xzf automake-${AUTOMAKE_VERSION}.tar.gz \ + && cd automake-${AUTOMAKE_VERSION} \ + && ./configure --prefix=/usr --libdir=/usr/lib64 \ + && make -j && make install \ + && automake --version \ + && 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 \ + && 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 + +#install log4cxx +RUN mkdir -p dependencies/apache-log4cxx/-${LOG4CXX_VERSION} \ + && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ + && cd apache-log4cxx-${LOG4CXX_VERSION} \ + && ./configure --prefix=/dependencies/apache-log4cxx/${LOG4CXX_VERSION}/ --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION}/ --with-apr-util=/dependencies/apr-util/${APRUTIL_VERSION}/ && echo $? \ + && make -j 6 ; echo 0 \ + && automake --add-missing \ + && make install \ + && cd .. && rm -rf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz && rm -rf apache-log4cxx-${LOG4CXX_VERSION} + +# install opentelemetry +RUN mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ + && mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include \ + && git clone https://github.com/open-telemetry/opentelemetry-cpp \ + && cd opentelemetry-cpp/ \ + && git checkout tags/v${OPENTELEMETRY_VERSION} -b v${OPENTELEMETRY_VERSION} \ + && git submodule update --init --recursive \ + && mkdir build \ + && cd build \ + && cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON -DWITH_OTLP=ON -DCMAKE_INSTALL_PREFIX=/dependencies/opentelemetry/${OPENTELEMETRY_VERSION} \ + && cmake --build . --target all \ + && cd .. \ + && find . -name "*.so" -type f -exec cp {} /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib/ \; \ + && cp build/libopentelemetry_proto.a /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ + && cp -r api/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ + && for dir in exporters/*; do if [ -d "$dir" ]; then cp -rf "$dir/include" /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/; fi; done \ + && cp -r sdk/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ + && cp -r build/generated/third_party/opentelemetry-proto/opentelemetry/proto/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include/opentelemetry/ \ + && cd .. && rm -rf opentelemetry-cpp + +# install googletest +RUN mkdir -p dependencies/googletest/${GTEST_VERSION}/ \ + && wget https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.tar.gz --no-check-certificate \ + && tar -xf release-${GTEST_VERSION}.tar.gz \ + && cd googletest-release-${GTEST_VERSION}/ \ + && mkdir build && cd build \ + && cmake .. -DCMAKE_INSTALL_PREFIX=/dependencies/googletest/${GTEST_VERSION}/ \ + && make \ + && make install \ + && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ + +# install pcre +RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ + && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ + && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ + && cd pcre-${PCRE_VERSION} \ + && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ + && make && make install \ + && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} + +#Installing Apache and apr source code +RUN mkdir build-dependencies \ + && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz \ + && tar -xf apr-${APR_VERSION}.tar.gz \ + && mv -f apr-${APR_VERSION} build-dependencies \ + && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz \ + && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ + && mv -f apr-util-${APRUTIL_VERSION} build-dependencies \ + && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.2.31.tar.gz \ + && tar -xf httpd-2.2.31.tar.gz \ + && mv -f httpd-2.2.31 build-dependencies \ + && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.4.23.tar.gz \ + && tar -xf httpd-2.4.23.tar.gz \ + && mv -f httpd-2.4.23 build-dependencies + +# install nginx +RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ + && rm -rf nginx-${NGINX_VERSION}.tar.gz + +# Build Webserver Module +COPY . /otel-webserver-module + +RUN cp -r /dependencies /otel-webserver-module/ \ + && cp -r /build-dependencies /otel-webserver-module/ \ + && cd otel-webserver-module \ + && ./gradlew assembleWebServerModule + +RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ + && echo 'name=nginx repo' >> /etc/yum.repos.d/nginx.repo \ + && echo 'baseurl=https://nginx.org/packages/centos/6/x86_64' >> /etc/yum.repos.d/nginx.repo \ + && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ + && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ + && yum install nginx -y + +RUN cd /otel-webserver-module/build \ + && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ + && mv -f opentelemetry-webserver-sdk /opt/ \ + && cd ../ \ + && cp conf/nginx/opentelemetry_module.conf /opt/ \ + && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ + && cd /opt/opentelemetry-webserver-sdk \ + && ./install.sh \ + && cd / + + + +# Remove unwanted files +RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTOMAKE_VERSION} && rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 \ + && rm -rf libtool-${LIBTOOL_VERSION} && rm -rf Python-${PYTHON_VERSION} \ + && rm -f apr-${APR_VERSION}.tar.gz && rm -f apr-util-${APRUTIL_VERSION}.tar.gz \ + && 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"] diff --git a/instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile new file mode 100644 index 000000000..734cf6d6b --- /dev/null +++ b/instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile @@ -0,0 +1,301 @@ +FROM centos:7 + +ARG BUILD_NUMBER + +LABEL NAME=apm/build-image-webserver-agent-centos6-x64 VERSION=$BUILD_NUMBER + +ENV GOSU_ARCH amd64 +ENV JDK_ARCH x64 + +ARG PYTHON_VERSION="2.7.8" +ARG CMAKE_VERSION="3.20" +ARG CMAKE_0VERSION="3.20.0" +ARG GRPC_VERSION="1.36.4" +ARG OPENTELEMETRY_VERSION="1.2.0" +ARG BOOST_VERSION="1.75.0" +ARG BOOST_FILENAME="boost_1_75_0" +ARG APR_VERSION="1.7.0" +ARG EXPAT_VERSION="2.3.0" +ARG EXPAT_RVERSION="R_2_3_0" +ARG APRUTIL_VERSION="1.6.1" +ARG AUTOCONF_VERSION="2.68" +ARG LIBTOOL_VERSION="2.4.6" +ARG LOG4CXX_VERSION="0.11.0" +ARG GTEST_VERSION="1.10.0" +ARG AUTOMAKE_VERSION="1.16.3" +ARG PERL_VERSION="5.20.2" +ARG PERL_CPANVERSION="5.0" +ARG PCRE_VERSION="8.44" +ARG NGINX_VERSION="1.18.0" + +# create default non-root user +RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser + +RUN chmod -R 777 /opt + +# RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo + +# install required packages +RUN yum update -y \ + && yum install -y \ + yum install wget -y \ + yum install -y zlib-devel \ + yum install -y openssl-devel \ + yum install java-1.8.0-openjdk -y \ + yum install pcre-devel -y \ + yum install xz -y \ + yum install httpd -y \ + && yum clean all + +# install lcov package +RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ + && yum install ./epel-release-latest-*.noarch.rpm -y \ + && yum install lcov -y \ + && yum clean all + +# install devtoolset toolchain +# RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo \ +# && curl https://www.getpagespeed.com/files/centos6-epel-eol.repo --output /etc/yum.repos.d/epel.repo \ + RUN yum -y install centos-release-scl \ +# && curl https://www.getpagespeed.com/files/centos6-scl-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl.repo \ +# && curl https://www.getpagespeed.com/files/centos6-scl-rh-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo \ + && yum install yum-utils -y \ + && yum-config-manager --enable rhel-server-rhscl-7-rpms -y \ + && yum install devtoolset-7 -y \ + && yum clean all +ENV PATH="/opt/rh/devtoolset-7/root/usr/bin:${PATH}" + +# install python 2.7.8 +RUN wget http://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \ + && unxz Python-${PYTHON_VERSION}.tar.xz \ + && tar -xf Python-${PYTHON_VERSION}.tar \ + && cd Python-${PYTHON_VERSION} && ./configure --prefix=/usr/local && make && make install \ + && cd .. \ + && rm -rf Python-${PYTHON_VERSION}.tar.xz && rm -rf Python-${PYTHON_VERSION}.tar + +# install gosu for easy step-down from root (from https://github.com/tianon/gosu/blob/master/INSTALL.md#from-centos) +ENV GOSU_VERSION=1.10 +#RUN gpg --keyserver pgp.mit.edu --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ +# && curl -o /usr/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" \ +# && curl -o /usr/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc" \ +# && gpg --verify /usr/bin/gosu.asc \ +# && rm /usr/bin/gosu.asc \ +# && rm -r /root/.gnupg/ \ +RUN curl -o /usr/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" \ + && chmod +x /usr/bin/gosu \ + # Verify that the binary works + && gosu nobody true + +# install git required for grpc +RUN yum install git -y \ + && yum clean all + +# install cmake 3.20 +RUN wget https://cmake.org/files/v${CMAKE_VERSION}/cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ + && tar -xvf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ + && cd cmake-${CMAKE_0VERSION}-linux-x86_64 \ + && cp -rf * /usr/local/ \ + && cd .. && rm -rf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz + +# install grpc. If planning to upgrade, make sure sed command works +RUN git clone https://github.com/grpc/grpc \ + && cd grpc \ + && git checkout tags/v${GRPC_VERSION} -b v${GRPC_VERSION} \ + && git submodule update --init \ + && sed -i "s/target_link_libraries(bssl ssl crypto)/target_link_libraries(bssl ssl crypto rt)/g" third_party/boringssl-with-bazel/CMakeLists.txt \ + && mkdir -p cmake/build \ + && cd cmake/build \ + && cmake ../.. -DgRPC_INSTALL=ON -DCMAKE_BUILD_TYPE=Release -DgRPC_ABSL_PROVIDER=module -DgRPC_CARES_PROVIDER=module -DgRPC_PROTOBUF_PROVIDER=module -DgRPC_RE2_PROVIDER=module -DgRPC_SSL_PROVIDER=module -DgRPC_ZLIB_PROVIDER=module \ + && make \ + && make install \ + && cd ../../.. + +# Create dependencies folder to store all dependencies. +RUN mkdir -p dependencies + +# install boost version 1.75.0 +RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/${BOOST_FILENAME}_rc1.tar.gz \ + && tar -xvf ${BOOST_FILENAME}_rc1.tar.gz \ + && cd ${BOOST_FILENAME} \ + && ./bootstrap.sh --with-libraries=filesystem,system --prefix=/dependencies/boost/${BOOST_VERSION}/ \ + && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC" cflags="-fvisibility=hidden -fPIC" \ + && cd .. && rm -rf ${BOOST_FILENAME} && rm ${BOOST_FILENAME}_rc1.tar.gz + +#install Apr +RUN mkdir -p dependencies/apr/${APR_VERSION} \ + && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apr-${APR_VERSION}.tar.gz \ + && cd apr-${APR_VERSION} \ + && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf apr-${APR_VERSION} && rm -rf apr-${APR_VERSION}.tar.gz + +# install libexpat +RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ + && wget https://github.com/libexpat/libexpat/releases/download/${EXPAT_RVERSION}/expat-${EXPAT_VERSION}.tar.gz --no-check-certificate \ + && tar -xf expat-${EXPAT_VERSION}.tar.gz \ + && cd expat-${EXPAT_VERSION} \ + && ./configure --prefix=/dependencies/expat/${EXPAT_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf expat-${EXPAT_VERSION} && rm -rf expat-${EXPAT_VERSION}.tar.gz + +# install Apr-util +RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ + && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ + && cd apr-util-${APRUTIL_VERSION} \ + && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION} --with-expat=/dependencies/expat/${EXPAT_VERSION} && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf apr-util-${APRUTIL_VERSION} && rm -rf apr-util-${APRUTIL_VERSION}.tar.gz + +# install m4 +RUN yum install m4 -y \ + && yum install perl-Data-Dumper -y + +# Update perl version +RUN yum install perl-Thread-Queue.noarch -y \ + && wget http://www.cpan.org/src/${PERL_CPANVERSION}/perl-${PERL_VERSION}.tar.gz \ + && tar -xzf perl-${PERL_VERSION}.tar.gz \ + && cd perl-${PERL_VERSION} \ + && ./Configure -des -Dprefix=$HOME/localperl \ + && make \ + && make test; echo 0 \ + && make install +ENV PATH=$HOME/localperl/bin:$PATH + +# install autoconf +RUN wget --no-check-certificate https://ftp.gnu.org/gnu/autoconf/autoconf-${AUTOCONF_VERSION}.tar.gz \ + && tar xzf autoconf-${AUTOCONF_VERSION}.tar.gz \ + && cd autoconf-${AUTOCONF_VERSION} \ + && ./configure --prefix=/usr/ && make -j && make install && autoconf -V \ + && cd .. && rm -rf autoconf-${AUTOCONF_VERSION}.tar.gz + +# install automake +RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-${AUTOMAKE_VERSION}.tar.gz \ + && tar xzf automake-${AUTOMAKE_VERSION}.tar.gz \ + && cd automake-${AUTOMAKE_VERSION} \ + && ./configure --prefix=/usr --libdir=/usr/lib64 \ + && make -j && make install \ + && automake --version \ + && 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 \ + && 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 + +#install log4cxx +RUN mkdir -p dependencies/apache-log4cxx/-${LOG4CXX_VERSION} \ + && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ + && cd apache-log4cxx-${LOG4CXX_VERSION} \ + && ./configure --prefix=/dependencies/apache-log4cxx/${LOG4CXX_VERSION}/ --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION}/ --with-apr-util=/dependencies/apr-util/${APRUTIL_VERSION}/ && echo $? \ + && make -j 6 ; echo 0 \ + && automake --add-missing \ + && make install \ + && cd .. && rm -rf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz && rm -rf apache-log4cxx-${LOG4CXX_VERSION} + +# install opentelemetry +RUN mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ + && mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include \ + && git clone https://github.com/open-telemetry/opentelemetry-cpp \ + && cd opentelemetry-cpp/ \ + && git checkout tags/v${OPENTELEMETRY_VERSION} -b v${OPENTELEMETRY_VERSION} \ + && git submodule update --init --recursive \ + && mkdir build \ + && cd build \ + && cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON -DWITH_OTLP=ON -DCMAKE_INSTALL_PREFIX=/dependencies/opentelemetry/${OPENTELEMETRY_VERSION} \ + && cmake --build . --target all \ + && cd .. \ + && find . -name "*.so" -type f -exec cp {} /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib/ \; \ + && cp build/libopentelemetry_proto.a /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ + && cp -r api/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ + && for dir in exporters/*; do if [ -d "$dir" ]; then cp -rf "$dir/include" /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/; fi; done \ + && cp -r sdk/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ + && cp -r build/generated/third_party/opentelemetry-proto/opentelemetry/proto/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include/opentelemetry/ \ + && cd .. && rm -rf opentelemetry-cpp + +# install googletest +RUN mkdir -p dependencies/googletest/${GTEST_VERSION}/ \ + && wget https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.tar.gz --no-check-certificate \ + && tar -xf release-${GTEST_VERSION}.tar.gz \ + && cd googletest-release-${GTEST_VERSION}/ \ + && mkdir build && cd build \ + && cmake .. -DCMAKE_INSTALL_PREFIX=/dependencies/googletest/${GTEST_VERSION}/ \ + && make \ + && make install \ + && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ + +# install pcre +RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ + && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ + && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ + && cd pcre-${PCRE_VERSION} \ + && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ + && make && make install \ + && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} + +#Installing Apache and apr source code +RUN mkdir build-dependencies \ + && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz \ + && tar -xf apr-${APR_VERSION}.tar.gz \ + && mv -f apr-${APR_VERSION} build-dependencies \ + && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz \ + && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ + && mv -f apr-util-${APRUTIL_VERSION} build-dependencies \ + && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.2.31.tar.gz \ + && tar -xf httpd-2.2.31.tar.gz \ + && mv -f httpd-2.2.31 build-dependencies \ + && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.4.23.tar.gz \ + && tar -xf httpd-2.4.23.tar.gz \ + && mv -f httpd-2.4.23 build-dependencies + +# install nginx +RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ + && rm -rf nginx-${NGINX_VERSION}.tar.gz + +# Build Webserver Module +COPY . /otel-webserver-module + +RUN cp -r /dependencies /otel-webserver-module/ \ + && cp -r /build-dependencies /otel-webserver-module/ \ + && cd otel-webserver-module \ + && ./gradlew assembleWebServerModule + +RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ + && echo 'name=nginx repo' >> /etc/yum.repos.d/nginx.repo \ + && echo 'baseurl=https://nginx.org/packages/centos/7/x86_64' >> /etc/yum.repos.d/nginx.repo \ + && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ + && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ + && yum install nginx-1.18.0 -y + +RUN cd /otel-webserver-module/build \ + && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ + && mv -f opentelemetry-webserver-sdk /opt/ \ + && cd ../ \ + && cp conf/nginx/opentelemetry_module.conf /opt/ \ + && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ + && cd /opt/opentelemetry-webserver-sdk \ + && ./install.sh \ + && cd / + + + +# Remove unwanted files +RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTOMAKE_VERSION} && rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 \ + && rm -rf libtool-${LIBTOOL_VERSION} && rm -rf Python-${PYTHON_VERSION} \ + && rm -f apr-${APR_VERSION}.tar.gz && rm -f apr-util-${APRUTIL_VERSION}.tar.gz \ + && 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"] diff --git a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile index fa672ef8b..1973dde31 100644 --- a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile @@ -37,6 +37,8 @@ ARG EXPAT_RVERSION="R_2_3_0" ARG APRUTIL_VERSION="1.6.1" ARG LOG4CXX_VERSION="0.11.0" ARG GTEST_VERSION="1.10.0" +ARG PCRE_VERSION="8.44" +ARG NGINX_VERSION="1.18.0" # Install GRPC RUN git clone --shallow-submodules --depth 1 --recurse-submodules -b v${GRPC_VERSION} \ @@ -164,6 +166,20 @@ RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/sou && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC" cflags="-fvisibility=hidden -fPIC" \ && cd .. && rm -rf ${BOOST_FILENAME} && rm ${BOOST_FILENAME}.tar.gz +# install pcre +RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ + && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ + && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ + && cd pcre-${PCRE_VERSION} \ + && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ + && make && make install \ + && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} + +# install nginx +RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ + && rm -rf nginx-${NGINX_VERSION}.tar.gz + # Build Webserver Module COPY . /otel-webserver-module diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h new file mode 100644 index 000000000..d279757df --- /dev/null +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -0,0 +1,72 @@ +/* +* Copyright 2021 AppDynamics LLC. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OPENTELEMETRY_NGX_API_H +#define OPENTELEMETRY_NGX_API_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BAGGAGE "baggage" +#define TRACEPARENT "traceparent" +#define TRACESTATE "tracestate" + +const char* httpHeaders[] = {"baggage", "traceparent", "tracestate"}; + +typedef struct{ + char* name; + char* value; +}http_headers; + +/* Structure for the request payload */ +typedef struct { + const char* uri; + const char* protocol; + const char* http_get_param; + const char* http_post_param; + const char* request_method; + http_headers* headers; +}request_payload; + +typedef struct{ + const char* cName; + const char* sNamespace; + const char* sName; + const char* sInstanceId; +}contextInfo; + +struct cNode{ + contextInfo cInfo; + struct cNode* next; +}; + +void initDependency(); +void populatePayload(request_payload* req_payload, void* payload, int count); +APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN); +APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle, int count); +APPD_SDK_STATUS_CODE startModuleInteraction(const char* req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int* ix); +APPD_SDK_STATUS_CODE stopModuleInteraction(const char* req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg); +APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg); + +#ifdef __cplusplus +} +#endif +#endif /* OPENTELEMETRY_NGX_API_H ends */ diff --git a/instrumentation/otel-webserver-module/src/build.gyp b/instrumentation/otel-webserver-module/src/build.gyp index 6402c2cc2..de085b370 100644 --- a/instrumentation/otel-webserver-module/src/build.gyp +++ b/instrumentation/otel-webserver-module/src/build.gyp @@ -21,6 +21,7 @@ 'core/api/RequestProcessingEngine.cpp', 'core/api/ApiUtils.cpp', 'core/api/SpanNamer.cpp', + 'core/api/opentelemetry_ngx_api.cpp', 'core/AgentLogger.cpp', 'core/AgentCore.cpp', 'core/sdkwrapper/SdkHelperFactory.cpp', diff --git a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp index cb0ff0074..6e2ebeadf 100755 --- a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp @@ -101,7 +101,7 @@ boost::filesystem::path ApiUtils::getSDKInstallPath() #ifdef _WIN32 char path[FILENAME_MAX]; HMODULE hm = NULL; - if (!(hm = GetModuleHandleA("appdynamics_native_sdk"))) + if (!(hm = GetModuleHandleA("opentelemetry_webserver_sdk"))) { int ret = GetLastError(); // Logger not initialized it diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp new file mode 100644 index 000000000..e85a32902 --- /dev/null +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -0,0 +1,112 @@ +/* +* Copyright 2021 AppDynamics LLC. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#include "api/AppdynamicsSdk.h" +#include "api/opentelemetry_ngx_api.h" +#include "api/WSAgent.h" +#include "api/Payload.h" + + +appd::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic + +void populatePayload(request_payload* req_payload, void* load, int count) +{ + appd::core::RequestPayload* payload = (appd::core::RequestPayload*)load; + payload->set_uri(req_payload->uri); + payload->set_request_protocol(req_payload->protocol); + payload->set_http_post_parameter(req_payload->http_post_param); + payload->set_http_get_parameter(req_payload->http_get_param); + payload->set_http_request_method(req_payload->request_method); + + for(int i=0; iset_http_headers(req_payload->headers[i].name, req_payload->headers[i].value); + } +} + +void initDependency() +{ + wsAgent.initDependency(); +} + +APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN) +{ + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + struct cNode *curCN = rootCN; + + while(curCN){ + appd::core::WSContextConfig cfg; + cfg.serviceNamespace = (curCN->cInfo).sNamespace; + cfg.serviceName = (curCN->cInfo).sName; + cfg.serviceInstanceId = (curCN->cInfo).sInstanceId; + wsAgent.addWSContextToCore((curCN->cInfo).cName, &cfg); + curCN = curCN->next; + } + + res = wsAgent.init(env, numberOfRecords); + + return res; +} + +APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle, int count) +{ + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + + std::unique_ptr requestPayload(new appd::core::RequestPayload); + populatePayload(req_payload, requestPayload.get(), count); + res = wsAgent.startRequest(wscontext, requestPayload.get(), reqHandle); + + return res; +} + +APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg) +{ + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + res = wsAgent.endRequest(req_handle_key, errMsg); + + return res; +} + +APPD_SDK_STATUS_CODE startModuleInteraction(const char* req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int *ix) +{ + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + std::unordered_map pHeaders; + std::string module(module_name); + std::string m_stage(stage); + + std::unique_ptr payload(new appd::core::InteractionPayload(module, m_stage, resolveBackends)); + res = wsAgent.startInteraction((APPD_SDK_HANDLE_REQ)req_handle_key, payload.get(), pHeaders); + + if (APPD_ISSUCCESS(res)) + { + if (!pHeaders.empty()) + { + for (auto itr = pHeaders.begin(); itr != pHeaders.end(); itr++) + { + propagationHeaders[*ix].name = itr->first.c_str(); + propagationHeaders[*ix].value = itr->second.c_str(); + ++(*ix); + } + } + } + return res; +} + +APPD_SDK_STATUS_CODE stopModuleInteraction(const char* req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg) +{ + std::unique_ptr payload(new appd::core::EndInteractionPayload(backendName, backendType, err_code, msg)); + APPD_SDK_STATUS_CODE res = wsAgent.endInteraction((APPD_SDK_HANDLE_REQ)req_handle_key, false, payload.get()); + + return res; +} diff --git a/instrumentation/otel-webserver-module/src/nginx/Makefile b/instrumentation/otel-webserver-module/src/nginx/Makefile new file mode 100644 index 000000000..09b25bfed --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/Makefile @@ -0,0 +1,1306 @@ + +CC = cc +CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable +CPP = cc -E +LINK = $(CC) + + +ALL_INCS = -I src/core \ + -I src/event \ + -I src/event/modules \ + -I src/os/unix \ + -I objs \ + -I src/http \ + -I src/http/modules + + +CORE_DEPS = src/core/nginx.h \ + src/core/ngx_config.h \ + src/core/ngx_core.h \ + src/core/ngx_log.h \ + src/core/ngx_palloc.h \ + src/core/ngx_array.h \ + src/core/ngx_list.h \ + src/core/ngx_hash.h \ + src/core/ngx_buf.h \ + src/core/ngx_queue.h \ + src/core/ngx_string.h \ + src/core/ngx_parse.h \ + src/core/ngx_parse_time.h \ + src/core/ngx_inet.h \ + src/core/ngx_file.h \ + src/core/ngx_crc.h \ + src/core/ngx_crc32.h \ + src/core/ngx_murmurhash.h \ + src/core/ngx_md5.h \ + src/core/ngx_sha1.h \ + src/core/ngx_rbtree.h \ + src/core/ngx_radix_tree.h \ + src/core/ngx_rwlock.h \ + src/core/ngx_slab.h \ + src/core/ngx_times.h \ + src/core/ngx_shmtx.h \ + src/core/ngx_connection.h \ + src/core/ngx_cycle.h \ + src/core/ngx_conf_file.h \ + src/core/ngx_module.h \ + src/core/ngx_resolver.h \ + src/core/ngx_open_file_cache.h \ + src/core/ngx_crypt.h \ + src/core/ngx_proxy_protocol.h \ + src/core/ngx_syslog.h \ + src/event/ngx_event.h \ + src/event/ngx_event_timer.h \ + src/event/ngx_event_posted.h \ + src/event/ngx_event_connect.h \ + src/event/ngx_event_pipe.h \ + src/os/unix/ngx_time.h \ + src/os/unix/ngx_errno.h \ + src/os/unix/ngx_alloc.h \ + src/os/unix/ngx_files.h \ + src/os/unix/ngx_channel.h \ + src/os/unix/ngx_shmem.h \ + src/os/unix/ngx_process.h \ + src/os/unix/ngx_setaffinity.h \ + src/os/unix/ngx_setproctitle.h \ + src/os/unix/ngx_atomic.h \ + src/os/unix/ngx_gcc_atomic_x86.h \ + src/os/unix/ngx_thread.h \ + src/os/unix/ngx_socket.h \ + src/os/unix/ngx_os.h \ + src/os/unix/ngx_user.h \ + src/os/unix/ngx_dlopen.h \ + src/os/unix/ngx_process_cycle.h \ + src/os/unix/ngx_linux_config.h \ + src/os/unix/ngx_linux.h \ + src/core/ngx_regex.h \ + objs/ngx_auto_config.h + + +CORE_INCS = -I src/core \ + -I src/event \ + -I src/event/modules \ + -I src/os/unix \ + -I objs + + +HTTP_DEPS = src/http/ngx_http.h \ + src/http/ngx_http_request.h \ + src/http/ngx_http_config.h \ + src/http/ngx_http_core_module.h \ + src/http/ngx_http_cache.h \ + src/http/ngx_http_variables.h \ + src/http/ngx_http_script.h \ + src/http/ngx_http_upstream.h \ + src/http/ngx_http_upstream_round_robin.h \ + src/http/modules/ngx_http_ssi_filter_module.h + + +HTTP_INCS = -I src/http \ + -I src/http/modules + + +ADDON_DEPS = $(CORE_DEPS) $(HTTP_DEPS) + + +build: binary modules manpage + +binary: objs/nginx + +objs/nginx: objs/src/core/nginx.o \ + objs/src/core/ngx_log.o \ + objs/src/core/ngx_palloc.o \ + objs/src/core/ngx_array.o \ + objs/src/core/ngx_list.o \ + objs/src/core/ngx_hash.o \ + objs/src/core/ngx_buf.o \ + objs/src/core/ngx_queue.o \ + objs/src/core/ngx_output_chain.o \ + objs/src/core/ngx_string.o \ + objs/src/core/ngx_parse.o \ + objs/src/core/ngx_parse_time.o \ + objs/src/core/ngx_inet.o \ + objs/src/core/ngx_file.o \ + objs/src/core/ngx_crc32.o \ + objs/src/core/ngx_murmurhash.o \ + objs/src/core/ngx_md5.o \ + objs/src/core/ngx_sha1.o \ + objs/src/core/ngx_rbtree.o \ + objs/src/core/ngx_radix_tree.o \ + objs/src/core/ngx_slab.o \ + objs/src/core/ngx_times.o \ + objs/src/core/ngx_shmtx.o \ + objs/src/core/ngx_connection.o \ + objs/src/core/ngx_cycle.o \ + objs/src/core/ngx_spinlock.o \ + objs/src/core/ngx_rwlock.o \ + objs/src/core/ngx_cpuinfo.o \ + objs/src/core/ngx_conf_file.o \ + objs/src/core/ngx_module.o \ + objs/src/core/ngx_resolver.o \ + objs/src/core/ngx_open_file_cache.o \ + objs/src/core/ngx_crypt.o \ + objs/src/core/ngx_proxy_protocol.o \ + objs/src/core/ngx_syslog.o \ + objs/src/event/ngx_event.o \ + objs/src/event/ngx_event_timer.o \ + objs/src/event/ngx_event_posted.o \ + objs/src/event/ngx_event_accept.o \ + objs/src/event/ngx_event_udp.o \ + objs/src/event/ngx_event_connect.o \ + objs/src/event/ngx_event_pipe.o \ + objs/src/os/unix/ngx_time.o \ + objs/src/os/unix/ngx_errno.o \ + objs/src/os/unix/ngx_alloc.o \ + objs/src/os/unix/ngx_files.o \ + objs/src/os/unix/ngx_socket.o \ + objs/src/os/unix/ngx_recv.o \ + objs/src/os/unix/ngx_readv_chain.o \ + objs/src/os/unix/ngx_udp_recv.o \ + objs/src/os/unix/ngx_send.o \ + objs/src/os/unix/ngx_writev_chain.o \ + objs/src/os/unix/ngx_udp_send.o \ + objs/src/os/unix/ngx_udp_sendmsg_chain.o \ + objs/src/os/unix/ngx_channel.o \ + objs/src/os/unix/ngx_shmem.o \ + objs/src/os/unix/ngx_process.o \ + objs/src/os/unix/ngx_daemon.o \ + objs/src/os/unix/ngx_setaffinity.o \ + objs/src/os/unix/ngx_setproctitle.o \ + objs/src/os/unix/ngx_posix_init.o \ + objs/src/os/unix/ngx_user.o \ + objs/src/os/unix/ngx_dlopen.o \ + objs/src/os/unix/ngx_process_cycle.o \ + objs/src/os/unix/ngx_linux_init.o \ + objs/src/event/modules/ngx_epoll_module.o \ + objs/src/os/unix/ngx_linux_sendfile_chain.o \ + objs/src/core/ngx_regex.o \ + objs/src/http/ngx_http.o \ + objs/src/http/ngx_http_core_module.o \ + objs/src/http/ngx_http_special_response.o \ + objs/src/http/ngx_http_request.o \ + objs/src/http/ngx_http_parse.o \ + objs/src/http/modules/ngx_http_log_module.o \ + objs/src/http/ngx_http_request_body.o \ + objs/src/http/ngx_http_variables.o \ + objs/src/http/ngx_http_script.o \ + objs/src/http/ngx_http_upstream.o \ + objs/src/http/ngx_http_upstream_round_robin.o \ + objs/src/http/ngx_http_file_cache.o \ + objs/src/http/ngx_http_write_filter_module.o \ + objs/src/http/ngx_http_header_filter_module.o \ + objs/src/http/modules/ngx_http_chunked_filter_module.o \ + objs/src/http/modules/ngx_http_range_filter_module.o \ + objs/src/http/modules/ngx_http_gzip_filter_module.o \ + objs/src/http/ngx_http_postpone_filter_module.o \ + objs/src/http/modules/ngx_http_ssi_filter_module.o \ + objs/src/http/modules/ngx_http_charset_filter_module.o \ + objs/src/http/modules/ngx_http_userid_filter_module.o \ + objs/src/http/modules/ngx_http_headers_filter_module.o \ + objs/src/http/ngx_http_copy_filter_module.o \ + objs/src/http/modules/ngx_http_not_modified_filter_module.o \ + objs/src/http/modules/ngx_http_static_module.o \ + objs/src/http/modules/ngx_http_autoindex_module.o \ + objs/src/http/modules/ngx_http_index_module.o \ + objs/src/http/modules/ngx_http_mirror_module.o \ + objs/src/http/modules/ngx_http_try_files_module.o \ + objs/src/http/modules/ngx_http_auth_basic_module.o \ + objs/src/http/modules/ngx_http_access_module.o \ + objs/src/http/modules/ngx_http_limit_conn_module.o \ + objs/src/http/modules/ngx_http_limit_req_module.o \ + objs/src/http/modules/ngx_http_geo_module.o \ + objs/src/http/modules/ngx_http_map_module.o \ + objs/src/http/modules/ngx_http_split_clients_module.o \ + objs/src/http/modules/ngx_http_referer_module.o \ + objs/src/http/modules/ngx_http_rewrite_module.o \ + objs/src/http/modules/ngx_http_proxy_module.o \ + objs/src/http/modules/ngx_http_fastcgi_module.o \ + objs/src/http/modules/ngx_http_uwsgi_module.o \ + objs/src/http/modules/ngx_http_scgi_module.o \ + objs/src/http/modules/ngx_http_memcached_module.o \ + objs/src/http/modules/ngx_http_empty_gif_module.o \ + objs/src/http/modules/ngx_http_browser_module.o \ + objs/src/http/modules/ngx_http_upstream_hash_module.o \ + objs/src/http/modules/ngx_http_upstream_ip_hash_module.o \ + objs/src/http/modules/ngx_http_upstream_least_conn_module.o \ + objs/src/http/modules/ngx_http_upstream_random_module.o \ + objs/src/http/modules/ngx_http_upstream_keepalive_module.o \ + objs/src/http/modules/ngx_http_upstream_zone_module.o \ + objs/ngx_modules.o + + $(LINK) -o objs/nginx \ + objs/src/core/nginx.o \ + objs/src/core/ngx_log.o \ + objs/src/core/ngx_palloc.o \ + objs/src/core/ngx_array.o \ + objs/src/core/ngx_list.o \ + objs/src/core/ngx_hash.o \ + objs/src/core/ngx_buf.o \ + objs/src/core/ngx_queue.o \ + objs/src/core/ngx_output_chain.o \ + objs/src/core/ngx_string.o \ + objs/src/core/ngx_parse.o \ + objs/src/core/ngx_parse_time.o \ + objs/src/core/ngx_inet.o \ + objs/src/core/ngx_file.o \ + objs/src/core/ngx_crc32.o \ + objs/src/core/ngx_murmurhash.o \ + objs/src/core/ngx_md5.o \ + objs/src/core/ngx_sha1.o \ + objs/src/core/ngx_rbtree.o \ + objs/src/core/ngx_radix_tree.o \ + objs/src/core/ngx_slab.o \ + objs/src/core/ngx_times.o \ + objs/src/core/ngx_shmtx.o \ + objs/src/core/ngx_connection.o \ + objs/src/core/ngx_cycle.o \ + objs/src/core/ngx_spinlock.o \ + objs/src/core/ngx_rwlock.o \ + objs/src/core/ngx_cpuinfo.o \ + objs/src/core/ngx_conf_file.o \ + objs/src/core/ngx_module.o \ + objs/src/core/ngx_resolver.o \ + objs/src/core/ngx_open_file_cache.o \ + objs/src/core/ngx_crypt.o \ + objs/src/core/ngx_proxy_protocol.o \ + objs/src/core/ngx_syslog.o \ + objs/src/event/ngx_event.o \ + objs/src/event/ngx_event_timer.o \ + objs/src/event/ngx_event_posted.o \ + objs/src/event/ngx_event_accept.o \ + objs/src/event/ngx_event_udp.o \ + objs/src/event/ngx_event_connect.o \ + objs/src/event/ngx_event_pipe.o \ + objs/src/os/unix/ngx_time.o \ + objs/src/os/unix/ngx_errno.o \ + objs/src/os/unix/ngx_alloc.o \ + objs/src/os/unix/ngx_files.o \ + objs/src/os/unix/ngx_socket.o \ + objs/src/os/unix/ngx_recv.o \ + objs/src/os/unix/ngx_readv_chain.o \ + objs/src/os/unix/ngx_udp_recv.o \ + objs/src/os/unix/ngx_send.o \ + objs/src/os/unix/ngx_writev_chain.o \ + objs/src/os/unix/ngx_udp_send.o \ + objs/src/os/unix/ngx_udp_sendmsg_chain.o \ + objs/src/os/unix/ngx_channel.o \ + objs/src/os/unix/ngx_shmem.o \ + objs/src/os/unix/ngx_process.o \ + objs/src/os/unix/ngx_daemon.o \ + objs/src/os/unix/ngx_setaffinity.o \ + objs/src/os/unix/ngx_setproctitle.o \ + objs/src/os/unix/ngx_posix_init.o \ + objs/src/os/unix/ngx_user.o \ + objs/src/os/unix/ngx_dlopen.o \ + objs/src/os/unix/ngx_process_cycle.o \ + objs/src/os/unix/ngx_linux_init.o \ + objs/src/event/modules/ngx_epoll_module.o \ + objs/src/os/unix/ngx_linux_sendfile_chain.o \ + objs/src/core/ngx_regex.o \ + objs/src/http/ngx_http.o \ + objs/src/http/ngx_http_core_module.o \ + objs/src/http/ngx_http_special_response.o \ + objs/src/http/ngx_http_request.o \ + objs/src/http/ngx_http_parse.o \ + objs/src/http/modules/ngx_http_log_module.o \ + objs/src/http/ngx_http_request_body.o \ + objs/src/http/ngx_http_variables.o \ + objs/src/http/ngx_http_script.o \ + objs/src/http/ngx_http_upstream.o \ + objs/src/http/ngx_http_upstream_round_robin.o \ + objs/src/http/ngx_http_file_cache.o \ + objs/src/http/ngx_http_write_filter_module.o \ + objs/src/http/ngx_http_header_filter_module.o \ + objs/src/http/modules/ngx_http_chunked_filter_module.o \ + objs/src/http/modules/ngx_http_range_filter_module.o \ + objs/src/http/modules/ngx_http_gzip_filter_module.o \ + objs/src/http/ngx_http_postpone_filter_module.o \ + objs/src/http/modules/ngx_http_ssi_filter_module.o \ + objs/src/http/modules/ngx_http_charset_filter_module.o \ + objs/src/http/modules/ngx_http_userid_filter_module.o \ + objs/src/http/modules/ngx_http_headers_filter_module.o \ + objs/src/http/ngx_http_copy_filter_module.o \ + objs/src/http/modules/ngx_http_not_modified_filter_module.o \ + objs/src/http/modules/ngx_http_static_module.o \ + objs/src/http/modules/ngx_http_autoindex_module.o \ + objs/src/http/modules/ngx_http_index_module.o \ + objs/src/http/modules/ngx_http_mirror_module.o \ + objs/src/http/modules/ngx_http_try_files_module.o \ + objs/src/http/modules/ngx_http_auth_basic_module.o \ + objs/src/http/modules/ngx_http_access_module.o \ + objs/src/http/modules/ngx_http_limit_conn_module.o \ + objs/src/http/modules/ngx_http_limit_req_module.o \ + objs/src/http/modules/ngx_http_geo_module.o \ + objs/src/http/modules/ngx_http_map_module.o \ + objs/src/http/modules/ngx_http_split_clients_module.o \ + objs/src/http/modules/ngx_http_referer_module.o \ + objs/src/http/modules/ngx_http_rewrite_module.o \ + objs/src/http/modules/ngx_http_proxy_module.o \ + objs/src/http/modules/ngx_http_fastcgi_module.o \ + objs/src/http/modules/ngx_http_uwsgi_module.o \ + objs/src/http/modules/ngx_http_scgi_module.o \ + objs/src/http/modules/ngx_http_memcached_module.o \ + objs/src/http/modules/ngx_http_empty_gif_module.o \ + objs/src/http/modules/ngx_http_browser_module.o \ + objs/src/http/modules/ngx_http_upstream_hash_module.o \ + objs/src/http/modules/ngx_http_upstream_ip_hash_module.o \ + objs/src/http/modules/ngx_http_upstream_least_conn_module.o \ + objs/src/http/modules/ngx_http_upstream_random_module.o \ + objs/src/http/modules/ngx_http_upstream_keepalive_module.o \ + objs/src/http/modules/ngx_http_upstream_zone_module.o \ + objs/ngx_modules.o \ + -L/root/webserver-agent/build/linux-x64/opentelemetry-webserver-sdk/sdk_lib/lib -lopentelemetry_webserver_sdk -ldl -lrt -lpthread -lcrypt -lpcre -lz \ + -Wl,-E + + + +modules: + +objs/ngx_modules.o: $(CORE_DEPS) \ + objs/ngx_modules.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/ngx_modules.o \ + objs/ngx_modules.c + + +objs/src/core/nginx.o: $(CORE_DEPS) \ + src/core/nginx.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/nginx.o \ + src/core/nginx.c + + +objs/src/core/ngx_log.o: $(CORE_DEPS) \ + src/core/ngx_log.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_log.o \ + src/core/ngx_log.c + + +objs/src/core/ngx_palloc.o: $(CORE_DEPS) \ + src/core/ngx_palloc.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_palloc.o \ + src/core/ngx_palloc.c + + +objs/src/core/ngx_array.o: $(CORE_DEPS) \ + src/core/ngx_array.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_array.o \ + src/core/ngx_array.c + + +objs/src/core/ngx_list.o: $(CORE_DEPS) \ + src/core/ngx_list.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_list.o \ + src/core/ngx_list.c + + +objs/src/core/ngx_hash.o: $(CORE_DEPS) \ + src/core/ngx_hash.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_hash.o \ + src/core/ngx_hash.c + + +objs/src/core/ngx_buf.o: $(CORE_DEPS) \ + src/core/ngx_buf.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_buf.o \ + src/core/ngx_buf.c + + +objs/src/core/ngx_queue.o: $(CORE_DEPS) \ + src/core/ngx_queue.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_queue.o \ + src/core/ngx_queue.c + + +objs/src/core/ngx_output_chain.o: $(CORE_DEPS) \ + src/core/ngx_output_chain.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_output_chain.o \ + src/core/ngx_output_chain.c + + +objs/src/core/ngx_string.o: $(CORE_DEPS) \ + src/core/ngx_string.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_string.o \ + src/core/ngx_string.c + + +objs/src/core/ngx_parse.o: $(CORE_DEPS) \ + src/core/ngx_parse.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_parse.o \ + src/core/ngx_parse.c + + +objs/src/core/ngx_parse_time.o: $(CORE_DEPS) \ + src/core/ngx_parse_time.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_parse_time.o \ + src/core/ngx_parse_time.c + + +objs/src/core/ngx_inet.o: $(CORE_DEPS) \ + src/core/ngx_inet.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_inet.o \ + src/core/ngx_inet.c + + +objs/src/core/ngx_file.o: $(CORE_DEPS) \ + src/core/ngx_file.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_file.o \ + src/core/ngx_file.c + + +objs/src/core/ngx_crc32.o: $(CORE_DEPS) \ + src/core/ngx_crc32.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_crc32.o \ + src/core/ngx_crc32.c + + +objs/src/core/ngx_murmurhash.o: $(CORE_DEPS) \ + src/core/ngx_murmurhash.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_murmurhash.o \ + src/core/ngx_murmurhash.c + + +objs/src/core/ngx_md5.o: $(CORE_DEPS) \ + src/core/ngx_md5.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_md5.o \ + src/core/ngx_md5.c + + +objs/src/core/ngx_sha1.o: $(CORE_DEPS) \ + src/core/ngx_sha1.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_sha1.o \ + src/core/ngx_sha1.c + + +objs/src/core/ngx_rbtree.o: $(CORE_DEPS) \ + src/core/ngx_rbtree.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_rbtree.o \ + src/core/ngx_rbtree.c + + +objs/src/core/ngx_radix_tree.o: $(CORE_DEPS) \ + src/core/ngx_radix_tree.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_radix_tree.o \ + src/core/ngx_radix_tree.c + + +objs/src/core/ngx_slab.o: $(CORE_DEPS) \ + src/core/ngx_slab.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_slab.o \ + src/core/ngx_slab.c + + +objs/src/core/ngx_times.o: $(CORE_DEPS) \ + src/core/ngx_times.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_times.o \ + src/core/ngx_times.c + + +objs/src/core/ngx_shmtx.o: $(CORE_DEPS) \ + src/core/ngx_shmtx.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_shmtx.o \ + src/core/ngx_shmtx.c + + +objs/src/core/ngx_connection.o: $(CORE_DEPS) \ + src/core/ngx_connection.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_connection.o \ + src/core/ngx_connection.c + + +objs/src/core/ngx_cycle.o: $(CORE_DEPS) \ + src/core/ngx_cycle.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_cycle.o \ + src/core/ngx_cycle.c + + +objs/src/core/ngx_spinlock.o: $(CORE_DEPS) \ + src/core/ngx_spinlock.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_spinlock.o \ + src/core/ngx_spinlock.c + + +objs/src/core/ngx_rwlock.o: $(CORE_DEPS) \ + src/core/ngx_rwlock.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_rwlock.o \ + src/core/ngx_rwlock.c + + +objs/src/core/ngx_cpuinfo.o: $(CORE_DEPS) \ + src/core/ngx_cpuinfo.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_cpuinfo.o \ + src/core/ngx_cpuinfo.c + + +objs/src/core/ngx_conf_file.o: $(CORE_DEPS) \ + src/core/ngx_conf_file.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_conf_file.o \ + src/core/ngx_conf_file.c + + +objs/src/core/ngx_module.o: $(CORE_DEPS) \ + src/core/ngx_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_module.o \ + src/core/ngx_module.c + + +objs/src/core/ngx_resolver.o: $(CORE_DEPS) \ + src/core/ngx_resolver.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_resolver.o \ + src/core/ngx_resolver.c + + +objs/src/core/ngx_open_file_cache.o: $(CORE_DEPS) \ + src/core/ngx_open_file_cache.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_open_file_cache.o \ + src/core/ngx_open_file_cache.c + + +objs/src/core/ngx_crypt.o: $(CORE_DEPS) \ + src/core/ngx_crypt.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_crypt.o \ + src/core/ngx_crypt.c + + +objs/src/core/ngx_proxy_protocol.o: $(CORE_DEPS) \ + src/core/ngx_proxy_protocol.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_proxy_protocol.o \ + src/core/ngx_proxy_protocol.c + + +objs/src/core/ngx_syslog.o: $(CORE_DEPS) \ + src/core/ngx_syslog.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_syslog.o \ + src/core/ngx_syslog.c + + +objs/src/event/ngx_event.o: $(CORE_DEPS) \ + src/event/ngx_event.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event.o \ + src/event/ngx_event.c + + +objs/src/event/ngx_event_timer.o: $(CORE_DEPS) \ + src/event/ngx_event_timer.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event_timer.o \ + src/event/ngx_event_timer.c + + +objs/src/event/ngx_event_posted.o: $(CORE_DEPS) \ + src/event/ngx_event_posted.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event_posted.o \ + src/event/ngx_event_posted.c + + +objs/src/event/ngx_event_accept.o: $(CORE_DEPS) \ + src/event/ngx_event_accept.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event_accept.o \ + src/event/ngx_event_accept.c + + +objs/src/event/ngx_event_udp.o: $(CORE_DEPS) \ + src/event/ngx_event_udp.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event_udp.o \ + src/event/ngx_event_udp.c + + +objs/src/event/ngx_event_connect.o: $(CORE_DEPS) \ + src/event/ngx_event_connect.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event_connect.o \ + src/event/ngx_event_connect.c + + +objs/src/event/ngx_event_pipe.o: $(CORE_DEPS) \ + src/event/ngx_event_pipe.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/ngx_event_pipe.o \ + src/event/ngx_event_pipe.c + + +objs/src/os/unix/ngx_time.o: $(CORE_DEPS) \ + src/os/unix/ngx_time.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_time.o \ + src/os/unix/ngx_time.c + + +objs/src/os/unix/ngx_errno.o: $(CORE_DEPS) \ + src/os/unix/ngx_errno.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_errno.o \ + src/os/unix/ngx_errno.c + + +objs/src/os/unix/ngx_alloc.o: $(CORE_DEPS) \ + src/os/unix/ngx_alloc.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_alloc.o \ + src/os/unix/ngx_alloc.c + + +objs/src/os/unix/ngx_files.o: $(CORE_DEPS) \ + src/os/unix/ngx_files.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_files.o \ + src/os/unix/ngx_files.c + + +objs/src/os/unix/ngx_socket.o: $(CORE_DEPS) \ + src/os/unix/ngx_socket.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_socket.o \ + src/os/unix/ngx_socket.c + + +objs/src/os/unix/ngx_recv.o: $(CORE_DEPS) \ + src/os/unix/ngx_recv.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_recv.o \ + src/os/unix/ngx_recv.c + + +objs/src/os/unix/ngx_readv_chain.o: $(CORE_DEPS) \ + src/os/unix/ngx_readv_chain.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_readv_chain.o \ + src/os/unix/ngx_readv_chain.c + + +objs/src/os/unix/ngx_udp_recv.o: $(CORE_DEPS) \ + src/os/unix/ngx_udp_recv.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_udp_recv.o \ + src/os/unix/ngx_udp_recv.c + + +objs/src/os/unix/ngx_send.o: $(CORE_DEPS) \ + src/os/unix/ngx_send.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_send.o \ + src/os/unix/ngx_send.c + + +objs/src/os/unix/ngx_writev_chain.o: $(CORE_DEPS) \ + src/os/unix/ngx_writev_chain.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_writev_chain.o \ + src/os/unix/ngx_writev_chain.c + + +objs/src/os/unix/ngx_udp_send.o: $(CORE_DEPS) \ + src/os/unix/ngx_udp_send.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_udp_send.o \ + src/os/unix/ngx_udp_send.c + + +objs/src/os/unix/ngx_udp_sendmsg_chain.o: $(CORE_DEPS) \ + src/os/unix/ngx_udp_sendmsg_chain.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_udp_sendmsg_chain.o \ + src/os/unix/ngx_udp_sendmsg_chain.c + + +objs/src/os/unix/ngx_channel.o: $(CORE_DEPS) \ + src/os/unix/ngx_channel.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_channel.o \ + src/os/unix/ngx_channel.c + + +objs/src/os/unix/ngx_shmem.o: $(CORE_DEPS) \ + src/os/unix/ngx_shmem.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_shmem.o \ + src/os/unix/ngx_shmem.c + + +objs/src/os/unix/ngx_process.o: $(CORE_DEPS) \ + src/os/unix/ngx_process.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_process.o \ + src/os/unix/ngx_process.c + + +objs/src/os/unix/ngx_daemon.o: $(CORE_DEPS) \ + src/os/unix/ngx_daemon.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_daemon.o \ + src/os/unix/ngx_daemon.c + + +objs/src/os/unix/ngx_setaffinity.o: $(CORE_DEPS) \ + src/os/unix/ngx_setaffinity.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_setaffinity.o \ + src/os/unix/ngx_setaffinity.c + + +objs/src/os/unix/ngx_setproctitle.o: $(CORE_DEPS) \ + src/os/unix/ngx_setproctitle.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_setproctitle.o \ + src/os/unix/ngx_setproctitle.c + + +objs/src/os/unix/ngx_posix_init.o: $(CORE_DEPS) \ + src/os/unix/ngx_posix_init.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_posix_init.o \ + src/os/unix/ngx_posix_init.c + + +objs/src/os/unix/ngx_user.o: $(CORE_DEPS) \ + src/os/unix/ngx_user.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_user.o \ + src/os/unix/ngx_user.c + + +objs/src/os/unix/ngx_dlopen.o: $(CORE_DEPS) \ + src/os/unix/ngx_dlopen.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_dlopen.o \ + src/os/unix/ngx_dlopen.c + + +objs/src/os/unix/ngx_process_cycle.o: $(CORE_DEPS) \ + src/os/unix/ngx_process_cycle.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_process_cycle.o \ + src/os/unix/ngx_process_cycle.c + + +objs/src/os/unix/ngx_linux_init.o: $(CORE_DEPS) \ + src/os/unix/ngx_linux_init.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_linux_init.o \ + src/os/unix/ngx_linux_init.c + + +objs/src/event/modules/ngx_epoll_module.o: $(CORE_DEPS) \ + src/event/modules/ngx_epoll_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/event/modules/ngx_epoll_module.o \ + src/event/modules/ngx_epoll_module.c + + +objs/src/os/unix/ngx_linux_sendfile_chain.o: $(CORE_DEPS) \ + src/os/unix/ngx_linux_sendfile_chain.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/os/unix/ngx_linux_sendfile_chain.o \ + src/os/unix/ngx_linux_sendfile_chain.c + + +objs/src/core/ngx_regex.o: $(CORE_DEPS) \ + src/core/ngx_regex.c + $(CC) -c $(CFLAGS) $(CORE_INCS) \ + -o objs/src/core/ngx_regex.o \ + src/core/ngx_regex.c + + +objs/src/http/ngx_http.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http.o \ + src/http/ngx_http.c + + +objs/src/http/ngx_http_core_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_core_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_core_module.o \ + src/http/ngx_http_core_module.c + + +objs/src/http/ngx_http_special_response.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_special_response.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_special_response.o \ + src/http/ngx_http_special_response.c + + +objs/src/http/ngx_http_request.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_request.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_request.o \ + src/http/ngx_http_request.c + + +objs/src/http/ngx_http_parse.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_parse.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_parse.o \ + src/http/ngx_http_parse.c + + +objs/src/http/modules/ngx_http_log_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_log_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_log_module.o \ + src/http/modules/ngx_http_log_module.c + + +objs/src/http/ngx_http_request_body.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_request_body.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_request_body.o \ + src/http/ngx_http_request_body.c + + +objs/src/http/ngx_http_variables.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_variables.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_variables.o \ + src/http/ngx_http_variables.c + + +objs/src/http/ngx_http_script.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_script.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_script.o \ + src/http/ngx_http_script.c + + +objs/src/http/ngx_http_upstream.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_upstream.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_upstream.o \ + src/http/ngx_http_upstream.c + + +objs/src/http/ngx_http_upstream_round_robin.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_upstream_round_robin.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_upstream_round_robin.o \ + src/http/ngx_http_upstream_round_robin.c + + +objs/src/http/ngx_http_file_cache.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_file_cache.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_file_cache.o \ + src/http/ngx_http_file_cache.c + + +objs/src/http/ngx_http_write_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_write_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_write_filter_module.o \ + src/http/ngx_http_write_filter_module.c + + +objs/src/http/ngx_http_header_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_header_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_header_filter_module.o \ + src/http/ngx_http_header_filter_module.c + + +objs/src/http/modules/ngx_http_chunked_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_chunked_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_chunked_filter_module.o \ + src/http/modules/ngx_http_chunked_filter_module.c + + +objs/src/http/modules/ngx_http_range_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_range_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_range_filter_module.o \ + src/http/modules/ngx_http_range_filter_module.c + + +objs/src/http/modules/ngx_http_gzip_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_gzip_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_gzip_filter_module.o \ + src/http/modules/ngx_http_gzip_filter_module.c + + +objs/src/http/ngx_http_postpone_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_postpone_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_postpone_filter_module.o \ + src/http/ngx_http_postpone_filter_module.c + + +objs/src/http/modules/ngx_http_ssi_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_ssi_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_ssi_filter_module.o \ + src/http/modules/ngx_http_ssi_filter_module.c + + +objs/src/http/modules/ngx_http_charset_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_charset_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_charset_filter_module.o \ + src/http/modules/ngx_http_charset_filter_module.c + + +objs/src/http/modules/ngx_http_userid_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_userid_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_userid_filter_module.o \ + src/http/modules/ngx_http_userid_filter_module.c + + +objs/src/http/modules/ngx_http_headers_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_headers_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_headers_filter_module.o \ + src/http/modules/ngx_http_headers_filter_module.c + + +objs/src/http/ngx_http_copy_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/ngx_http_copy_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/ngx_http_copy_filter_module.o \ + src/http/ngx_http_copy_filter_module.c + + +objs/src/http/modules/ngx_http_not_modified_filter_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_not_modified_filter_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_not_modified_filter_module.o \ + src/http/modules/ngx_http_not_modified_filter_module.c + + +objs/src/http/modules/ngx_http_static_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_static_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_static_module.o \ + src/http/modules/ngx_http_static_module.c + + +objs/src/http/modules/ngx_http_autoindex_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_autoindex_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_autoindex_module.o \ + src/http/modules/ngx_http_autoindex_module.c + + +objs/src/http/modules/ngx_http_index_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_index_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_index_module.o \ + src/http/modules/ngx_http_index_module.c + + +objs/src/http/modules/ngx_http_mirror_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_mirror_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_mirror_module.o \ + src/http/modules/ngx_http_mirror_module.c + + +objs/src/http/modules/ngx_http_try_files_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_try_files_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_try_files_module.o \ + src/http/modules/ngx_http_try_files_module.c + + +objs/src/http/modules/ngx_http_auth_basic_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_auth_basic_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_auth_basic_module.o \ + src/http/modules/ngx_http_auth_basic_module.c + + +objs/src/http/modules/ngx_http_access_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_access_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_access_module.o \ + src/http/modules/ngx_http_access_module.c + + +objs/src/http/modules/ngx_http_limit_conn_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_limit_conn_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_limit_conn_module.o \ + src/http/modules/ngx_http_limit_conn_module.c + + +objs/src/http/modules/ngx_http_limit_req_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_limit_req_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_limit_req_module.o \ + src/http/modules/ngx_http_limit_req_module.c + + +objs/src/http/modules/ngx_http_geo_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_geo_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_geo_module.o \ + src/http/modules/ngx_http_geo_module.c + + +objs/src/http/modules/ngx_http_map_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_map_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_map_module.o \ + src/http/modules/ngx_http_map_module.c + + +objs/src/http/modules/ngx_http_split_clients_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_split_clients_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_split_clients_module.o \ + src/http/modules/ngx_http_split_clients_module.c + + +objs/src/http/modules/ngx_http_referer_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_referer_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_referer_module.o \ + src/http/modules/ngx_http_referer_module.c + + +objs/src/http/modules/ngx_http_rewrite_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_rewrite_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_rewrite_module.o \ + src/http/modules/ngx_http_rewrite_module.c + + +objs/src/http/modules/ngx_http_proxy_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_proxy_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_proxy_module.o \ + src/http/modules/ngx_http_proxy_module.c + + +objs/src/http/modules/ngx_http_fastcgi_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_fastcgi_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_fastcgi_module.o \ + src/http/modules/ngx_http_fastcgi_module.c + + +objs/src/http/modules/ngx_http_uwsgi_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_uwsgi_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_uwsgi_module.o \ + src/http/modules/ngx_http_uwsgi_module.c + + +objs/src/http/modules/ngx_http_scgi_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_scgi_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_scgi_module.o \ + src/http/modules/ngx_http_scgi_module.c + + +objs/src/http/modules/ngx_http_memcached_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_memcached_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_memcached_module.o \ + src/http/modules/ngx_http_memcached_module.c + + +objs/src/http/modules/ngx_http_empty_gif_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_empty_gif_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_empty_gif_module.o \ + src/http/modules/ngx_http_empty_gif_module.c + + +objs/src/http/modules/ngx_http_browser_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_browser_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_browser_module.o \ + src/http/modules/ngx_http_browser_module.c + + +objs/src/http/modules/ngx_http_upstream_hash_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_upstream_hash_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_upstream_hash_module.o \ + src/http/modules/ngx_http_upstream_hash_module.c + + +objs/src/http/modules/ngx_http_upstream_ip_hash_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_upstream_ip_hash_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_upstream_ip_hash_module.o \ + src/http/modules/ngx_http_upstream_ip_hash_module.c + + +objs/src/http/modules/ngx_http_upstream_least_conn_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_upstream_least_conn_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_upstream_least_conn_module.o \ + src/http/modules/ngx_http_upstream_least_conn_module.c + + +objs/src/http/modules/ngx_http_upstream_random_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_upstream_random_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_upstream_random_module.o \ + src/http/modules/ngx_http_upstream_random_module.c + + +objs/src/http/modules/ngx_http_upstream_keepalive_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_upstream_keepalive_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_upstream_keepalive_module.o \ + src/http/modules/ngx_http_upstream_keepalive_module.c + + +objs/src/http/modules/ngx_http_upstream_zone_module.o: $(CORE_DEPS) $(HTTP_DEPS) \ + src/http/modules/ngx_http_upstream_zone_module.c + $(CC) -c $(CFLAGS) $(CORE_INCS) $(HTTP_INCS) \ + -o objs/src/http/modules/ngx_http_upstream_zone_module.o \ + src/http/modules/ngx_http_upstream_zone_module.c + + +modules: objs/ngx_http_opentelemetry_module.so + +objs/ngx_http_opentelemetry_module.so: objs/addon/nginx/ngx_http_opentelemetry_log.o \ + objs/addon/nginx/ngx_http_opentelemetry_module.o \ + objs/ngx_http_opentelemetry_module_modules.o + + $(LINK) -o objs/ngx_http_opentelemetry_module.so \ + objs/addon/nginx/ngx_http_opentelemetry_log.o \ + objs/addon/nginx/ngx_http_opentelemetry_module.o \ + objs/ngx_http_opentelemetry_module_modules.o \ + -L../linux-x64/opentelemetry-webserver-sdk/sdk_lib/lib \ + -lopentelemetry_webserver_sdk \ + -shared + + +objs/ngx_http_opentelemetry_module_modules.o: $(CORE_DEPS) \ + objs/ngx_http_opentelemetry_module_modules.c + $(CC) -c -fPIC $(CFLAGS) $(ALL_INCS) \ + -o objs/ngx_http_opentelemetry_module_modules.o \ + objs/ngx_http_opentelemetry_module_modules.c + + +objs/addon/nginx/ngx_http_opentelemetry_log.o: $(ADDON_DEPS) \ + ../../src/nginx/ngx_http_opentelemetry_log.c + $(CC) -c -fPIC $(CFLAGS) $(ALL_INCS) \ + -o objs/addon/nginx/ngx_http_opentelemetry_log.o \ + ../../src/nginx/ngx_http_opentelemetry_log.c + + +objs/addon/nginx/ngx_http_opentelemetry_module.o: $(ADDON_DEPS) \ + ../../src/nginx/ngx_http_opentelemetry_module.c + $(CC) -c -fPIC $(CFLAGS) $(ALL_INCS) \ + -o objs/addon/nginx/ngx_http_opentelemetry_module.o \ + ../../src/nginx/ngx_http_opentelemetry_module.c + + +manpage: objs/nginx.8 + +objs/nginx.8: man/nginx.8 objs/ngx_auto_config.h + sed -e "s|%%PREFIX%%|/usr/local/nginx|" \ + -e "s|%%PID_PATH%%|/usr/local/nginx/logs/nginx.pid|" \ + -e "s|%%CONF_PATH%%|/usr/local/nginx/conf/nginx.conf|" \ + -e "s|%%ERROR_LOG_PATH%%|/usr/local/nginx/logs/error.log|" \ + < man/nginx.8 > $@ + +install: build + test -d '$(DESTDIR)/usr/local/nginx' || mkdir -p '$(DESTDIR)/usr/local/nginx' + + test -d '$(DESTDIR)/usr/local/nginx/sbin' \ + || mkdir -p '$(DESTDIR)/usr/local/nginx/sbin' + test ! -f '$(DESTDIR)/usr/local/nginx/sbin/nginx' \ + || mv '$(DESTDIR)/usr/local/nginx/sbin/nginx' \ + '$(DESTDIR)/usr/local/nginx/sbin/nginx.old' + cp objs/nginx '$(DESTDIR)/usr/local/nginx/sbin/nginx' + + test -d '$(DESTDIR)/usr/local/nginx/conf' \ + || mkdir -p '$(DESTDIR)/usr/local/nginx/conf' + + cp conf/koi-win '$(DESTDIR)/usr/local/nginx/conf' + cp conf/koi-utf '$(DESTDIR)/usr/local/nginx/conf' + cp conf/win-utf '$(DESTDIR)/usr/local/nginx/conf' + + test -f '$(DESTDIR)/usr/local/nginx/conf/mime.types' \ + || cp conf/mime.types '$(DESTDIR)/usr/local/nginx/conf' + cp conf/mime.types '$(DESTDIR)/usr/local/nginx/conf/mime.types.default' + + test -f '$(DESTDIR)/usr/local/nginx/conf/fastcgi_params' \ + || cp conf/fastcgi_params '$(DESTDIR)/usr/local/nginx/conf' + cp conf/fastcgi_params \ + '$(DESTDIR)/usr/local/nginx/conf/fastcgi_params.default' + + test -f '$(DESTDIR)/usr/local/nginx/conf/fastcgi.conf' \ + || cp conf/fastcgi.conf '$(DESTDIR)/usr/local/nginx/conf' + cp conf/fastcgi.conf '$(DESTDIR)/usr/local/nginx/conf/fastcgi.conf.default' + + test -f '$(DESTDIR)/usr/local/nginx/conf/uwsgi_params' \ + || cp conf/uwsgi_params '$(DESTDIR)/usr/local/nginx/conf' + cp conf/uwsgi_params \ + '$(DESTDIR)/usr/local/nginx/conf/uwsgi_params.default' + + test -f '$(DESTDIR)/usr/local/nginx/conf/scgi_params' \ + || cp conf/scgi_params '$(DESTDIR)/usr/local/nginx/conf' + cp conf/scgi_params \ + '$(DESTDIR)/usr/local/nginx/conf/scgi_params.default' + + test -f '$(DESTDIR)/usr/local/nginx/conf/nginx.conf' \ + || cp conf/nginx.conf '$(DESTDIR)/usr/local/nginx/conf/nginx.conf' + cp conf/nginx.conf '$(DESTDIR)/usr/local/nginx/conf/nginx.conf.default' + + test -d '$(DESTDIR)/usr/local/nginx/logs' \ + || mkdir -p '$(DESTDIR)/usr/local/nginx/logs' + + test -d '$(DESTDIR)/usr/local/nginx/logs' \ + || mkdir -p '$(DESTDIR)/usr/local/nginx/logs' + + test -d '$(DESTDIR)/usr/local/nginx/html' \ + || cp -R html '$(DESTDIR)/usr/local/nginx' + + test -d '$(DESTDIR)/usr/local/nginx/logs' \ + || mkdir -p '$(DESTDIR)/usr/local/nginx/logs' + + test -d '$(DESTDIR)/usr/local/nginx/modules' \ + || mkdir -p '$(DESTDIR)/usr/local/nginx/modules' + + test ! -f '$(DESTDIR)/usr/local/nginx/modules/ngx_http_opentelemetry_module.so' \ + || mv '$(DESTDIR)/usr/local/nginx/modules/ngx_http_opentelemetry_module.so' \ + '$(DESTDIR)/usr/local/nginx/modules/ngx_http_opentelemetry_module.so.old' + cp objs/ngx_http_opentelemetry_module.so '$(DESTDIR)/usr/local/nginx/modules/ngx_http_opentelemetry_module.so' diff --git a/instrumentation/otel-webserver-module/src/nginx/config b/instrumentation/otel-webserver-module/src/nginx/config new file mode 100644 index 000000000..12f078217 --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/config @@ -0,0 +1,16 @@ +ngx_addon_name=ngx_http_opentelemetry_module + +if test -n "$ngx_module_link"; then + ngx_module_type=HTTP + ngx_module_name=ngx_http_opentelemetry_module + ngx_module_srcs=" \ + $ngx_addon_dir/ngx_http_opentelemetry_log.c \ + $ngx_addon_dir/ngx_http_opentelemetry_module.c" + . auto/module +else + HTTP_MODULES="$HTTP_MODULES ngx_http_opentelemetry_module" + NGX_ADDON_SRCS="$NGX_ADDON_SRCS \ + $ngx_addon_dir/ngx_http_opentelemetry_log.c \ + $ngx_addon_dir/ngx_http_opentelemetry_module.c" +fi +CORE_LIBS="-lopentelemetry_webserver_sdk $CORE_LIBS" diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c new file mode 100644 index 000000000..f861da5cf --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c @@ -0,0 +1,52 @@ +/* +* Copyright 2021 AppDynamics LLC. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#include "ngx_http_opentelemetry_log.h" + +ngx_flag_t logState = false; + +/* This will log the error only when logState(traceAsError) flag is set by user*/ +void ngx_writeTrace(ngx_log_t *log, const char* funcName, const char* format, ...) +{ + char note[8192]; + va_list args; + + va_start(args, format); + vsnprintf(note, sizeof(note), format, args); + va_end(args); + + if (logState && log) + { + ngx_log_error(NGX_LOG_ERR, log, 0, "mod_opentelemetry: %s: %s", funcName, note); + } +} + +/* This will always log the error irrespective of the logState(traceAsError) flag */ +void ngx_writeError(ngx_log_t *log, const char* funcName, const char* format, ...) +{ + char note[8192]; + va_list args; + + va_start(args, format); + vsnprintf(note, sizeof(note), format, args); + va_end(args); + + if (log && funcName) + { + ngx_log_error(NGX_LOG_ERR, log, 0, "mod_opentelemetry: %s: %s", funcName, note); + } +} diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h new file mode 100644 index 000000000..1f2f6aa92 --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h @@ -0,0 +1,29 @@ +/* +* Copyright 2021 AppDynamics LLC. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +#include +#include +#include +#include + +/* + To log Agent logs into NGINX error logs, + based on the flag "NginxModuleTraceAsError" set by user +*/ +ngx_flag_t logState; // read the value of "NginxModuleTraceAsError" flag +void ngx_writeTrace(ngx_log_t *log, const char* funcName, const char* note, ...); +void ngx_writeError(ngx_log_t *log, const char* funcName, const char* note, ...); diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c new file mode 100644 index 000000000..891411acd --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -0,0 +1,1358 @@ +/* +* Copyright 2021 AppDynamics LLC. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include + +#include "ngx_http_opentelemetry_module.h" +#include "ngx_http_opentelemetry_log.h" + +ngx_http_opentelemetry_worker_conf_t *worker_conf; +static contextNode contexts[5]; +static unsigned int c_count = 0; +static unsigned int isGlobalContextSet = 0; + +/* +List of modules being monitored +*/ +otel_ngx_module otel_monitored_modules[] = { + { + "ngx_http_realip_module", + 0, + {NGX_HTTP_POST_READ_PHASE, NGX_HTTP_PREACCESS_PHASE}, + ngx_http_otel_realip_handler, + 0, + 2 + }, + { + "ngx_http_rewrite_module", + 0, + {NGX_HTTP_SERVER_REWRITE_PHASE, NGX_HTTP_REWRITE_PHASE}, + ngx_http_otel_rewrite_handler, + 0, + 2 + }, + { + "ngx_http_limit_conn_module", + 0, + {NGX_HTTP_PREACCESS_PHASE}, + ngx_http_otel_limit_conn_handler, + 0, + 1 + }, + { + "ngx_http_limit_req_module", + 0, + {NGX_HTTP_PREACCESS_PHASE}, + ngx_http_otel_limit_req_handler, + 0, + 1 + }, + { + "ngx_http_auth_request_module", + 0, + {NGX_HTTP_ACCESS_PHASE}, + ngx_http_otel_auth_request_handler, + 0, + 1 + }, + { + "ngx_http_auth_basic_module", + 0, + {NGX_HTTP_ACCESS_PHASE}, + ngx_http_otel_auth_basic_handler, + 0, + 1 + }, + { + "ngx_http_access_module", + 0, + {NGX_HTTP_ACCESS_PHASE}, + ngx_http_otel_access_handler, + 0, + 1 + }, + { + "ngx_http_static_module", + 0, + {NGX_HTTP_CONTENT_PHASE}, + ngx_http_otel_static_handler, + 0, + 1 + }, + { + "ngx_http_gzip_static_module", + 0, + {NGX_HTTP_CONTENT_PHASE}, + ngx_http_otel_gzip_static_handler, + 0, + 1 + }, + { + "ngx_http_dav_module", + 0, + {NGX_HTTP_CONTENT_PHASE}, + ngx_http_otel_dav_handler, + 0, + 1 + }, + { + "ngx_http_autoindex_module", + 0, + {NGX_HTTP_CONTENT_PHASE}, + ngx_http_otel_autoindex_handler, + 0, + 1 + }, + { + "ngx_http_index_module", + 0, + {NGX_HTTP_CONTENT_PHASE}, + ngx_http_otel_index_handler, + 0, + 1 + }, + { + "ngx_http_random_index_module", + 0, + {NGX_HTTP_CONTENT_PHASE}, + ngx_http_otel_random_index_handler, + 0, + 1 + }, + { + "ngx_http_log_module", + 0, + {NGX_HTTP_LOG_PHASE}, + ngx_http_otel_log_handler, + 0, + 1 + } +}; + + +/* + Here's the list of directives specific to our module, and information about where they + may appear and how the command parser should process them. +*/ +static ngx_command_t ngx_http_opentelemetry_commands[] = { + + { ngx_string("NginxModuleEnabled"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleEnabled), + NULL}, + + { ngx_string("NginxModuleOtelSpanExporter"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelSpanExporter), + NULL}, + + { ngx_string("NginxModuleOtelSslEnabled"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelSslEnabled), + NULL}, + + { ngx_string("NginxModuleOtelSslCertificatePath"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelSslCertificatePath), + NULL}, + + { ngx_string("NginxModuleOtelExporterEndpoint"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelExporterEndpoint), + NULL}, + + { ngx_string("NginxModuleOtelSpanProcessor"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelSpanProcessor), + NULL}, + + { ngx_string("NginxModuleOtelSampler"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelSampler), + NULL}, + + { ngx_string("NginxModuleServiceName"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleServiceName), + NULL}, + + { ngx_string("NginxModuleServiceNamespace"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleServiceNamespace), + NULL}, + + { ngx_string("NginxModuleServiceInstanceId"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleServiceInstanceId), + NULL}, + + { ngx_string("NginxModuleOtelMaxQueueSize"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelMaxQueueSize), + NULL}, + + { ngx_string("NginxModuleOtelScheduledDelayMillis"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelScheduledDelayMillis), + NULL}, + + { ngx_string("NginxModuleOtelExportTimeoutMillis"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelExportTimeoutMillis), + NULL}, + + { ngx_string("NginxModuleOtelMaxExportBatchSize"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelMaxExportBatchSize), + NULL}, + + { ngx_string("NginxModuleResolveBackends"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleResolveBackends), + NULL}, + + { ngx_string("NginxModuleTraceAsError"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleTraceAsError), + NULL}, + + { ngx_string("NginxModuleReportAllInstrumentedModules"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleReportAllInstrumentedModules), + NULL}, + + { ngx_string("NginxModuleWebserverContext"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3, + ngx_otel_context_set, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL}, + + { ngx_string("NginxModuleMaskCookie"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleMaskCookie), + NULL}, + + { ngx_string("NginxModuleCookieMatchPattern"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleCookieMatchPattern), + NULL}, + + { ngx_string("NginxModuleMaskSmUser"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleMaskSmUser), + NULL}, + + { ngx_string("NginxModuleDelimiter"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleDelimiter), + NULL}, + + { ngx_string("NginxModuleSegment"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleSegment), + NULL}, + + { ngx_string("NginxModuleMatchfilter"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleMatchfilter), + NULL}, + + { ngx_string("NginxModuleMatchpattern"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleMatchpattern), + NULL}, + + { ngx_string("NginxModuleSegmentType"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleSegmentType), + NULL}, + + { ngx_string("NginxModuleSegmentParameter"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleSegmentParameter), + NULL}, + + ngx_null_command /* command termination */ +}; + +/* The module context. */ +static ngx_http_module_t ngx_http_opentelemetry_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_opentelemetry_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_opentelemetry_create_loc_conf, /* create location configuration */ + ngx_http_opentelemetry_merge_loc_conf /* merge location configuration */ +}; + +/* Module definition. */ +ngx_module_t ngx_http_opentelemetry_module = { + NGX_MODULE_V1, /* module version and a signature */ + &ngx_http_opentelemetry_module_ctx, /* module context */ + ngx_http_opentelemetry_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + ngx_http_opentelemetry_init_worker, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + ngx_http_opentelemetry_exit_worker, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + +/* + Create loc conf to be used by the module + It takes a directive struct (ngx_conf_t) and returns a newly + created module configuration struct + */ +static void* ngx_http_opentelemetry_create_loc_conf(ngx_conf_t *cf) +{ + ngx_http_opentelemetry_loc_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_opentelemetry_loc_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + /* Initialize */ + conf->nginxModuleEnabled = NGX_CONF_UNSET; + conf->nginxModuleResolveBackends = NGX_CONF_UNSET; + conf->nginxModuleOtelScheduledDelayMillis = NGX_CONF_UNSET; + conf->nginxModuleOtelExportTimeoutMillis = NGX_CONF_UNSET; + conf->nginxModuleOtelMaxExportBatchSize = NGX_CONF_UNSET; + conf->nginxModuleReportAllInstrumentedModules = NGX_CONF_UNSET; + conf->nginxModuleMaskCookie = NGX_CONF_UNSET; + conf->nginxModuleMaskSmUser = NGX_CONF_UNSET; + conf->nginxModuleTraceAsError = NGX_CONF_UNSET; + conf->nginxModuleOtelMaxQueueSize = NGX_CONF_UNSET; + conf->nginxModuleOtelSslEnabled = NGX_CONF_UNSET; + + return conf; +} + +static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_opentelemetry_loc_conf_t *prev = parent; + ngx_http_opentelemetry_loc_conf_t *conf = child; + ngx_otel_set_global_context(prev); + + ngx_conf_merge_value(conf->nginxModuleEnabled, prev->nginxModuleEnabled, 1); + ngx_conf_merge_value(conf->nginxModuleReportAllInstrumentedModules, prev->nginxModuleReportAllInstrumentedModules, 0); + ngx_conf_merge_value(conf->nginxModuleResolveBackends, prev->nginxModuleResolveBackends, 1); + ngx_conf_merge_value(conf->nginxModuleTraceAsError, prev->nginxModuleTraceAsError, 0); + ngx_conf_merge_value(conf->nginxModuleMaskCookie, prev->nginxModuleMaskCookie, 0); + ngx_conf_merge_value(conf->nginxModuleMaskSmUser, prev->nginxModuleMaskSmUser, 0); + + ngx_conf_merge_str_value(conf->nginxModuleOtelSpanExporter, prev->nginxModuleOtelSpanExporter, ""); + ngx_conf_merge_str_value(conf->nginxModuleOtelExporterEndpoint, prev->nginxModuleOtelExporterEndpoint, ""); + ngx_conf_merge_value(conf->nginxModuleOtelSslEnabled, prev->nginxModuleOtelSslEnabled, 0); + ngx_conf_merge_str_value(conf->nginxModuleOtelSslCertificatePath, prev->nginxModuleOtelSslCertificatePath, ""); + ngx_conf_merge_str_value(conf->nginxModuleOtelSpanProcessor, prev->nginxModuleOtelSpanProcessor, ""); + ngx_conf_merge_str_value(conf->nginxModuleOtelSampler, prev->nginxModuleOtelSampler, ""); + ngx_conf_merge_str_value(conf->nginxModuleServiceName, prev->nginxModuleServiceName, ""); + ngx_conf_merge_str_value(conf->nginxModuleServiceNamespace, prev->nginxModuleServiceNamespace, ""); + ngx_conf_merge_str_value(conf->nginxModuleServiceInstanceId, prev->nginxModuleServiceInstanceId, ""); + ngx_conf_merge_str_value(conf->nginxModuleCookieMatchPattern, prev->nginxModuleCookieMatchPattern, ""); + ngx_conf_merge_str_value(conf->nginxModuleDelimiter, prev->nginxModuleDelimiter, ""); + ngx_conf_merge_str_value(conf->nginxModuleMatchfilter, prev->nginxModuleMatchfilter, ""); + ngx_conf_merge_str_value(conf->nginxModuleSegment, prev->nginxModuleSegment, ""); + ngx_conf_merge_str_value(conf->nginxModuleMatchpattern, prev->nginxModuleMatchpattern, ""); + + ngx_conf_merge_size_value(conf->nginxModuleOtelMaxQueueSize, prev->nginxModuleOtelMaxQueueSize, 2048); + ngx_conf_merge_msec_value(conf->nginxModuleOtelScheduledDelayMillis, prev->nginxModuleOtelScheduledDelayMillis, 5000); + ngx_conf_merge_msec_value(conf->nginxModuleOtelExportTimeoutMillis, prev->nginxModuleOtelExportTimeoutMillis, 30000); + ngx_conf_merge_size_value(conf->nginxModuleOtelMaxExportBatchSize, prev->nginxModuleOtelMaxExportBatchSize, 512); + + ngx_conf_merge_str_value(conf->nginxModuleSegmentType, prev->nginxModuleSegmentType, "First"); + ngx_conf_merge_str_value(conf->nginxModuleSegmentParameter, prev->nginxModuleSegmentParameter, "2"); + + return NGX_CONF_OK; +} + +/* + Function to initialize the module and used to register all the phases handlers and filters. + ------------------------------------------------------------------------------------------------- + For reference: HTTP Request phases + + Each HTTP request passes through a sequence of phases. In each phase a distinct type of processing + is performed on the request. Module-specific handlers can be registered in most phases, and many + standard nginx modules register their phase handlers as a way to get called at a specific stage of + request processing. Phases are processed successively and the phase handlers are called once the + request reaches the phase. Following is the list of nginx HTTP phases: + + NGX_HTTP_POST_READ_PHASE + NGX_HTTP_SERVER_REWRITE_PHASE + NGX_HTTP_FIND_CONFIG_PHASE + NGX_HTTP_REWRITE_PHASE + NGX_HTTP_POST_REWRITE_PHASE + NGX_HTTP_PREACCESS_PHASE + NGX_HTTP_ACCESS_PHASE + NGX_HTTP_POST_ACCESS_PHASE + NGX_HTTP_PRECONTENT_PHASE + NGX_HTTP_CONTENT_PHASE + NGX_HTTP_LOG_PHASE + + On every phase you can register any number of your handlers. Exceptions are following phases: + + NGX_HTTP_FIND_CONFIG_PHASE + NGX_HTTP_POST_ACCESS_PHASE + NGX_HTTP_POST_REWRITE_PHASE + NGX_HTTP_TRY_FILES_PHASE + ------------------------------------------------------------------------------------------------- + */ +static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) +{ + ngx_http_core_main_conf_t *cmcf; + ngx_uint_t m, cp, ap, pap, srp, prp, rp, lp; + ngx_http_phases ph; + ngx_uint_t phase_index; + ngx_int_t res; + + ngx_writeError(cf->cycle->log, __func__, "Starting Opentelemetry Modlue init"); + + cp = ap = pap = srp = prp = rp = lp = 0; + res = -1; + + cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); + + ngx_writeError(cf->cycle->log, __func__, "Registering handlers for modules in different phases"); + + for (m = 0; cf->cycle->modules[m]; m++) { + if (cf->cycle->modules[m]->type == NGX_HTTP_MODULE) { + res = isOTelMonitored(cf->cycle->modules[m]->name); + if(res != -1){ + otel_monitored_modules[res].ngx_index = m; + phase_index = otel_monitored_modules[res].mod_phase_index; + while(phase_index < otel_monitored_modules[res].phase_count){ + ph = otel_monitored_modules[res].ph[phase_index]; + switch(ph){ + case NGX_HTTP_POST_READ_PHASE: + if(prp < cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers.elts)[prp]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_POST_READ_PHASE].handlers.elts)[prp] = otel_monitored_modules[res].handler; + prp++; + } + break; + + case NGX_HTTP_SERVER_REWRITE_PHASE: + if(srp < cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers.elts)[srp]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers.elts)[srp] = otel_monitored_modules[res].handler; + srp++; + } + break; + + case NGX_HTTP_REWRITE_PHASE: + if(rp < cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.elts)[rp]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers.elts)[rp] = otel_monitored_modules[res].handler; + rp++; + } + break; + + case NGX_HTTP_PREACCESS_PHASE: + if(pap < cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers.elts)[pap]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers.elts)[pap] = otel_monitored_modules[res].handler; + pap++; + } + break; + + case NGX_HTTP_ACCESS_PHASE: + if(ap < cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.elts)[ap]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers.elts)[ap] = otel_monitored_modules[res].handler; + ap++; + } + break; + + case NGX_HTTP_CONTENT_PHASE: + if(cp < cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers.elts)[cp]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers.elts)[cp] = otel_monitored_modules[res].handler; + cp++; + } + break; + + case NGX_HTTP_LOG_PHASE: + if(lp < cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts)[lp]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts)[cp] = otel_monitored_modules[res].handler; + lp++; + } + break; + + case NGX_HTTP_FIND_CONFIG_PHASE: + case NGX_HTTP_POST_REWRITE_PHASE: + case NGX_HTTP_POST_ACCESS_PHASE: + case NGX_HTTP_PRECONTENT_PHASE: + break; + } + phase_index++; + } + } + } + } + + /* Register header_filter */ + // ngx_http_next_header_filter = ngx_http_top_header_filter; + // ngx_http_top_header_filter = ngx_http_opentelemetry_header_filter; + + /* Register body_filter */ + // ngx_http_next_body_filter = ngx_http_top_body_filter; + // ngx_http_top_body_filter = ngx_http_opentelemetry_body_filter; + + ngx_writeError(cf->cycle->log, __func__, "Opentelemetry Modlue init completed !"); + + return NGX_OK; +} + +/* + This function gets called when master process creates worker processes +*/ +static ngx_int_t ngx_http_opentelemetry_init_worker(ngx_cycle_t *cycle) +{ + int p = getpid(); + char * s = (char *)ngx_pcalloc(cycle->pool, 6); + sprintf(s, "%d", p); + ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "mod_opentelemetry: ngx_http_opentelemetry_init_worker: Initializing Nginx Worker for process with PID: %s", s); + + /* Allocate memory for worker configuration */ + worker_conf = ngx_pcalloc(cycle->pool, sizeof(ngx_http_opentelemetry_worker_conf_t)); + if (worker_conf == NULL) { + ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "mod_opentelemetry: ngx_http_opentelemetry_init_worker: Not able to allocate memeory for worker conf"); + return NGX_ERROR; + } + + worker_conf->pid = s; + + return NGX_OK; +} + +/* + This function gets called when a worker process pool is destroyed +*/ +static void ngx_http_opentelemetry_exit_worker(ngx_cycle_t *cycle) +{ + if (worker_conf && worker_conf->isInitialized) + { + ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "mod_opentelemetry: ngx_http_opentelemetry_exit_worker: Exiting Nginx Worker for process with PID: %s**********", worker_conf->pid); + } +} + +static char* ngx_otel_context_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf){ + ngx_str_t* value; + + value = cf->args->elts; + ngx_http_opentelemetry_loc_conf_t * otel_conf_temp=(ngx_http_opentelemetry_loc_conf_t *)conf; + if(cf->args->nelts == 4){ + contexts[c_count].sNamespace = value[1]; + otel_conf_temp->nginxModuleServiceNamespace = value[1]; + contexts[c_count].sName = value[2]; + otel_conf_temp->nginxModuleServiceName = value[2]; + contexts[c_count].sInstanceId = value[3]; + otel_conf_temp->nginxModuleServiceInstanceId = value[3]; + c_count++; + } + + return NGX_CONF_OK; +} +static void ngx_otel_set_global_context(ngx_http_opentelemetry_loc_conf_t * prev) +{ + if(isGlobalContextSet==0){ + if((prev->nginxModuleServiceName).data != NULL && (prev->nginxModuleServiceNamespace).data != NULL && (prev->nginxModuleServiceInstanceId).data != NULL){ + isGlobalContextSet = 1; + contexts[c_count].sNamespace = prev->nginxModuleServiceNamespace; + contexts[c_count].sName = prev->nginxModuleServiceName; + contexts[c_count].sInstanceId = prev->nginxModuleServiceInstanceId; + c_count++; + } + } +} + +/* + Begin a new interaction +*/ +static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const char* module_name){ + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + ngx_http_otel_handles_t* ctx; + + if(!r || r->internal) + { + ngx_writeTrace(r->connection->log, __func__, "It is not a main Request, not starting interaction"); + return res; + } + + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + if(ctx && ctx->otel_req_handle_key) + { + ngx_flag_t resolveBackends = false; + ngx_http_opentelemetry_loc_conf_t* conf; + conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + if(conf) + { + resolveBackends = conf->nginxModuleResolveBackends; + } + APPD_SDK_ENV_RECORD* propagationHeaders = ngx_pcalloc(r->pool, 5 * sizeof(APPD_SDK_ENV_RECORD)); + if (propagationHeaders == NULL) + { + ngx_writeError(r->connection->log, __func__, "Failed to allocate memory for propagation headers"); + return APPD_STATUS(fail); + } + ngx_writeTrace(r->connection->log, __func__, "Starting a new module interaction for: %s", module_name); + int ix = 0; + res = startModuleInteraction(ctx->otel_req_handle_key, module_name, "", resolveBackends, propagationHeaders, &ix); + + if (APPD_ISSUCCESS(res)) + { + otel_payload_decorator(r, propagationHeaders, ix); + ngx_writeTrace(r->connection->log, __func__, "Interaction begin successful"); + } + else + { + ngx_writeError(r->connection->log, __func__, "Error: Interaction begin result code: %d", res); + } + } + return res; +} + +static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* propagationHeaders, int count) +{ + ngx_table_elt_t *h; + ngx_http_header_t *hh; + ngx_http_core_main_conf_t *cmcf; +/* + for(int i=0; iheaders_in.headers); + if(h == NULL){ + return; + } + h->key.len = strlen(propagationHeaders[i].name); + h->key.data = propagationHeaders[i].name; + + ngx_writeTrace(r->connection->log, __func__, "Key : %s", propagationHeaders[i].name); + + h->hash = ngx_hash_key(h->key.data, h->key.len); + + h->value.len = strlen(propagationHeaders[i].value); + h->value.data = propagationHeaders[i].value; + h->lowcase_key = h->key.data; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,h->lowcase_key, h->key.len); + if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { + return; + } + + ngx_writeTrace(r->connection->log, __func__, "Value : %s", propagationHeaders[i].value); + }*/ + + ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + ctx->propagationHeaders = propagationHeaders; + ctx->pheaderCount = count; +} + +/* + Stopping an Interaction +*/ +static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name) +{ + if(!r || r->internal) + { + return; + } + + ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + if(ctx && ctx->otel_req_handle_key) + { + // TODO: Work on backend naming and type + char* backendName = ngx_pcalloc(r->pool, 6); + *backendName = '\0'; + const char* backendType = "HTTP"; + unsigned int errCode=0; + char* code = ngx_pcalloc(r->pool, 6); + + const char* status = "HTTP Status Code: "; + char* msg = ngx_pcalloc(r->pool, strlen(status) + 6); + *msg = '\0'; + if(otel_requestHasErrors(r)) + { + errCode=(unsigned int)otel_getErrorCode(r); + sprintf(code, "%d", errCode); + strcpy(msg, status); + strcat(msg, code); + } + ngx_writeTrace(r->connection->log, __func__, "Stopping the Interaction for: %s", module_name); + APPD_SDK_STATUS_CODE res = stopModuleInteraction(ctx->otel_req_handle_key, backendName, backendType, errCode, msg); + if (APPD_ISFAIL(res)) + { + ngx_writeError(r->connection->log, __func__, "Error: Stop Interaction failed, result code: %d", res); + } + } +} + +static ngx_flag_t otel_requestHasErrors(ngx_http_request_t* r) +{ + return (r->err_status >= LOWEST_HTTP_ERROR_CODE)||(r->headers_out.status >= LOWEST_HTTP_ERROR_CODE); +} +static ngx_uint_t otel_getErrorCode(ngx_http_request_t* r) +{ + if(r->err_status >= LOWEST_HTTP_ERROR_CODE) + return r->err_status; + else if(r->headers_out.status >= LOWEST_HTTP_ERROR_CODE) + return r->headers_out.status; + else return 0; +} + +static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) +{ + // check to see if we have already been initialized + if (worker_conf && worker_conf->isInitialized) + { + ngx_writeTrace(r->connection->log, __func__, "Opentelemetry SDK already initialized for process with PID: %s", worker_conf->pid); + return true; + } + + ngx_http_opentelemetry_loc_conf_t *conf; + conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + if (conf == NULL) + { + ngx_writeError(r->connection->log, __func__, "Module location configuration is NULL"); + return false; + } + + traceConfig(r, conf); + + if (conf->nginxModuleEnabled) + { + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + char *qs = (char *)malloc(6); + char *et = (char *)malloc(6); + char *es = (char *)malloc(6); + char *sd = (char *)malloc(6); + ngx_uint_t i; + + logState = conf->nginxModuleTraceAsError; //Setting Logging Flag + + initDependency(); + + struct cNode *cn = ngx_pcalloc(r->pool, sizeof(struct cNode)); + // (cn->cInfo).cName = computeContextName(r, conf); + struct cNode *rootCN = NULL; + cn = NULL; + + + // Update the apr_pcalloc if we add another parameter to the input array! + APPD_SDK_ENV_RECORD* env_config = ngx_pcalloc(r->pool, 16 * sizeof(APPD_SDK_ENV_RECORD)); + if(env_config == NULL) + { + ngx_writeError(r->connection->log, __func__, "Not Able to allocate memory for the Env Config"); + return false; + } + int ix = 0; + + // Otel Exporter Type + env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_TYPE; + env_config[ix].value = (const char*)((conf->nginxModuleOtelSpanExporter).data); + ++ix; + + // sdk libaray name + env_config[ix].name = APPD_SDK_ENV_OTEL_LIBRARY_NAME; + env_config[ix].value = "Nginx"; + ++ix; + + // Otel Exporter Endpoint + env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT; + env_config[ix].value = (const char*)(conf->nginxModuleOtelExporterEndpoint).data; + ++ix; + + // Otel SSL Enabled + env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_ENABLED; + env_config[ix].value = conf->nginxModuleOtelSslEnabled == 1 ? "1" : "0"; + ++ix; + + // Otel SSL Certificate Path + env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; + env_config[ix].value = (const char*)(conf->nginxModuleOtelSslCertificatePath).data; + ++ix; + + // Otel Processor Type + env_config[ix].name = APPD_SDK_ENV_OTEL_PROCESSOR_TYPE; + env_config[ix].value = (const char*)(conf->nginxModuleOtelSpanProcessor).data; + ++ix; + + // Otel Sampler Type + env_config[ix].name = APPD_SDK_ENV_OTEL_SAMPLER_TYPE; + env_config[ix].value = (const char*)(conf->nginxModuleOtelSampler).data; + ++ix; + + // Service Namespace + env_config[ix].name = APPD_SDK_ENV_SERVICE_NAMESPACE; + env_config[ix].value = (const char*)(conf->nginxModuleServiceNamespace).data; + ++ix; + + // Service Name + env_config[ix].name = APPD_SDK_ENV_SERVICE_NAME; + env_config[ix].value = (const char*)(conf->nginxModuleServiceName).data; + ++ix; + + // Service Instance ID + env_config[ix].name = APPD_SDK_ENV_SERVICE_INSTANCE_ID; + env_config[ix].value = (const char*)(conf->nginxModuleServiceInstanceId).data; + ++ix; + + // Otel Max Queue Size + env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; + sprintf(qs, "%d", conf->nginxModuleOtelMaxQueueSize); + env_config[ix].value = qs; + ++ix; + + // Otel Scheduled Delay + env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; + sprintf(sd, "%d", conf->nginxModuleOtelScheduledDelayMillis); + env_config[ix].value = sd; + ++ix; + + // Otel Max Export Batch Size + env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; + sprintf(es, "%d", conf->nginxModuleOtelMaxExportBatchSize); + env_config[ix].value = es; + ++ix; + + // Otel Export Timeout + env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; + sprintf(et, "%d", conf->nginxModuleOtelExportTimeoutMillis); + env_config[ix].value = et; + ++ix; + + // Segment Type + env_config[ix].name = APPD_SDK_ENV_SEGMENT_TYPE; + env_config[ix].value = (const char*)(conf->nginxModuleSegmentType).data; + ++ix; + + // Segment Parameter + env_config[ix].name = APPD_SDK_ENV_SEGMENT_PARAMETER; + env_config[ix].value = (const char*)(conf->nginxModuleSegmentParameter).data; + ++ix; + + + // !!! + // Remember to update the ngx_pcalloc call size if we add another parameter to the input array! + // !!! + + // Adding the webserver context here + for(int context_i=0; context_ipool, sizeof(struct cNode)); + char* name = ngx_pcalloc(r->pool,(contexts[context_i].sNamespace).len + (contexts[context_i].sName).len + (contexts[context_i].sInstanceId).len + 1); + if(name != NULL){ + strcpy(name, (const char*)(contexts[context_i].sNamespace).data); + strcat(name, (const char*)(contexts[context_i].sName).data); + strcat(name, (const char*)(contexts[context_i].sInstanceId).data); + } + (temp_cn->cInfo).cName = name; + (temp_cn->cInfo).sNamespace = (const char*)(contexts[context_i].sNamespace).data; + (temp_cn->cInfo).sName = (const char*)(contexts[context_i].sName).data; + (temp_cn->cInfo).sInstanceId = (const char*)(contexts[context_i].sInstanceId).data; + if(context_i==0) + { + cn = temp_cn; + rootCN = cn; + } + else + { + cn->next = temp_cn; + cn = cn->next; + } + } + + res = opentelemetry_core_init(env_config, ix, rootCN); + free(qs); + free(sd); + free(et); + free(es); + if (APPD_ISSUCCESS(res)) + { + worker_conf->isInitialized = 1; + ngx_writeTrace(r->connection->log, __func__, "Initializing Agent Core succceeded for process with PID: %s", worker_conf->pid); + return true; + } + else + { + ngx_writeError(r->connection->log, __func__, "Agent Core Init failed, result code is %d", res); + return false; + } + } + else + { + // Agent core is not enabled + ngx_writeError(r->connection->log, __func__, "Agent Core is not enabled"); + return false; + } + return false; +} + +static void stopMonitoringRequest(ngx_http_request_t* r) +{ + if(r->internal) + { + return; + } + + ngx_http_opentelemetry_loc_conf_t *ngx_conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + if(!ngx_conf->nginxModuleEnabled) + { + ngx_writeError(r->connection->log, __func__, "Agent is Disabled"); + } + + ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + if(!ctx || !ctx->otel_req_handle_key) + { + return; + } + APPD_SDK_HANDLE_REQ reqHandle = (APPD_SDK_HANDLE_REQ)ctx->otel_req_handle_key; + ngx_pfree(r->pool, ctx); + + ngx_writeTrace(r->connection->log, __func__, "Stopping the Request Monitoring"); + + APPD_SDK_STATUS_CODE res; + unsigned int errCode=0; + char* msg = NULL; + + if (otel_requestHasErrors(r)) + { + errCode=(unsigned int)otel_getErrorCode(r); + msg = (char*)malloc(6); + sprintf(msg, "%d", errCode); + res = endRequest(reqHandle, msg); + } + else + { + res = endRequest(reqHandle, msg); + } + + if (APPD_ISSUCCESS(res)) + { + ngx_writeError(r->connection->log, __func__, "Request Ends with result code: %d", res); + } + else + { + ngx_writeError(r->connection->log, __func__, "Request End FAILED with code: %d", res); + } + if(msg){ + free(msg); + } + + return; +} + +static void startMonitoringRequest(ngx_http_request_t* r){ + // If a not a the main request(sub-request or internal redirect), calls Realip handler and return + if(r->internal) + { + ngx_writeTrace(r->connection->log, __func__, "Not a Main Request(sub-request or internal redirect)"); + return; + } + else if (!ngx_initialize_opentelemetry(r)) /* check if Appd Agent Core is initialized */ + { + ngx_writeError(r->connection->log, __func__, "Opentelemetry Agent Core did not get initialized"); + return; + } + + ngx_http_otel_handles_t* ctx; + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + if(ctx && ctx->otel_req_handle_key){ + return; + } + + ngx_writeError(r->connection->log, __func__, "Starting Request Monitoring for: %s", r->uri.data); + + // Handle request for static contents (Nginx is used for habdling static contents) + + APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + APPD_SDK_HANDLE_REQ reqHandle = APPD_SDK_NO_HANDLE; + + const char* wscontext = NULL; + + ngx_http_opentelemetry_loc_conf_t *ngx_conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + + if(ngx_conf) + { + wscontext = computeContextName(r, ngx_conf); + } + + if(wscontext) + { + ngx_writeTrace(r->connection->log, __func__, "WebServer Context: %s", wscontext); + } + else + { + ngx_writeTrace(r->connection->log, __func__, "Using Default context "); + } + + // Fill the Request payload information and start the request monitoring + request_payload* req_payload = ngx_pcalloc(r->pool, sizeof(request_payload)); + if(req_payload == NULL) + { + ngx_writeError(r->connection->log, __func__, "Not able to get memory for request payload"); + } + int header_count = 0; + fillRequestPayload(req_payload, r, &header_count); + + res = startRequest(wscontext, req_payload, &reqHandle, header_count); + + if (APPD_ISSUCCESS(res)) + { + if (ctx == NULL) + { + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_otel_handles_t)); + if (ctx == NULL) + { + ngx_writeError(r->connection->log, __func__, "Cannot allocate memory for handles"); + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cannot allocate memory for handles"); + return; + } + // Store the Request Handle on the request object + APPD_SDK_HANDLE_REQ reqHandleValue = ngx_pcalloc(r->pool, sizeof(APPD_SDK_HANDLE_REQ)); + if (reqHandleValue) + { + reqHandleValue = reqHandle; + ctx->otel_req_handle_key = reqHandleValue; + ngx_http_set_ctx(r, ctx, ngx_http_opentelemetry_module); + } + } + ngx_writeTrace(r->connection->log, __func__, "Request Monitoring begins successfully "); + } + else if (res == APPD_STATUS(cfg_channel_uninitialized) || res == APPD_STATUS(bt_detection_disabled)) + { + ngx_writeTrace(r->connection->log, __func__, "Request begin detection disabled, result code: %d", res); + } + else + { + ngx_writeError(r->connection->log, __func__, "Request begin error, result code: %d", res); + } +} + +static ngx_int_t ngx_http_otel_rewrite_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_rewrite_module"); + ngx_int_t rvalue = h[0](r); + otel_stopInteraction(r, "ngx_http_rewrite_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_limit_conn_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_limit_conn_module"); + ngx_int_t rvalue = h[1](r); + otel_stopInteraction(r, "ngx_http_limit_conn_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_limit_req_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_limit_req_module"); + ngx_int_t rvalue = h[2](r); + otel_stopInteraction(r, "ngx_http_limit_req_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_realip_handler(ngx_http_request_t *r){ + + // This will be the first hanndler to be encountered, + // Here, Init and start the Request Processing by creating Trace, spans etc + if(!r->internal) + { + startMonitoringRequest(r); + } + + otel_startInteraction(r, "ngx_http_realip_module"); + ngx_int_t rvalue = h[3](r); + otel_stopInteraction(r, "ngx_http_realip_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_auth_request_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_auth_request_module"); + ngx_int_t rvalue = h[4](r); + otel_stopInteraction(r, "ngx_http_auth_request_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_auth_basic_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_auth_basic_module"); + ngx_int_t rvalue = h[5](r); + otel_stopInteraction(r, "ngx_http_auth_basic_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_access_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_access_module"); + ngx_int_t rvalue = h[6](r); + otel_stopInteraction(r, "ngx_http_access_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_static_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_static_module"); + ngx_int_t rvalue = h[7](r); + otel_stopInteraction(r, "ngx_http_static_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_gzip_static_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_gzip_static_module"); + ngx_int_t rvalue = h[8](r); + otel_stopInteraction(r, "ngx_http_gzip_static_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_dav_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_dav_module"); + ngx_int_t rvalue = h[9](r); + otel_stopInteraction(r, "ngx_http_dav_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_autoindex_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_autoindex_module"); + ngx_int_t rvalue = h[10](r); + otel_stopInteraction(r, "ngx_http_autoindex_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_index_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_index_module"); + ngx_int_t rvalue = h[11](r); + otel_stopInteraction(r, "ngx_http_index_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_random_index_handler(ngx_http_request_t *r){ + otel_startInteraction(r, "ngx_http_random_index_module"); + ngx_int_t rvalue = h[12](r); + otel_stopInteraction(r, "ngx_http_random_index_module"); + + return rvalue; +} + +static ngx_int_t ngx_http_otel_log_handler(ngx_http_request_t *r){ + //This will be last handler to be be encountered before a request ends and response is finally sent back to client + // Here, End the main trace, span created by Webserver Agent and the collected data will be passed to the backend + // It will work as ngx_http_opentelemetry_log_transaction_end + if(!r->internal) + { + stopMonitoringRequest(r); + } + + ngx_int_t rvalue = h[13](r); + + return rvalue; +} + +static ngx_int_t isOTelMonitored(const char* str){ + unsigned int i = 0; + for(i=0; i<14; i++){ + if(strcmp(str, otel_monitored_modules[i].name) == 0) + return i; + } + return -1; +} + +static char* computeContextName(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t* conf){ + char* name = ngx_pcalloc(r->pool,(conf->nginxModuleServiceNamespace).len + (conf->nginxModuleServiceName).len + (conf->nginxModuleServiceInstanceId).len + 1); + + if(name != NULL){ + strcpy(name, (const char*)(conf->nginxModuleServiceNamespace).data); + strcat(name, (const char*)(conf->nginxModuleServiceName).data); + strcat(name, (const char*)(conf->nginxModuleServiceInstanceId).data); + } + return name; +} + +static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t* conf){ + ngx_writeTrace(r->connection->log, __func__, " Config { :" + "(Enabled=\"%d\")" + "(OtelExporterEndpoint=\"%s\")" + "(OtelSslEnabled=\"%d\")" + "(OtelSslCertificatePath=\"%s\")" + "(OtelSpanExporter=\"%s\")" + "(OtelSpanProcessor=\"%s\")" + "(OtelSampler=\"%s\")" + "(ServiceNamespace=\"%s\")" + "(ServiceName=\"%s\")" + "(ServiceInstanceId=\"%s\")" + "(OtelMaxQueueSize=\"%d\")" + "(OtelScheduledDelayMillis=\"%d\")" + "(OtelExportTimeoutMillis=\"%d\")" + "(OtelMaxExportBatchSize=\"%d\")" + "(ResolveBackends=\"%d\")" + "(TraceAsError=\"%d\")" + "(ReportAllInstrumentedModules=\"%d\")" + "(MaskCookie=\"%d\")" + "(MaskSmUser=\"%d\")" + "(SegmentType=\"%s\")" + "(SegmentParameter=\"%s\")" + " }", + conf->nginxModuleEnabled, + (conf->nginxModuleOtelExporterEndpoint).data, + conf->nginxModuleOtelSslEnabled, + (conf->nginxModuleOtelSslCertificatePath).data, + (conf->nginxModuleOtelSpanExporter).data, + (conf->nginxModuleOtelSpanProcessor).data, + (conf->nginxModuleOtelSampler).data, + (conf->nginxModuleServiceNamespace).data, + (conf->nginxModuleServiceName).data, + (conf->nginxModuleServiceInstanceId).data, + conf->nginxModuleOtelMaxQueueSize, + conf->nginxModuleOtelScheduledDelayMillis, + conf->nginxModuleOtelExportTimeoutMillis, + conf->nginxModuleOtelMaxExportBatchSize, + conf->nginxModuleResolveBackends, + conf->nginxModuleTraceAsError, + conf->nginxModuleReportAllInstrumentedModules, + conf->nginxModuleMaskCookie, + conf->nginxModuleMaskSmUser, + (conf->nginxModuleSegmentType).data, + (conf->nginxModuleSegmentParameter).data); +} + +static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r, int* count){ + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_uint_t nelts; + ngx_table_elt_t *h; + + // creating a temporary uri for uri parsing + // (r->uri).data has an extra component "HTTP/1.1 connection" so to obtain the uri it + // has to trimmed. This is done by putting a '/0' after the uri length + // WEBSRV-558 + char *temp_uri = ngx_pcalloc(r->pool, (strlen((r->uri).data))+1); + strcpy(temp_uri,(const char*)(r->uri).data); + temp_uri[(r->uri).len]='\0'; + req_payload->uri = temp_uri; + + req_payload->protocol = (const char*)(r->http_protocol).data; + req_payload->request_method = (const char*)(r->method_name).data; + + req_payload->http_post_param = ngx_pcalloc(r->pool, sizeof(u_char*)); + req_payload->http_get_param = ngx_pcalloc(r->pool, sizeof(u_char*)); + + if(strstr(req_payload->request_method, "GET") !=NULL){ + req_payload->http_post_param = "No param"; + if((r->args).len){ + req_payload->http_get_param = (const char*)(r->args).data; + }else{ + req_payload->http_get_param = "No param"; + } + }else if(strstr(req_payload->request_method, "POST") != NULL){ + req_payload->http_get_param = "No param"; + if((r->args).len){ + req_payload->http_post_param = (const char*)(r->args).data; + }else{ + req_payload->http_post_param = "No param"; + } + } + + part = &r->headers_in.headers.part; + header = (ngx_table_elt_t*)part->elts; + nelts = part->nelts; + + req_payload->headers = ngx_pcalloc(r->pool, 3 * sizeof(http_headers)); + for(int i=0; i<3; i++){ + char* c = httpHeaders[i]; + req_payload->headers[*count].name = c; + for(ngx_uint_t j = 0; jkey.data)==0){ + req_payload->headers[*count].value = (const char*)(h->value).data; + } + } + if(!req_payload->headers[*count].value){ + req_payload->headers[*count].value = "No Param"; + } + ++(*count); + } +} diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h new file mode 100644 index 000000000..30648f902 --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -0,0 +1,151 @@ +/* +* Copyright 2021 AppDynamics LLC. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include "../../include/core/api/AppdynamicsSdk.h" +#include "../../include/core/api/opentelemetry_ngx_api.h" + + +#define LOWEST_HTTP_ERROR_CODE 400 +/* +Function pointer struct for module specific hooks +*/ +typedef ngx_int_t (*mod_handler)(ngx_http_request_t*); +mod_handler h[14]; + +/* + Structure for storing module details for mapping module handlers with their respective module +*/ +typedef struct { + char* name; + ngx_uint_t ngx_index; + ngx_http_phases ph[2]; + mod_handler handler; + ngx_uint_t mod_phase_index; + ngx_uint_t phase_count; +}otel_ngx_module; + +/* + Configuration struct for module +*/ +typedef struct { + ngx_flag_t nginxModuleEnabled; // OPTIONAL: ON or OFF to enable the OpenTelemetry NGINX Agent or not respectively. (defaults to true) + ngx_str_t nginxModuleOtelSpanExporter; + ngx_str_t nginxModuleOtelExporterEndpoint; + ngx_flag_t nginxModuleOtelSslEnabled; + ngx_str_t nginxModuleOtelSslCertificatePath; + ngx_str_t nginxModuleOtelSpanProcessor; + ngx_str_t nginxModuleOtelSampler; + ngx_str_t nginxModuleServiceName; + ngx_str_t nginxModuleServiceNamespace; + ngx_str_t nginxModuleServiceInstanceId; + ngx_uint_t nginxModuleOtelMaxQueueSize; + ngx_uint_t nginxModuleOtelScheduledDelayMillis; + ngx_uint_t nginxModuleOtelExportTimeoutMillis; + ngx_uint_t nginxModuleOtelMaxExportBatchSize; + ngx_flag_t nginxModuleReportAllInstrumentedModules; + ngx_flag_t nginxModuleResolveBackends; + ngx_flag_t nginxModuleTraceAsError; + ngx_flag_t nginxModuleMaskCookie; + ngx_flag_t nginxModuleMaskSmUser; + ngx_str_t nginxModuleCookieMatchPattern; + ngx_str_t nginxModuleDelimiter; + ngx_str_t nginxModuleSegment; + ngx_str_t nginxModuleMatchfilter; + ngx_str_t nginxModuleMatchpattern; + ngx_str_t nginxModuleSegmentType; + ngx_str_t nginxModuleSegmentParameter; +} ngx_http_opentelemetry_loc_conf_t; + +/* + Configuration structure for storing information throughout the worker process life-time +*/ +typedef struct { + ngx_flag_t isInitialized; + char* pid; +} ngx_http_opentelemetry_worker_conf_t; + +typedef struct{ + const char* key; + const char* value; +}NGX_HTTP_OTEL_RECORDS; + +typedef struct { + const char* otel_req_handle_key; + APPD_SDK_ENV_RECORD* propagationHeaders; + int pheaderCount; +}ngx_http_otel_handles_t; + +typedef struct{ + ngx_str_t sNamespace; + ngx_str_t sName; + ngx_str_t sInstanceId; +}contextNode; + +// static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +// static ngx_http_output_body_filter_pt ngx_http_next_body_filter; + +/* Function prototypes */ +static void *ngx_http_opentelemetry_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf); +static ngx_int_t ngx_http_opentelemetry_init_worker(ngx_cycle_t *cycle); +static void ngx_http_opentelemetry_exit_worker(ngx_cycle_t *cycle); +static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r); +static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r, int* count); +static void startMonitoringRequest(ngx_http_request_t* r); +static void stopMonitoringRequest(ngx_http_request_t* r); +static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const char* module_name); +static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name); +static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* propagationHeaders, int count); +static ngx_flag_t otel_requestHasErrors(ngx_http_request_t* r); +static ngx_uint_t otel_getErrorCode(ngx_http_request_t* r); +static char* ngx_otel_context_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static void ngx_otel_set_global_context(ngx_http_opentelemetry_loc_conf_t * prev); + +/* + Module specific handler +*/ +static ngx_int_t ngx_http_otel_rewrite_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_limit_conn_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_limit_req_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_realip_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_auth_request_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_auth_basic_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_access_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_static_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_gzip_static_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_dav_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_autoindex_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_index_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_random_index_handler(ngx_http_request_t *r); +static ngx_int_t ngx_http_otel_log_handler(ngx_http_request_t *r); + +/* + Utility fuction to check if the given module is monitored by Appd Agent +*/ + +static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t* conf); +static ngx_int_t isOTelMonitored(const char* str); +static char* computeContextName(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t* conf); + +/* Filters */ +// static ngx_int_t ngx_http_opentelemetry_header_filter(ngx_http_request_t *r); +// static ngx_int_t ngx_http_opentelemetry_body_filter(ngx_http_request_t *r, ngx_chain_t *in); + diff --git a/instrumentation/otel-webserver-module/test/NginxTesting.sh b/instrumentation/otel-webserver-module/test/NginxTesting.sh new file mode 100755 index 000000000..689ed5a88 --- /dev/null +++ b/instrumentation/otel-webserver-module/test/NginxTesting.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +# Bash script for testing Apache Server + +# Extract the agent +tar -xf ../build/appdynamics-webserver-sdk-x64-linux.tgz -C /opt + +cd /opt/appdynamics-sdk-native + +echo "Installing Apache Agent" +./install.sh + +# Create a appdynamics_agent.conf file +echo "Copying agent config to appdynamics_agent file" +echo ' +AppDynamicsEnabled ON; + +#AppDynamics Otel Exporter details +AppDynamicsOtelSpanExporter OTLP; +AppDynamicsOtelExporterEndpoint example.com:14250; + +AppDynamicsOtelSpanProcessor Batch; +AppDynamicsOtelSampler AlwaysOn; + +AppDynamicsServiceName cart; +AppDynamicsServiceNamespace e-commerce; +AppDynamicsServiceInstanceId 71410b7dec09; + +AppDynamicsOtelMaxQueueSize 1024; +AppDynamicsOtelScheduledDelayMillis 3000; +AppDynamicsOtelExportTimeoutMillis 30000; +AppDynamicsOtelMaxExportBatchSize 1024; + +AppDynamicsResolveBackends ON; + +AppDynamicsTraceAsError ON; + +AppDynamicsReportAllInstrumentedModules OFF; + +#AppDynamicsWebserverContext electronics e-commerce 71410b7jan13; + +AppDynamicsMaskCookie ON; +AppDynamicsCookieMatchPattern PHPSESSID; +AppDynamicsMaskSmUser ON; + +AppDynamicsDelimiter /; +AppDynamicsSegment 2,3; +AppDynamicsMatchfilter CONTAINS; +AppDynamicsMatchpattern myapp; +' > /opt/appdynamics_agent.conf + +# Overwrite nginx.conf file and include appdynamics_agent.conf and ngx_http_appdynamics_module.so in it +echo ' +user nobody; +worker_processes 1; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +load_module /opt/appdynamics-sdk-native/WebServerAgent/Nginx/ngx_http_appdynamics_module.so; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main " $remote_addr - $remote_user [$time_local] $status " ; + + access_log /var/log/nginx/access.log main; + + sendfile on; + keepalive_timeout 65; + + include /opt/appdynamics_agent.conf; + + server { + listen 8080; + } +} +' > /etc/nginx/nginx.conf + +echo "Starting Nginx Server" +pkill nginx +nginx # re-start the server + +# run load +curl -m 5 http://localhost:80 + +echo "Stopping Nginx Server" +pkill nginx # stop the server From 3b08f1c11d0fab862492667f51a91803031f96df Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Wed, 13 Jul 2022 17:02:50 +0530 Subject: [PATCH 04/77] Adding support for nginx Ubuntu (#186) --- .../otel-webserver-module/docker-compose.yml | 16 ++++++++++++++++ .../docker/ubuntu20.04/Dockerfile | 12 +++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/instrumentation/otel-webserver-module/docker-compose.yml b/instrumentation/otel-webserver-module/docker-compose.yml index 7d191c080..2a7b3cfeb 100644 --- a/instrumentation/otel-webserver-module/docker-compose.yml +++ b/instrumentation/otel-webserver-module/docker-compose.yml @@ -71,6 +71,20 @@ services: - "8012:80" depends_on: - otel-collector + nginx_ubuntu: + build: + context: . + dockerfile: docker/ubuntu20.04/Dockerfile + image: nginx_ubuntu + hostname: webserver + container_name: nginx_ubuntu + command: bash -c "export LD_LIBRARY_PATH=/opt/opentelemetry-webserver-sdk/sdk_lib/lib && nginx && tail -f /dev/null" + profiles: + - ubuntu20.04_nginx + ports: + - "8016:80" + depends_on: + - otel-collector # Collector @@ -83,6 +97,7 @@ services: - centos7 - centos_nginx - centos7_nginx + - ubuntu20.04_nginx command: ["--config=/etc/otel-config.yml", "--log-level=DEBUG", "${OTELCOL_ARGS}"] volumes: - ./otel-config.yml:/etc/otel-config.yml @@ -103,6 +118,7 @@ services: - centos7 - centos_nginx - centos7_nginx + - ubuntu20.04_nginx ports: - "9411:9411" - "9410:9410" diff --git a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile index 1973dde31..ab84bfc8f 100644 --- a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile @@ -180,13 +180,15 @@ RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ && rm -rf nginx-${NGINX_VERSION}.tar.gz +RUN apt-get install nginx -y + # Build Webserver Module COPY . /otel-webserver-module RUN cp -r /dependencies /otel-webserver-module/ \ && cp -r /build-dependencies /otel-webserver-module/ \ && cd otel-webserver-module \ - && ./gradlew assembleApacheModule -DtargetSystem=ubuntu + && ./gradlew assembleWebServerModule -DtargetSystem=ubuntu RUN cd /otel-webserver-module/build \ && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ @@ -198,3 +200,11 @@ RUN cd /otel-webserver-module/build \ && cd /opt/opentelemetry-webserver-sdk \ && ./install.sh \ && cd / + +RUN cd /otel-webserver-module/build \ + && cp ../conf/nginx/opentelemetry_module.conf /opt/ \ + && sed -i '5i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '64i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ + && cd /opt/opentelemetry-webserver-sdk \ + && ./install.sh \ + && cd / From 62ed64d8324f27709c67c6bd9bed95bcb112fb1d Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Fri, 15 Jul 2022 12:18:47 +0530 Subject: [PATCH 05/77] Handling span creation/end on Nginx internal redirection and named location. (#174) * Added dependencies of Nginx Build (#158) * updated nginx build directory (#159) * nginx source code (#160) * Add license (#162) * Add license * removing Ubuntu condition * Nomenclature changes from Appdynamics to OpenTelemetry (#163) * Changed appd to otel * Added build command for Nginx Module * Added a missing file to be built * Incorporated Review comments * Nginx docker (#167) * Changing docker compose * centos7 * Updated README for Nginx instrumentation (#168) * Updated README for Nginx instrumentation * Updated README.md * Updated README.md * Set span status according to Semantic Conventions of Http (#164) (#169) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine Co-authored-by: Narasimha * Updated error codes (#170) * Merged from Main branch (#172) * Set span status according to Semantic Conventions of Http (#164) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed UT failure (#171) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed unit test failure Co-authored-by: Narasimha * Handling span creation/end on Nginx internal redirection and named location, related to bug WEBSRV-721 * Fix for try files modules * Added minor changes * Incorporated some review comments Co-authored-by: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Co-authored-by: Narasimha --- .../otel-webserver-module/build.gradle | 5 +- .../include/core/api/opentelemetry_ngx_api.h | 4 +- .../src/core/api/opentelemetry_ngx_api.cpp | 8 +- .../src/nginx/ngx_http_opentelemetry_module.c | 276 +++++++++++++----- .../src/nginx/ngx_http_opentelemetry_module.h | 42 ++- 5 files changed, 245 insertions(+), 90 deletions(-) diff --git a/instrumentation/otel-webserver-module/build.gradle b/instrumentation/otel-webserver-module/build.gradle index 08a72cb5b..ddbcf7c17 100644 --- a/instrumentation/otel-webserver-module/build.gradle +++ b/instrumentation/otel-webserver-module/build.gradle @@ -3,6 +3,7 @@ apply from: 'common.gradle' def coverageEnabled = System.getenv('enableCoverage') def target_system = System.getProperty('targetSystem') ?: 'centos6' +def buildType = System.getProperty('buildType') ?: 'release' project.ext { // To do a 32-bit build, pass "-Dos.arch=x86" @@ -10,10 +11,6 @@ project.ext { modDepDir = "${platBuildDir}/module-dependencies" debug = false - if (!Project.hasProperty('buildType')) { - buildType = 'release' - } - if (buildType != 'release') { buildType = 'debug' debug = true; diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index d279757df..ce2e2b1c5 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -62,8 +62,8 @@ void initDependency(); void populatePayload(request_payload* req_payload, void* payload, int count); APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN); APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle, int count); -APPD_SDK_STATUS_CODE startModuleInteraction(const char* req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int* ix); -APPD_SDK_STATUS_CODE stopModuleInteraction(const char* req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg); +APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int* ix); +APPD_SDK_STATUS_CODE stopModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg); APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg); #ifdef __cplusplus diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index e85a32902..51dfd9393 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -78,7 +78,7 @@ APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* return res; } -APPD_SDK_STATUS_CODE startModuleInteraction(const char* req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int *ix) +APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int *ix) { APPD_SDK_STATUS_CODE res = APPD_SUCCESS; std::unordered_map pHeaders; @@ -86,7 +86,7 @@ APPD_SDK_STATUS_CODE startModuleInteraction(const char* req_handle_key, const ch std::string m_stage(stage); std::unique_ptr payload(new appd::core::InteractionPayload(module, m_stage, resolveBackends)); - res = wsAgent.startInteraction((APPD_SDK_HANDLE_REQ)req_handle_key, payload.get(), pHeaders); + res = wsAgent.startInteraction(req_handle_key, payload.get(), pHeaders); if (APPD_ISSUCCESS(res)) { @@ -103,10 +103,10 @@ APPD_SDK_STATUS_CODE startModuleInteraction(const char* req_handle_key, const ch return res; } -APPD_SDK_STATUS_CODE stopModuleInteraction(const char* req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg) +APPD_SDK_STATUS_CODE stopModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg) { std::unique_ptr payload(new appd::core::EndInteractionPayload(backendName, backendType, err_code, msg)); - APPD_SDK_STATUS_CODE res = wsAgent.endInteraction((APPD_SDK_HANDLE_REQ)req_handle_key, false, payload.get()); + APPD_SDK_STATUS_CODE res = wsAgent.endInteraction(req_handle_key, false, payload.get()); return res; } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 891411acd..10faacfb5 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -141,6 +141,22 @@ otel_ngx_module otel_monitored_modules[] = { ngx_http_otel_log_handler, 0, 1 + }, + { + "ngx_http_try_files_module", + 0, + {NGX_HTTP_PRECONTENT_PHASE}, + ngx_http_otel_try_files_handler, + 0, + 1 + }, + { + "ngx_http_mirror_module", + 0, + {NGX_HTTP_PRECONTENT_PHASE}, + ngx_http_otel_mirror_handler, + 0, + 1 } }; @@ -477,14 +493,15 @@ static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) { ngx_http_core_main_conf_t *cmcf; - ngx_uint_t m, cp, ap, pap, srp, prp, rp, lp; + ngx_uint_t m, cp, ap, pap, srp, prp, rp, lp, pcp; ngx_http_phases ph; ngx_uint_t phase_index; ngx_int_t res; ngx_writeError(cf->cycle->log, __func__, "Starting Opentelemetry Modlue init"); - cp = ap = pap = srp = prp = rp = lp = 0; + cp = ap = pap = srp = prp = rp = lp = pcp = 0; + res = -1; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); @@ -555,12 +572,17 @@ static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) lp++; } break; - + case NGX_HTTP_PRECONTENT_PHASE: + if(pcp < cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers.nelts){ + h[res] = ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers.elts)[pcp]; + ((ngx_http_handler_pt*)cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers.elts)[pcp] = otel_monitored_modules[res].handler; + pcp++; + } + break; case NGX_HTTP_FIND_CONFIG_PHASE: case NGX_HTTP_POST_REWRITE_PHASE: case NGX_HTTP_POST_ACCESS_PHASE: - case NGX_HTTP_PRECONTENT_PHASE: - break; + break; } phase_index++; } @@ -673,9 +695,9 @@ static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c ngx_writeError(r->connection->log, __func__, "Failed to allocate memory for propagation headers"); return APPD_STATUS(fail); } - ngx_writeTrace(r->connection->log, __func__, "Starting a new module interaction for: %s", module_name); + ngx_writeTrace(r->connection->log, __func__, "Starting a new module interaction for: %s", module_name); int ix = 0; - res = startModuleInteraction(ctx->otel_req_handle_key, module_name, "", resolveBackends, propagationHeaders, &ix); + res = startModuleInteraction((void*)ctx->otel_req_handle_key, module_name, "", resolveBackends, propagationHeaders, &ix); if (APPD_ISSUCCESS(res)) { @@ -729,40 +751,56 @@ static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* p /* Stopping an Interaction */ -static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name) +static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name, + void* request_handle_key) { if(!r || r->internal) { return; } + APPD_SDK_HANDLE_REQ otel_req_handle_key = APPD_SDK_NO_HANDLE; ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); - if(ctx && ctx->otel_req_handle_key) + if (r->pool == NULL && request_handle_key != NULL) { - // TODO: Work on backend naming and type - char* backendName = ngx_pcalloc(r->pool, 6); - *backendName = '\0'; - const char* backendType = "HTTP"; - unsigned int errCode=0; - char* code = ngx_pcalloc(r->pool, 6); - - const char* status = "HTTP Status Code: "; - char* msg = ngx_pcalloc(r->pool, strlen(status) + 6); - *msg = '\0'; - if(otel_requestHasErrors(r)) - { - errCode=(unsigned int)otel_getErrorCode(r); - sprintf(code, "%d", errCode); - strcpy(msg, status); - strcat(msg, code); - } - ngx_writeTrace(r->connection->log, __func__, "Stopping the Interaction for: %s", module_name); - APPD_SDK_STATUS_CODE res = stopModuleInteraction(ctx->otel_req_handle_key, backendName, backendType, errCode, msg); - if (APPD_ISFAIL(res)) - { - ngx_writeError(r->connection->log, __func__, "Error: Stop Interaction failed, result code: %d", res); - } + otel_req_handle_key = request_handle_key; + } + else if (ctx && ctx->otel_req_handle_key) + { + otel_req_handle_key = ctx->otel_req_handle_key; } + else + { + return; + } + + // TODO: Work on backend naming and type + char* backendName = (char *)malloc(6 * sizeof(char)); + *backendName = '\0'; + const char* backendType = "HTTP"; + unsigned int errCode=0; + char* code = (char *)malloc(6 * sizeof(char)); + + const char* status = "HTTP Status Code: "; + char* msg = (char *)malloc(strlen(status) + 6 * sizeof(char)); + *msg = '\0'; + if(otel_requestHasErrors(r)) + { + errCode=(unsigned int)otel_getErrorCode(r); + sprintf(code, "%d", errCode); + strcpy(msg, status); + strcat(msg, code); + } + ngx_writeTrace(r->connection->log, __func__, "Stopping the Interaction for: %s", module_name); + APPD_SDK_STATUS_CODE res = stopModuleInteraction(otel_req_handle_key, backendName, backendType, errCode, msg); + if (APPD_ISFAIL(res)) + { + ngx_writeError(r->connection->log, __func__, "Error: Stop Interaction failed, result code: %d", res); + } + + free (backendName); + free (code); + free (msg); } static ngx_flag_t otel_requestHasErrors(ngx_http_request_t* r) @@ -965,26 +1003,34 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) return false; } -static void stopMonitoringRequest(ngx_http_request_t* r) +static void stopMonitoringRequest(ngx_http_request_t* r, + APPD_SDK_HANDLE_REQ request_handle_key) { - if(r->internal) - { - return; - } - ngx_http_opentelemetry_loc_conf_t *ngx_conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); if(!ngx_conf->nginxModuleEnabled) { ngx_writeError(r->connection->log, __func__, "Agent is Disabled"); + return; } + APPD_SDK_HANDLE_REQ otel_req_handle_key = APPD_SDK_NO_HANDLE; ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); - if(!ctx || !ctx->otel_req_handle_key) + if (r->pool == NULL && request_handle_key != NULL) + { + otel_req_handle_key = request_handle_key; + } + else if (ctx && ctx->otel_req_handle_key) + { + otel_req_handle_key = ctx->otel_req_handle_key; + } + else { return; } - APPD_SDK_HANDLE_REQ reqHandle = (APPD_SDK_HANDLE_REQ)ctx->otel_req_handle_key; - ngx_pfree(r->pool, ctx); + + if (r->pool) { + ngx_pfree(r->pool, ctx); + } ngx_writeTrace(r->connection->log, __func__, "Stopping the Request Monitoring"); @@ -997,11 +1043,11 @@ static void stopMonitoringRequest(ngx_http_request_t* r) errCode=(unsigned int)otel_getErrorCode(r); msg = (char*)malloc(6); sprintf(msg, "%d", errCode); - res = endRequest(reqHandle, msg); + res = endRequest(otel_req_handle_key, msg); } else { - res = endRequest(reqHandle, msg); + res = endRequest(otel_req_handle_key, msg); } if (APPD_ISSUCCESS(res)) @@ -1108,24 +1154,24 @@ static void startMonitoringRequest(ngx_http_request_t* r){ static ngx_int_t ngx_http_otel_rewrite_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_rewrite_module"); - ngx_int_t rvalue = h[0](r); - otel_stopInteraction(r, "ngx_http_rewrite_module"); + ngx_int_t rvalue = h[NGX_HTTP_REWRITE_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_rewrite_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_limit_conn_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_limit_conn_module"); - ngx_int_t rvalue = h[1](r); - otel_stopInteraction(r, "ngx_http_limit_conn_module"); + ngx_int_t rvalue = h[NGX_HTTP_LIMIT_CONN_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_limit_conn_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_limit_req_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_limit_req_module"); - ngx_int_t rvalue = h[2](r); - otel_stopInteraction(r, "ngx_http_limit_req_module"); + ngx_int_t rvalue = h[NGX_HTTP_LIMIT_REQ_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_limit_req_module", APPD_SDK_NO_HANDLE); return rvalue; } @@ -1140,80 +1186,163 @@ static ngx_int_t ngx_http_otel_realip_handler(ngx_http_request_t *r){ } otel_startInteraction(r, "ngx_http_realip_module"); - ngx_int_t rvalue = h[3](r); - otel_stopInteraction(r, "ngx_http_realip_module"); + ngx_int_t rvalue = h[NGX_HTTP_REALIP_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_realip_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_auth_request_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_auth_request_module"); - ngx_int_t rvalue = h[4](r); - otel_stopInteraction(r, "ngx_http_auth_request_module"); + ngx_int_t rvalue = h[NGX_HTTP_LIMIT_AUTH_REQ_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_auth_request_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_auth_basic_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_auth_basic_module"); - ngx_int_t rvalue = h[5](r); - otel_stopInteraction(r, "ngx_http_auth_basic_module"); + ngx_int_t rvalue = h[NGX_HTTP_AUTH_BASIC_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_auth_basic_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_access_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_access_module"); - ngx_int_t rvalue = h[6](r); - otel_stopInteraction(r, "ngx_http_access_module"); + ngx_int_t rvalue = h[NGX_HTTP_ACCESS_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_access_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_static_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_static_module"); - ngx_int_t rvalue = h[7](r); - otel_stopInteraction(r, "ngx_http_static_module"); + ngx_int_t rvalue = h[NGX_HTTP_STATIC_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_static_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_gzip_static_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_gzip_static_module"); - ngx_int_t rvalue = h[8](r); - otel_stopInteraction(r, "ngx_http_gzip_static_module"); + ngx_int_t rvalue = h[NGX_HTTP_GZIP_STATIC_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_gzip_static_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_dav_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_dav_module"); - ngx_int_t rvalue = h[9](r); - otel_stopInteraction(r, "ngx_http_dav_module"); + ngx_int_t rvalue = h[NGX_HTTP_DAV_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_dav_module", APPD_SDK_NO_HANDLE); return rvalue; } static ngx_int_t ngx_http_otel_autoindex_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_autoindex_module"); - ngx_int_t rvalue = h[10](r); - otel_stopInteraction(r, "ngx_http_autoindex_module"); + ngx_int_t rvalue = h[NGX_HTTP_AUTO_INDEX_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_autoindex_module", APPD_SDK_NO_HANDLE); return rvalue; } +/* autoindex, index and randomindex handlers get called during + internal redirection. In case of index and randomIndex handlers, + it has been observed that 'ctx' ptr gets cleaned up from request + pool and r->internal gets set to 1. But, we need 'ctx' to stop the + interaction. + Therefore, as a special handling, we store the ctx pointer and reset + before stopping the interaction. We avoid starting/stopping + interaction/request when r->intenal is 1. But in this case, + when we started the interaction r->internal is 0 but when the + actual handler calls completes, it internally transforms r->internal + to 1. Therefore, we need extra handling for r->internal as well. +*/ + static ngx_int_t ngx_http_otel_index_handler(ngx_http_request_t *r){ + bool old_internal = r->internal; + ngx_http_otel_handles_t* old_ctx; + otel_startInteraction(r, "ngx_http_index_module"); - ngx_int_t rvalue = h[11](r); - otel_stopInteraction(r, "ngx_http_index_module"); + old_ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + ngx_int_t rvalue = h[NGX_HTTP_INDEX_MODULE_INDEX](r); + bool new_internal = r->internal; + if (new_internal == true && new_internal != old_internal) { + ngx_http_set_ctx(r, old_ctx, ngx_http_opentelemetry_module); + r->internal = 0; + otel_stopInteraction(r, "ngx_http_index_module", APPD_SDK_NO_HANDLE); + r->internal = 1; + } else { + otel_stopInteraction(r, "ngx_http_index_module", APPD_SDK_NO_HANDLE); + } return rvalue; } static ngx_int_t ngx_http_otel_random_index_handler(ngx_http_request_t *r){ + bool old_internal = r->internal; + ngx_http_otel_handles_t* old_ctx; + + old_ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); otel_startInteraction(r, "ngx_http_random_index_module"); - ngx_int_t rvalue = h[12](r); - otel_stopInteraction(r, "ngx_http_random_index_module"); + ngx_int_t rvalue = h[NGX_HTTP_RANDOM_INDEX_MODULE_INDEX](r); + bool new_internal = r->internal; + if (new_internal == true && new_internal != old_internal) { + ngx_http_set_ctx(r, old_ctx, ngx_http_opentelemetry_module); + r->internal = 0; + otel_stopInteraction(r, "ngx_http_random_index_module", APPD_SDK_NO_HANDLE); + r->internal = 1; + + } else { + otel_stopInteraction(r, "ngx_http_random_index_module", APPD_SDK_NO_HANDLE); + } + + return rvalue; +} + +/* tryfiles handler gets called with try_files tag. In this case + also, internal redirection happens. But on completion of this + handler, request pool gets wiped out and since ctx is created + in request pool, its no longer valid. However, request hanlde + is not created in request pool. Therefore,we save the request + handle and pass it along to stop the interaction. Also, we + stop the request using the same request handle. +*/ + + +static ngx_int_t ngx_http_otel_try_files_handler(ngx_http_request_t *r) { + bool old_internal = r->internal; + ngx_http_otel_handles_t* old_ctx; + + APPD_SDK_HANDLE_REQ request_handle = APPD_SDK_NO_HANDLE; + old_ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + if (old_ctx && old_ctx->otel_req_handle_key) { + request_handle = old_ctx->otel_req_handle_key; + } + + otel_startInteraction(r, "ngx_http_otel_try_files_handler"); + ngx_int_t rvalue = h[NGX_HTTP_TRY_FILES_MODULE_INDEX](r); + bool new_internal = r->internal; + if (new_internal == true && new_internal != old_internal) { + r->internal = 0; + otel_stopInteraction(r, "ngx_http_otel_try_files_handler", request_handle); + r->internal = 1; + } else { + otel_stopInteraction(r, "ngx_http_otel_try_files_handler", APPD_SDK_NO_HANDLE); + } + + if (!r->pool) { + stopMonitoringRequest(r, request_handle); + } + return rvalue; +} + +static ngx_int_t ngx_http_otel_mirror_handler(ngx_http_request_t *r) { + otel_startInteraction(r, "ngx_http_otel_mirror_handler"); + ngx_int_t rvalue = h[NGX_HTTP_MIRROR_MODULE_INDEX](r); + otel_stopInteraction(r, "ngx_http_otel_mirror_handler", APPD_SDK_NO_HANDLE); return rvalue; } @@ -1222,19 +1351,16 @@ static ngx_int_t ngx_http_otel_log_handler(ngx_http_request_t *r){ //This will be last handler to be be encountered before a request ends and response is finally sent back to client // Here, End the main trace, span created by Webserver Agent and the collected data will be passed to the backend // It will work as ngx_http_opentelemetry_log_transaction_end - if(!r->internal) - { - stopMonitoringRequest(r); - } + stopMonitoringRequest(r, APPD_SDK_NO_HANDLE); - ngx_int_t rvalue = h[13](r); + ngx_int_t rvalue = h[NGX_HTTP_LOG_MODULE_INDEX](r); return rvalue; } static ngx_int_t isOTelMonitored(const char* str){ unsigned int i = 0; - for(i=0; i<14; i++){ + for(i=0; i Date: Fri, 15 Jul 2022 12:25:02 +0530 Subject: [PATCH 06/77] Adding support for Propagation Headers (#185) * Adding support for Propagation Headers * Adding Garbage collection --- .../src/core/api/opentelemetry_ngx_api.cpp | 9 +++++++-- .../src/nginx/ngx_http_opentelemetry_module.c | 17 +++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index 51dfd9393..5e4580c1d 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -17,6 +17,7 @@ #include "api/opentelemetry_ngx_api.h" #include "api/WSAgent.h" #include "api/Payload.h" +#include appd::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic @@ -94,8 +95,12 @@ APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, { for (auto itr = pHeaders.begin(); itr != pHeaders.end(); itr++) { - propagationHeaders[*ix].name = itr->first.c_str(); - propagationHeaders[*ix].value = itr->second.c_str(); + char *temp_key = (char*)malloc(itr->first.size() + 1); + std::strcpy(temp_key, itr->first.c_str()); + propagationHeaders[*ix].name = temp_key; + char *temp_value= (char*)malloc(itr->second.size() + 1); + std::strcpy(temp_value, itr->second.c_str()); + propagationHeaders[*ix].value = temp_value; ++(*ix); } } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 10faacfb5..38a91fa4e 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -708,6 +708,13 @@ static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c { ngx_writeError(r->connection->log, __func__, "Error: Interaction begin result code: %d", res); } + for(int i=0;iheaders_in.headers); if(h == NULL){ return; } h->key.len = strlen(propagationHeaders[i].name); - h->key.data = propagationHeaders[i].name; + h->key.data = ngx_pcalloc(r->pool, sizeof(char)*((h->key.len)+1)); + strcpy(h->key.data, propagationHeaders[i].name); ngx_writeTrace(r->connection->log, __func__, "Key : %s", propagationHeaders[i].name); h->hash = ngx_hash_key(h->key.data, h->key.len); h->value.len = strlen(propagationHeaders[i].value); - h->value.data = propagationHeaders[i].value; + h->value.data = ngx_pcalloc(r->pool, sizeof(char)*((h->value.len)+1)); + strcpy(h->value.data, propagationHeaders[i].value); h->lowcase_key = h->key.data; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); @@ -741,7 +750,7 @@ static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* p } ngx_writeTrace(r->connection->log, __func__, "Value : %s", propagationHeaders[i].value); - }*/ + } ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); ctx->propagationHeaders = propagationHeaders; From 06b41d9fd75022127141e5b83258fd5df34bec8f Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Tue, 19 Jul 2022 15:03:29 +0530 Subject: [PATCH 07/77] CodeQL tool integration with otel-webserver-module for static analysis run (#188) * Added codeql * Added code ql * Adding codeql * Adding codeql * Adding codeql * Adding codeql * Added codeql * Added codeql * Added codeql * Added codeql * Added codeql * Added codeql * Added codeql * Added codeql * Added codeql * Added codeql * Add codeql * Add codeql * Adding codeql * Adding codeql * Adding codeql * Add codeql * Adding Codeql * Added static analyis for webserver * Added static analysis tool integration using codeql * Added new line --- .github/workflows/webserver.yml | 34 +++- .../otel-webserver-module/codeql-env.sh | 179 ++++++++++++++++++ .../src/nginx/ngx_http_opentelemetry_module.c | 30 +-- 3 files changed, 223 insertions(+), 20 deletions(-) create mode 100755 instrumentation/otel-webserver-module/codeql-env.sh diff --git a/.github/workflows/webserver.yml b/.github/workflows/webserver.yml index 525d77305..d7141c3bb 100644 --- a/.github/workflows/webserver.yml +++ b/.github/workflows/webserver.yml @@ -7,14 +7,14 @@ on: - 'instrumentation/otel-webserver-module/**' - '.github/workflows/webserver.yml' pull_request: - branches: [ main ] + branches: [ main, webserver-dev ] paths: - 'instrumentation/otel-webserver-module/**' - '.github/workflows/webserver.yml' jobs: webserver-build-test-ubuntu: - name: apache-ubuntu + name: webserver-ubuntu-build runs-on: ubuntu-20.04 steps: - name: checkout otel webserver @@ -49,7 +49,7 @@ jobs: 'cd /otel-webserver-module; rm -rf build; \ cp -r /dependencies /otel-webserver-module/; \ cp -r /build-dependencies /otel-webserver-module/; \ - ./gradlew assembleApacheModule -DtargetSystem=ubuntu' + ./gradlew assembleWebServerModule -DtargetSystem=ubuntu' - name: unit test run: | docker exec apache_ubuntu_container bash -c \ @@ -60,7 +60,7 @@ jobs: mv /tmp/buildx-cache/apache_ubuntu-new /tmp/buildx-cache/apache_ubuntu webserver-build-test-centos7: - name: apache-centos7 + name: webserver-centos7-build runs-on: ubuntu-20.04 steps: - name: checkout otel webserver @@ -118,7 +118,7 @@ jobs: path: /tmp/apache_centos7/opentelemetry-webserver-sdk-x64-linux.tgz webserver-build-test-centos6: - name: apache-centos6 + name: webserver-centos6-build runs-on: ubuntu-20.04 steps: - name: checkout otel webserver @@ -163,3 +163,27 @@ jobs: rm -rf /tmp/buildx-cache/apache_centos6 mv /tmp/buildx-cache/apache_centos6-new /tmp/buildx-cache/apache_centos6 + Codeql-build: + name: static-analysis + runs-on: ubuntu-20.04 + steps: + - name: checkout otel webserver + uses: actions/checkout@v3 + - name: setup environment + run: | + cd .. + cp opentelemetry-cpp-contrib/instrumentation/otel-webserver-module/codeql-env.sh . + sudo ./codeql-env.sh + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: cpp + - name: build + run: | + cd instrumentation/otel-webserver-module + cp -r /dependencies ../otel-webserver-module/ + cp -r /build-dependencies ../otel-webserver-module/ + ./gradlew assembleWebserverModule -DtargetSystem=ubuntu --info + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + diff --git a/instrumentation/otel-webserver-module/codeql-env.sh b/instrumentation/otel-webserver-module/codeql-env.sh new file mode 100755 index 000000000..c45b434fe --- /dev/null +++ b/instrumentation/otel-webserver-module/codeql-env.sh @@ -0,0 +1,179 @@ +#!/bin/bash + +apt-get -y update && apt-get -y upgrade && apt-get -y dist-upgrade +apt-get install -qq -y --ignore-missing \ + build-essential \ + curl \ + git \ + make \ + pkg-config \ + protobuf-compiler \ + libprotobuf-dev \ + python \ + sudo \ + tar \ + zip \ + unzip \ + wget \ + cmake + +apt-get install -y \ + lcov \ + m4 \ + autoconf \ + automake \ + libtool \ + default-jre + +GRPC_VERSION="1.36.4" +OPENTELEMETRY_VERSION="1.2.0" +BOOST_VERSION="1.75.0" +BOOST_FILENAME="boost_1_75_0" +APR_VERSION="1.7.0" +EXPAT_VERSION="2.3.0" +EXPAT_RVERSION="R_2_3_0" +APRUTIL_VERSION="1.6.1" +LOG4CXX_VERSION="0.11.0" +GTEST_VERSION="1.10.0" +PCRE_VERSION="8.44" +NGINX_VERSION="1.18.0" + +# Install GRPC +git clone --shallow-submodules --depth 1 --recurse-submodules -b v${GRPC_VERSION} \ + 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 \ + && cd ../../.. && rm -rf grpc + +# install opentelemetry +mkdir -p /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ + && mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include \ + && git clone https://github.com/open-telemetry/opentelemetry-cpp \ + && cd opentelemetry-cpp/ \ + && git checkout tags/v${OPENTELEMETRY_VERSION} -b v${OPENTELEMETRY_VERSION} \ + && git submodule update --init --recursive \ + && mkdir build \ + && cd build \ + && cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON -DWITH_OTLP=ON -DCMAKE_INSTALL_PREFIX=/dependencies/opentelemetry/${OPENTELEMETRY_VERSION} \ + && cmake --build . --target all \ + && cd .. \ + && find . -name "*.so" -type f -exec cp {} /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib/ \; \ + && cp build/libopentelemetry_proto.a /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ + && cp -r api/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ + && for dir in exporters/*; do if [ -d "$dir" ]; then cp -rf "$dir/include" /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/; fi; done \ + && cp -r sdk/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ + && cp -r build/generated/third_party/opentelemetry-proto/opentelemetry/proto/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include/opentelemetry/ \ + && cd .. && rm -rf opentelemetry-cpp + +#install Apr +mkdir -p /dependencies/apr/${APR_VERSION} \ + && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apr-${APR_VERSION}.tar.gz \ + && cd apr-${APR_VERSION} \ + && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf apr-${APR_VERSION} && rm -rf apr-${APR_VERSION}.tar.gz + +# install libexpat +mkdir -p /dependencies/expat/${EXPAT_VERSION} \ + && wget https://github.com/libexpat/libexpat/releases/download/${EXPAT_RVERSION}/expat-${EXPAT_VERSION}.tar.gz --no-check-certificate \ + && tar -xf expat-${EXPAT_VERSION}.tar.gz \ + && cd expat-${EXPAT_VERSION} \ + && ./configure --prefix=/dependencies/expat/${EXPAT_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf expat-${EXPAT_VERSION} && rm -rf expat-${EXPAT_VERSION}.tar.gz + +# install Apr-util +mkdir -p /dependencies/apr-util/${APRUTIL_VERSION} \ + && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ + && cd apr-util-${APRUTIL_VERSION} \ + && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/1.7.0 --with-expat=/dependencies/expat/2.3.0 && echo $? \ + && make -j 6 \ + && make install \ + && cd ../ && rm -rf apr-util-${APRUTIL_VERSION} && rm -rf apr-util-${APRUTIL_VERSION}.tar.gz + + +#install log4cxx +mkdir -p /dependencies/apache-log4cxx/${LOG4CXX_VERSION} \ + && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ + && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ + && cd apache-log4cxx-${LOG4CXX_VERSION} \ + && ./configure --prefix=/dependencies/apache-log4cxx/${LOG4CXX_VERSION}/ --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/1.7.0/ --with-apr-util=/dependencies/apr-util/1.6.1/ && echo $? \ + && make -j 6 ; echo 0 \ + && automake --add-missing \ + && make install \ + && cd .. && rm -rf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz && rm -rf apache-log4cxx-${LOG4CXX_VERSION} + +# install googletest +mkdir -p /dependencies/googletest/${GTEST_VERSION}/ \ + && wget https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.tar.gz --no-check-certificate \ + && tar -xf release-${GTEST_VERSION}.tar.gz \ + && cd googletest-release-${GTEST_VERSION}/ \ + && mkdir build && cd build \ + && cmake .. -DCMAKE_INSTALL_PREFIX=/dependencies/googletest/${GTEST_VERSION}/ \ + && make \ + && make install \ + && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ + +#Installing Apache and apr source code +mkdir -p /build-dependencies \ + && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz \ + && tar -xf apr-${APR_VERSION}.tar.gz \ + && mv -f apr-${APR_VERSION} /build-dependencies \ + && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz \ + && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ + && mv -f apr-util-${APRUTIL_VERSION} /build-dependencies \ + && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.2.31.tar.gz \ + && tar -xf httpd-2.2.31.tar.gz \ + && mv -f httpd-2.2.31 /build-dependencies \ + && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.4.23.tar.gz \ + && tar -xf httpd-2.4.23.tar.gz \ + && mv -f httpd-2.4.23 /build-dependencies + +rm -rf apr-util-${APRUTIL_VERSION} && rm -rf apr-util-${APRUTIL_VERSION}.tar.gz \ + && rm -rf httpd-2.4.23.tar.gz && rm -rf httpd-2.2.31.tar.gz \ + && rm -rf grpc \ + && rm -rf apr-${APR_VERSION} && rm -rf apr-${APR_VERSION}.tar.gz + +apt-get install libpcre3 libpcre3-dev -y +apt-get install apache2 -y && a2enmod proxy && a2enmod proxy_http \ + && a2enmod proxy_balancer && a2enmod dav + +#Build and install boost +wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/${BOOST_FILENAME}.tar.gz \ + && tar -xvf ${BOOST_FILENAME}.tar.gz \ + && cd ${BOOST_FILENAME} \ + && ./bootstrap.sh --with-libraries=filesystem,system --prefix=/dependencies/boost/${BOOST_VERSION}/ \ + && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC" cflags="-fvisibility=hidden -fPIC" \ + && cd .. && rm -rf ${BOOST_FILENAME} && rm ${BOOST_FILENAME}.tar.gz + +# install pcre +mkdir -p /dependencies/pcre/${PCRE_VERSION}/ \ + && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ + && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ + && cd pcre-${PCRE_VERSION} \ + && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ + && make && make install \ + && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} + +# install nginx +wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ + && rm -rf nginx-${NGINX_VERSION}.tar.gz diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 38a91fa4e..0c6b619cd 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -924,25 +924,25 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) // Otel Max Queue Size env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; - sprintf(qs, "%d", conf->nginxModuleOtelMaxQueueSize); + sprintf(qs, "%lu", conf->nginxModuleOtelMaxQueueSize); env_config[ix].value = qs; ++ix; // Otel Scheduled Delay env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; - sprintf(sd, "%d", conf->nginxModuleOtelScheduledDelayMillis); + sprintf(sd, "%lu", conf->nginxModuleOtelScheduledDelayMillis); env_config[ix].value = sd; ++ix; // Otel Max Export Batch Size env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; - sprintf(es, "%d", conf->nginxModuleOtelMaxExportBatchSize); + sprintf(es, "%lu", conf->nginxModuleOtelMaxExportBatchSize); env_config[ix].value = es; ++ix; // Otel Export Timeout env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; - sprintf(et, "%d", conf->nginxModuleOtelExportTimeoutMillis); + sprintf(et, "%lu", conf->nginxModuleOtelExportTimeoutMillis); env_config[ix].value = et; ++ix; @@ -1389,9 +1389,9 @@ static char* computeContextName(ngx_http_request_t *r, ngx_http_opentelemetry_lo static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t* conf){ ngx_writeTrace(r->connection->log, __func__, " Config { :" - "(Enabled=\"%d\")" + "(Enabled=\"%ld\")" "(OtelExporterEndpoint=\"%s\")" - "(OtelSslEnabled=\"%d\")" + "(OtelSslEnabled=\"%ld\")" "(OtelSslCertificatePath=\"%s\")" "(OtelSpanExporter=\"%s\")" "(OtelSpanProcessor=\"%s\")" @@ -1399,15 +1399,15 @@ static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t "(ServiceNamespace=\"%s\")" "(ServiceName=\"%s\")" "(ServiceInstanceId=\"%s\")" - "(OtelMaxQueueSize=\"%d\")" - "(OtelScheduledDelayMillis=\"%d\")" - "(OtelExportTimeoutMillis=\"%d\")" - "(OtelMaxExportBatchSize=\"%d\")" - "(ResolveBackends=\"%d\")" - "(TraceAsError=\"%d\")" - "(ReportAllInstrumentedModules=\"%d\")" - "(MaskCookie=\"%d\")" - "(MaskSmUser=\"%d\")" + "(OtelMaxQueueSize=\"%lu\")" + "(OtelScheduledDelayMillis=\"%lu\")" + "(OtelExportTimeoutMillis=\"%lu\")" + "(OtelMaxExportBatchSize=\"%lu\")" + "(ResolveBackends=\"%ld\")" + "(TraceAsError=\"%ld\")" + "(ReportAllInstrumentedModules=\"%ld\")" + "(MaskCookie=\"%ld\")" + "(MaskSmUser=\"%ld\")" "(SegmentType=\"%s\")" "(SegmentParameter=\"%s\")" " }", From 9b2ac15e35cddf3399f273fb5fe17f3934370595 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Thu, 21 Jul 2022 16:02:07 +0530 Subject: [PATCH 08/77] making changes to dockerfile and compose (#191) --- .github/workflows/webserver.yml | 4 +- .../otel-webserver-module/Dockerfile | 31 +- .../otel-webserver-module/docker-compose.yml | 4 +- .../docker/centos7/Dockerfile | 22 +- .../docker/nginx/centos/Dockerfile | 283 ---------------- .../docker/nginx/centos7/Dockerfile | 301 ------------------ .../otel-webserver-module/otel-config.yml | 6 +- 7 files changed, 44 insertions(+), 607 deletions(-) delete mode 100644 instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile delete mode 100644 instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile diff --git a/.github/workflows/webserver.yml b/.github/workflows/webserver.yml index d7141c3bb..4b8977255 100644 --- a/.github/workflows/webserver.yml +++ b/.github/workflows/webserver.yml @@ -95,7 +95,7 @@ jobs: 'cd /otel-webserver-module; rm -rf build; \ cp -r /dependencies /otel-webserver-module/; \ cp -r /build-dependencies /otel-webserver-module/; \ - ./gradlew assembleApacheModule' + ./gradlew assembleWebServerModule' - name: unit test run: | docker exec apache_centos7_container bash -c \ @@ -153,7 +153,7 @@ jobs: 'cd /otel-webserver-module; rm -rf build; \ cp -r /dependencies /otel-webserver-module/; \ cp -r /build-dependencies /otel-webserver-module/; \ - ./gradlew assembleApacheModule' + ./gradlew assembleWebServerModule' - name: unit test run: | docker exec apache_centos6_container bash -c \ diff --git a/instrumentation/otel-webserver-module/Dockerfile b/instrumentation/otel-webserver-module/Dockerfile index f94801d21..a260c076b 100644 --- a/instrumentation/otel-webserver-module/Dockerfile +++ b/instrumentation/otel-webserver-module/Dockerfile @@ -48,9 +48,9 @@ RUN yum update -y \ # install lcov package RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ - && yum install ./epel-release-latest-*.noarch.rpm -y \ - && yum install lcov -y \ - && yum clean all + && yum install ./epel-release-latest-*.noarch.rpm -y \ + && yum install lcov -y \ + && yum clean all # install devtoolset toolchain RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo \ @@ -66,11 +66,11 @@ ENV PATH="/opt/rh/devtoolset-7/root/usr/bin:${PATH}" # install python RUN wget http://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \ - && unxz Python-${PYTHON_VERSION}.tar.xz \ - && tar -xf Python-${PYTHON_VERSION}.tar \ - && cd Python-${PYTHON_VERSION} && ./configure --prefix=/usr/local && make && make install \ - && cd .. \ - && rm -rf Python-${PYTHON_VERSION}.tar.xz && rm -rf Python-${PYTHON_VERSION}.tar + && unxz Python-${PYTHON_VERSION}.tar.xz \ + && tar -xf Python-${PYTHON_VERSION}.tar \ + && cd Python-${PYTHON_VERSION} && ./configure --prefix=/usr/local && make && make install \ + && cd .. \ + && rm -rf Python-${PYTHON_VERSION}.tar.xz && rm -rf Python-${PYTHON_VERSION}.tar # install gosu for easy step-down from root (from https://github.com/tianon/gosu/blob/master/INSTALL.md#from-centos) ENV GOSU_VERSION=1.10 @@ -251,9 +251,15 @@ COPY . /otel-webserver-module RUN cp -r /dependencies /otel-webserver-module/ \ && cp -r /build-dependencies /otel-webserver-module/ \ && cd otel-webserver-module \ - && ./gradlew assembleApacheModule + && ./gradlew assembleWebServerModule + +RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ + && echo 'name=nginx repo' >> /etc/yum.repos.d/nginx.repo \ + && echo 'baseurl=https://nginx.org/packages/centos/6/x86_64' >> /etc/yum.repos.d/nginx.repo \ + && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ + && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ + && yum install nginx -y -# install webserver module RUN cd /otel-webserver-module/build \ && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ && mv -f opentelemetry-webserver-sdk /opt/ \ @@ -264,6 +270,11 @@ RUN cd /otel-webserver-module/build \ && ./install.sh \ && cd / +RUN cp /otel-webserver-module/conf/nginx/opentelemetry_module.conf /opt/ \ + && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ + && cd / + # Remove unwanted files RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTOMAKE_VERSION} && rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 \ && rm -rf libtool-${LIBTOOL_VERSION} && rm -rf Python-${PYTHON_VERSION} \ diff --git a/instrumentation/otel-webserver-module/docker-compose.yml b/instrumentation/otel-webserver-module/docker-compose.yml index 2a7b3cfeb..5ca22ce2b 100644 --- a/instrumentation/otel-webserver-module/docker-compose.yml +++ b/instrumentation/otel-webserver-module/docker-compose.yml @@ -46,7 +46,7 @@ services: nginx_centos: build: context: . - dockerfile: docker/nginx/centos/Dockerfile + dockerfile: Dockerfile image: nginx_centos hostname: webserver container_name: nginx_centos @@ -60,7 +60,7 @@ services: nginx_centos7: build: context: . - dockerfile: docker/nginx/centos7/Dockerfile + dockerfile: docker/centos7/Dockerfile image: nginx_centos7 hostname: webserver container_name: nginx_centos7 diff --git a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile index 66fe742d3..ae214fba3 100644 --- a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile @@ -49,9 +49,9 @@ RUN yum update -y \ # install lcov package RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ - && yum install ./epel-release-latest-*.noarch.rpm -y \ - && yum install lcov -y \ - && yum clean all + && yum install ./epel-release-latest-*.noarch.rpm -y \ + && yum install lcov -y \ + && yum clean all # install devtoolset toolchain # RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo \ @@ -264,15 +264,20 @@ RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ && rm -rf nginx-${NGINX_VERSION}.tar.gz # Build Webserver Module - COPY . /otel-webserver-module RUN cp -r /dependencies /otel-webserver-module/ \ && cp -r /build-dependencies /otel-webserver-module/ \ && cd otel-webserver-module \ - && ./gradlew assembleApacheModule -DtargetSystem=centos7 + && ./gradlew assembleWebServerModule + +RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ + && echo 'name=nginx repo' >> /etc/yum.repos.d/nginx.repo \ + && echo 'baseurl=https://nginx.org/packages/centos/7/x86_64' >> /etc/yum.repos.d/nginx.repo \ + && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ + && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ + && yum install nginx-1.18.0 -y -# install webserver module RUN cd /otel-webserver-module/build \ && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ && mv -f opentelemetry-webserver-sdk /opt/ \ @@ -284,6 +289,11 @@ RUN cd /otel-webserver-module/build \ && ./install.sh \ && cd / +RUN cp /otel-webserver-module/conf/nginx/opentelemetry_module.conf /opt/ \ + && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ + && cd / + # Remove unwanted files RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTOMAKE_VERSION} && rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 \ && rm -rf libtool-${LIBTOOL_VERSION} && rm -rf Python-${PYTHON_VERSION} \ diff --git a/instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile b/instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile deleted file mode 100644 index 486ba8641..000000000 --- a/instrumentation/otel-webserver-module/docker/nginx/centos/Dockerfile +++ /dev/null @@ -1,283 +0,0 @@ -FROM centos:6.9 - -ARG BUILD_NUMBER - -LABEL NAME=apm/build-image-webserver-agent-centos6-x64 VERSION=$BUILD_NUMBER - -ENV GOSU_ARCH amd64 -ENV JDK_ARCH x64 - -ARG PYTHON_VERSION="2.7.8" -ARG CMAKE_VERSION="3.20" -ARG CMAKE_0VERSION="3.20.0" -ARG GRPC_VERSION="1.36.4" -ARG OPENTELEMETRY_VERSION="1.2.0" -ARG BOOST_VERSION="1.75.0" -ARG BOOST_FILENAME="boost_1_75_0" -ARG APR_VERSION="1.7.0" -ARG EXPAT_VERSION="2.3.0" -ARG EXPAT_RVERSION="R_2_3_0" -ARG APRUTIL_VERSION="1.6.1" -ARG AUTOCONF_VERSION="2.68" -ARG LIBTOOL_VERSION="2.4.6" -ARG LOG4CXX_VERSION="0.11.0" -ARG GTEST_VERSION="1.10.0" -ARG AUTOMAKE_VERSION="1.16.3" -ARG PCRE_VERSION="8.44" -ARG NGINX_VERSION="1.18.0" - - -# create default non-root user -RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser - -RUN chmod -R 777 /opt - -RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo - -# install required packages -RUN yum update -y \ - && yum install -y \ - yum install wget -y \ - yum install -y zlib-devel \ - yum install -y openssl-devel \ - yum install java-1.8.0-openjdk -y \ - yum install pcre-devel -y \ - yum install xz -y \ - yum install httpd -y \ - && yum clean all - -# install lcov package -RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ - && yum install ./epel-release-latest-*.noarch.rpm -y \ - && yum install lcov -y \ - && yum clean all - -# install devtoolset toolchain -RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo \ - && curl https://www.getpagespeed.com/files/centos6-epel-eol.repo --output /etc/yum.repos.d/epel.repo \ - && yum -y install centos-release-scl \ - && curl https://www.getpagespeed.com/files/centos6-scl-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl.repo \ - && curl https://www.getpagespeed.com/files/centos6-scl-rh-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo \ - && yum install yum-utils -y \ - && yum-config-manager --enable rhel-server-rhscl-7-rpms -y \ - && yum install devtoolset-7 -y \ - && yum clean all -ENV PATH="/opt/rh/devtoolset-7/root/usr/bin:${PATH}" - -# install python -RUN wget http://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \ - && unxz Python-${PYTHON_VERSION}.tar.xz \ - && tar -xf Python-${PYTHON_VERSION}.tar \ - && cd Python-${PYTHON_VERSION} && ./configure --prefix=/usr/local && make && make install \ - && cd .. \ - && rm -rf Python-${PYTHON_VERSION}.tar.xz && rm -rf Python-${PYTHON_VERSION}.tar - -# install gosu for easy step-down from root (from https://github.com/tianon/gosu/blob/master/INSTALL.md#from-centos) -ENV GOSU_VERSION=1.10 - -RUN curl -o /usr/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" \ - && chmod +x /usr/bin/gosu \ - # Verify that the binary works - && gosu nobody true - -# install git required for grpc -RUN yum install git -y \ - && yum clean all - -# install cmake -RUN wget https://cmake.org/files/v${CMAKE_VERSION}/cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ - && tar -xvf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ - && cd cmake-${CMAKE_0VERSION}-linux-x86_64 \ - && cp -rf * /usr/local/ \ - && cd .. && rm -rf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz - -# install grpc. If planning to upgrade, make sure sed command works -RUN git clone https://github.com/grpc/grpc \ - && cd grpc \ - && git checkout tags/v${GRPC_VERSION} -b v${GRPC_VERSION} \ - && git submodule update --init \ - && sed -i "s/target_link_libraries(bssl ssl crypto)/target_link_libraries(bssl ssl crypto rt)/g" third_party/boringssl-with-bazel/CMakeLists.txt \ - && mkdir -p cmake/build \ - && cd cmake/build \ - && cmake ../.. -DgRPC_INSTALL=ON -DCMAKE_BUILD_TYPE=Release -DgRPC_ABSL_PROVIDER=module -DgRPC_CARES_PROVIDER=module -DgRPC_PROTOBUF_PROVIDER=module -DgRPC_RE2_PROVIDER=module -DgRPC_SSL_PROVIDER=module -DgRPC_ZLIB_PROVIDER=module \ - && make \ - && make install \ - && cd ../../.. - -# Create dependencies folder to store all dependencies. -RUN mkdir -p dependencies - -# install boost version -RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/${BOOST_FILENAME}_rc1.tar.gz \ - && tar -xvf ${BOOST_FILENAME}_rc1.tar.gz \ - && cd ${BOOST_FILENAME} \ - && ./bootstrap.sh --with-libraries=filesystem,system --prefix=/dependencies/boost/${BOOST_VERSION}/ \ - && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC" cflags="-fvisibility=hidden -fPIC" \ - && cd .. && rm -rf ${BOOST_FILENAME} && rm ${BOOST_FILENAME}_rc1.tar.gz - -#install Apr -RUN mkdir -p dependencies/apr/${APR_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ - && tar -xf apr-${APR_VERSION}.tar.gz \ - && cd apr-${APR_VERSION} \ - && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ - && make -j 6 \ - && make install \ - && cd ../ && rm -rf apr-${APR_VERSION} && rm -rf apr-${APR_VERSION}.tar.gz - -# install libexpat -RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ - && wget https://github.com/libexpat/libexpat/releases/download/${EXPAT_RVERSION}/expat-${EXPAT_VERSION}.tar.gz --no-check-certificate \ - && tar -xf expat-${EXPAT_VERSION}.tar.gz \ - && cd expat-${EXPAT_VERSION} \ - && ./configure --prefix=/dependencies/expat/${EXPAT_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ - && make -j 6 \ - && make install \ - && cd ../ && rm -rf expat-${EXPAT_VERSION} && rm -rf expat-${EXPAT_VERSION}.tar.gz - -# install Apr-util -RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ - && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ - && cd apr-util-${APRUTIL_VERSION} \ - && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION} --with-expat=/dependencies/expat/${EXPAT_VERSION} && echo $? \ - && make -j 6 \ - && make install \ - && cd ../ && rm -rf apr-util-${APRUTIL_VERSION} && rm -rf apr-util-${APRUTIL_VERSION}.tar.gz - -# install m4 -RUN yum install m4 -y - -# install autoconf -RUN wget --no-check-certificate https://ftp.gnu.org/gnu/autoconf/autoconf-${AUTOCONF_VERSION}.tar.gz \ - && tar xzf autoconf-${AUTOCONF_VERSION}.tar.gz \ - && cd autoconf-${AUTOCONF_VERSION} \ - && ./configure --prefix=/usr/ && make -j && make install && autoconf -V \ - && cd .. && rm -rf autoconf-${AUTOCONF_VERSION}.tar.gz - -# install automake -RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-${AUTOMAKE_VERSION}.tar.gz \ - && tar xzf automake-${AUTOMAKE_VERSION}.tar.gz \ - && cd automake-${AUTOMAKE_VERSION} \ - && ./configure --prefix=/usr --libdir=/usr/lib64 \ - && make -j && make install \ - && automake --version \ - && 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 \ - && 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 - -#install log4cxx -RUN mkdir -p dependencies/apache-log4cxx/-${LOG4CXX_VERSION} \ - && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ - && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ - && cd apache-log4cxx-${LOG4CXX_VERSION} \ - && ./configure --prefix=/dependencies/apache-log4cxx/${LOG4CXX_VERSION}/ --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION}/ --with-apr-util=/dependencies/apr-util/${APRUTIL_VERSION}/ && echo $? \ - && make -j 6 ; echo 0 \ - && automake --add-missing \ - && make install \ - && cd .. && rm -rf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz && rm -rf apache-log4cxx-${LOG4CXX_VERSION} - -# install opentelemetry -RUN mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ - && mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include \ - && git clone https://github.com/open-telemetry/opentelemetry-cpp \ - && cd opentelemetry-cpp/ \ - && git checkout tags/v${OPENTELEMETRY_VERSION} -b v${OPENTELEMETRY_VERSION} \ - && git submodule update --init --recursive \ - && mkdir build \ - && cd build \ - && cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON -DWITH_OTLP=ON -DCMAKE_INSTALL_PREFIX=/dependencies/opentelemetry/${OPENTELEMETRY_VERSION} \ - && cmake --build . --target all \ - && cd .. \ - && find . -name "*.so" -type f -exec cp {} /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib/ \; \ - && cp build/libopentelemetry_proto.a /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ - && cp -r api/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ - && for dir in exporters/*; do if [ -d "$dir" ]; then cp -rf "$dir/include" /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/; fi; done \ - && cp -r sdk/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ - && cp -r build/generated/third_party/opentelemetry-proto/opentelemetry/proto/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include/opentelemetry/ \ - && cd .. && rm -rf opentelemetry-cpp - -# install googletest -RUN mkdir -p dependencies/googletest/${GTEST_VERSION}/ \ - && wget https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.tar.gz --no-check-certificate \ - && tar -xf release-${GTEST_VERSION}.tar.gz \ - && cd googletest-release-${GTEST_VERSION}/ \ - && mkdir build && cd build \ - && cmake .. -DCMAKE_INSTALL_PREFIX=/dependencies/googletest/${GTEST_VERSION}/ \ - && make \ - && make install \ - && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ - -# install pcre -RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ - && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ - && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ - && cd pcre-${PCRE_VERSION} \ - && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ - && make && make install \ - && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} - -#Installing Apache and apr source code -RUN mkdir build-dependencies \ - && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz \ - && tar -xf apr-${APR_VERSION}.tar.gz \ - && mv -f apr-${APR_VERSION} build-dependencies \ - && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz \ - && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ - && mv -f apr-util-${APRUTIL_VERSION} build-dependencies \ - && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.2.31.tar.gz \ - && tar -xf httpd-2.2.31.tar.gz \ - && mv -f httpd-2.2.31 build-dependencies \ - && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.4.23.tar.gz \ - && tar -xf httpd-2.4.23.tar.gz \ - && mv -f httpd-2.4.23 build-dependencies - -# install nginx -RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ - && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ - && rm -rf nginx-${NGINX_VERSION}.tar.gz - -# Build Webserver Module -COPY . /otel-webserver-module - -RUN cp -r /dependencies /otel-webserver-module/ \ - && cp -r /build-dependencies /otel-webserver-module/ \ - && cd otel-webserver-module \ - && ./gradlew assembleWebServerModule - -RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ - && echo 'name=nginx repo' >> /etc/yum.repos.d/nginx.repo \ - && echo 'baseurl=https://nginx.org/packages/centos/6/x86_64' >> /etc/yum.repos.d/nginx.repo \ - && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ - && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ - && yum install nginx -y - -RUN cd /otel-webserver-module/build \ - && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ - && mv -f opentelemetry-webserver-sdk /opt/ \ - && cd ../ \ - && cp conf/nginx/opentelemetry_module.conf /opt/ \ - && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ - && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ - && cd /opt/opentelemetry-webserver-sdk \ - && ./install.sh \ - && cd / - - - -# Remove unwanted files -RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTOMAKE_VERSION} && rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 \ - && rm -rf libtool-${LIBTOOL_VERSION} && rm -rf Python-${PYTHON_VERSION} \ - && rm -f apr-${APR_VERSION}.tar.gz && rm -f apr-util-${APRUTIL_VERSION}.tar.gz \ - && 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"] diff --git a/instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile deleted file mode 100644 index 734cf6d6b..000000000 --- a/instrumentation/otel-webserver-module/docker/nginx/centos7/Dockerfile +++ /dev/null @@ -1,301 +0,0 @@ -FROM centos:7 - -ARG BUILD_NUMBER - -LABEL NAME=apm/build-image-webserver-agent-centos6-x64 VERSION=$BUILD_NUMBER - -ENV GOSU_ARCH amd64 -ENV JDK_ARCH x64 - -ARG PYTHON_VERSION="2.7.8" -ARG CMAKE_VERSION="3.20" -ARG CMAKE_0VERSION="3.20.0" -ARG GRPC_VERSION="1.36.4" -ARG OPENTELEMETRY_VERSION="1.2.0" -ARG BOOST_VERSION="1.75.0" -ARG BOOST_FILENAME="boost_1_75_0" -ARG APR_VERSION="1.7.0" -ARG EXPAT_VERSION="2.3.0" -ARG EXPAT_RVERSION="R_2_3_0" -ARG APRUTIL_VERSION="1.6.1" -ARG AUTOCONF_VERSION="2.68" -ARG LIBTOOL_VERSION="2.4.6" -ARG LOG4CXX_VERSION="0.11.0" -ARG GTEST_VERSION="1.10.0" -ARG AUTOMAKE_VERSION="1.16.3" -ARG PERL_VERSION="5.20.2" -ARG PERL_CPANVERSION="5.0" -ARG PCRE_VERSION="8.44" -ARG NGINX_VERSION="1.18.0" - -# create default non-root user -RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser - -RUN chmod -R 777 /opt - -# RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo - -# install required packages -RUN yum update -y \ - && yum install -y \ - yum install wget -y \ - yum install -y zlib-devel \ - yum install -y openssl-devel \ - yum install java-1.8.0-openjdk -y \ - yum install pcre-devel -y \ - yum install xz -y \ - yum install httpd -y \ - && yum clean all - -# install lcov package -RUN wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \ - && yum install ./epel-release-latest-*.noarch.rpm -y \ - && yum install lcov -y \ - && yum clean all - -# install devtoolset toolchain -# RUN curl https://www.getpagespeed.com/files/centos6-eol.repo --output /etc/yum.repos.d/CentOS-Base.repo \ -# && curl https://www.getpagespeed.com/files/centos6-epel-eol.repo --output /etc/yum.repos.d/epel.repo \ - RUN yum -y install centos-release-scl \ -# && curl https://www.getpagespeed.com/files/centos6-scl-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl.repo \ -# && curl https://www.getpagespeed.com/files/centos6-scl-rh-eol.repo --output /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo \ - && yum install yum-utils -y \ - && yum-config-manager --enable rhel-server-rhscl-7-rpms -y \ - && yum install devtoolset-7 -y \ - && yum clean all -ENV PATH="/opt/rh/devtoolset-7/root/usr/bin:${PATH}" - -# install python 2.7.8 -RUN wget http://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tar.xz \ - && unxz Python-${PYTHON_VERSION}.tar.xz \ - && tar -xf Python-${PYTHON_VERSION}.tar \ - && cd Python-${PYTHON_VERSION} && ./configure --prefix=/usr/local && make && make install \ - && cd .. \ - && rm -rf Python-${PYTHON_VERSION}.tar.xz && rm -rf Python-${PYTHON_VERSION}.tar - -# install gosu for easy step-down from root (from https://github.com/tianon/gosu/blob/master/INSTALL.md#from-centos) -ENV GOSU_VERSION=1.10 -#RUN gpg --keyserver pgp.mit.edu --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \ -# && curl -o /usr/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" \ -# && curl -o /usr/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64.asc" \ -# && gpg --verify /usr/bin/gosu.asc \ -# && rm /usr/bin/gosu.asc \ -# && rm -r /root/.gnupg/ \ -RUN curl -o /usr/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64" \ - && chmod +x /usr/bin/gosu \ - # Verify that the binary works - && gosu nobody true - -# install git required for grpc -RUN yum install git -y \ - && yum clean all - -# install cmake 3.20 -RUN wget https://cmake.org/files/v${CMAKE_VERSION}/cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ - && tar -xvf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz \ - && cd cmake-${CMAKE_0VERSION}-linux-x86_64 \ - && cp -rf * /usr/local/ \ - && cd .. && rm -rf cmake-${CMAKE_0VERSION}-linux-x86_64.tar.gz - -# install grpc. If planning to upgrade, make sure sed command works -RUN git clone https://github.com/grpc/grpc \ - && cd grpc \ - && git checkout tags/v${GRPC_VERSION} -b v${GRPC_VERSION} \ - && git submodule update --init \ - && sed -i "s/target_link_libraries(bssl ssl crypto)/target_link_libraries(bssl ssl crypto rt)/g" third_party/boringssl-with-bazel/CMakeLists.txt \ - && mkdir -p cmake/build \ - && cd cmake/build \ - && cmake ../.. -DgRPC_INSTALL=ON -DCMAKE_BUILD_TYPE=Release -DgRPC_ABSL_PROVIDER=module -DgRPC_CARES_PROVIDER=module -DgRPC_PROTOBUF_PROVIDER=module -DgRPC_RE2_PROVIDER=module -DgRPC_SSL_PROVIDER=module -DgRPC_ZLIB_PROVIDER=module \ - && make \ - && make install \ - && cd ../../.. - -# Create dependencies folder to store all dependencies. -RUN mkdir -p dependencies - -# install boost version 1.75.0 -RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/source/${BOOST_FILENAME}_rc1.tar.gz \ - && tar -xvf ${BOOST_FILENAME}_rc1.tar.gz \ - && cd ${BOOST_FILENAME} \ - && ./bootstrap.sh --with-libraries=filesystem,system --prefix=/dependencies/boost/${BOOST_VERSION}/ \ - && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC" cflags="-fvisibility=hidden -fPIC" \ - && cd .. && rm -rf ${BOOST_FILENAME} && rm ${BOOST_FILENAME}_rc1.tar.gz - -#install Apr -RUN mkdir -p dependencies/apr/${APR_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ - && tar -xf apr-${APR_VERSION}.tar.gz \ - && cd apr-${APR_VERSION} \ - && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ - && make -j 6 \ - && make install \ - && cd ../ && rm -rf apr-${APR_VERSION} && rm -rf apr-${APR_VERSION}.tar.gz - -# install libexpat -RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ - && wget https://github.com/libexpat/libexpat/releases/download/${EXPAT_RVERSION}/expat-${EXPAT_VERSION}.tar.gz --no-check-certificate \ - && tar -xf expat-${EXPAT_VERSION}.tar.gz \ - && cd expat-${EXPAT_VERSION} \ - && ./configure --prefix=/dependencies/expat/${EXPAT_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ - && make -j 6 \ - && make install \ - && cd ../ && rm -rf expat-${EXPAT_VERSION} && rm -rf expat-${EXPAT_VERSION}.tar.gz - -# install Apr-util -RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ - && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ - && cd apr-util-${APRUTIL_VERSION} \ - && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION} --with-expat=/dependencies/expat/${EXPAT_VERSION} && echo $? \ - && make -j 6 \ - && make install \ - && cd ../ && rm -rf apr-util-${APRUTIL_VERSION} && rm -rf apr-util-${APRUTIL_VERSION}.tar.gz - -# install m4 -RUN yum install m4 -y \ - && yum install perl-Data-Dumper -y - -# Update perl version -RUN yum install perl-Thread-Queue.noarch -y \ - && wget http://www.cpan.org/src/${PERL_CPANVERSION}/perl-${PERL_VERSION}.tar.gz \ - && tar -xzf perl-${PERL_VERSION}.tar.gz \ - && cd perl-${PERL_VERSION} \ - && ./Configure -des -Dprefix=$HOME/localperl \ - && make \ - && make test; echo 0 \ - && make install -ENV PATH=$HOME/localperl/bin:$PATH - -# install autoconf -RUN wget --no-check-certificate https://ftp.gnu.org/gnu/autoconf/autoconf-${AUTOCONF_VERSION}.tar.gz \ - && tar xzf autoconf-${AUTOCONF_VERSION}.tar.gz \ - && cd autoconf-${AUTOCONF_VERSION} \ - && ./configure --prefix=/usr/ && make -j && make install && autoconf -V \ - && cd .. && rm -rf autoconf-${AUTOCONF_VERSION}.tar.gz - -# install automake -RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-${AUTOMAKE_VERSION}.tar.gz \ - && tar xzf automake-${AUTOMAKE_VERSION}.tar.gz \ - && cd automake-${AUTOMAKE_VERSION} \ - && ./configure --prefix=/usr --libdir=/usr/lib64 \ - && make -j && make install \ - && automake --version \ - && 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 \ - && 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 - -#install log4cxx -RUN mkdir -p dependencies/apache-log4cxx/-${LOG4CXX_VERSION} \ - && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ - && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ - && cd apache-log4cxx-${LOG4CXX_VERSION} \ - && ./configure --prefix=/dependencies/apache-log4cxx/${LOG4CXX_VERSION}/ --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION}/ --with-apr-util=/dependencies/apr-util/${APRUTIL_VERSION}/ && echo $? \ - && make -j 6 ; echo 0 \ - && automake --add-missing \ - && make install \ - && cd .. && rm -rf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz && rm -rf apache-log4cxx-${LOG4CXX_VERSION} - -# install opentelemetry -RUN mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ - && mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include \ - && git clone https://github.com/open-telemetry/opentelemetry-cpp \ - && cd opentelemetry-cpp/ \ - && git checkout tags/v${OPENTELEMETRY_VERSION} -b v${OPENTELEMETRY_VERSION} \ - && git submodule update --init --recursive \ - && mkdir build \ - && cd build \ - && cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON -DWITH_OTLP=ON -DCMAKE_INSTALL_PREFIX=/dependencies/opentelemetry/${OPENTELEMETRY_VERSION} \ - && cmake --build . --target all \ - && cd .. \ - && find . -name "*.so" -type f -exec cp {} /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib/ \; \ - && cp build/libopentelemetry_proto.a /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ - && cp -r api/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ - && for dir in exporters/*; do if [ -d "$dir" ]; then cp -rf "$dir/include" /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/; fi; done \ - && cp -r sdk/include/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/ \ - && cp -r build/generated/third_party/opentelemetry-proto/opentelemetry/proto/ /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/include/opentelemetry/ \ - && cd .. && rm -rf opentelemetry-cpp - -# install googletest -RUN mkdir -p dependencies/googletest/${GTEST_VERSION}/ \ - && wget https://github.com/google/googletest/archive/refs/tags/release-${GTEST_VERSION}.tar.gz --no-check-certificate \ - && tar -xf release-${GTEST_VERSION}.tar.gz \ - && cd googletest-release-${GTEST_VERSION}/ \ - && mkdir build && cd build \ - && cmake .. -DCMAKE_INSTALL_PREFIX=/dependencies/googletest/${GTEST_VERSION}/ \ - && make \ - && make install \ - && cd ../.. && rm -rf release-${GTEST_VERSION}.tar.gz && rm -rf googletest-release-${GTEST_VERSION}/ - -# install pcre -RUN mkdir -p dependencies/pcre/${PCRE_VERSION}/ \ - && wget https://ftp.exim.org/pub/pcre/pcre-${PCRE_VERSION}.tar.gz --no-check-certificate \ - && tar -xvf pcre-${PCRE_VERSION}.tar.gz \ - && cd pcre-${PCRE_VERSION} \ - && ./configure --prefix=/dependencies/pcre/${PCRE_VERSION} --enable-jit \ - && make && make install \ - && cd .. && rm -rf ${PCRE_VERSION}.tar.gz && rm -rf pcre-${PCRE_VERSION} - -#Installing Apache and apr source code -RUN mkdir build-dependencies \ - && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz \ - && tar -xf apr-${APR_VERSION}.tar.gz \ - && mv -f apr-${APR_VERSION} build-dependencies \ - && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz \ - && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ - && mv -f apr-util-${APRUTIL_VERSION} build-dependencies \ - && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.2.31.tar.gz \ - && tar -xf httpd-2.2.31.tar.gz \ - && mv -f httpd-2.2.31 build-dependencies \ - && wget --no-check-certificate http://archive.apache.org/dist/httpd/httpd-2.4.23.tar.gz \ - && tar -xf httpd-2.4.23.tar.gz \ - && mv -f httpd-2.4.23 build-dependencies - -# install nginx -RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ - && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ - && rm -rf nginx-${NGINX_VERSION}.tar.gz - -# Build Webserver Module -COPY . /otel-webserver-module - -RUN cp -r /dependencies /otel-webserver-module/ \ - && cp -r /build-dependencies /otel-webserver-module/ \ - && cd otel-webserver-module \ - && ./gradlew assembleWebServerModule - -RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ - && echo 'name=nginx repo' >> /etc/yum.repos.d/nginx.repo \ - && echo 'baseurl=https://nginx.org/packages/centos/7/x86_64' >> /etc/yum.repos.d/nginx.repo \ - && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ - && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ - && yum install nginx-1.18.0 -y - -RUN cd /otel-webserver-module/build \ - && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ - && mv -f opentelemetry-webserver-sdk /opt/ \ - && cd ../ \ - && cp conf/nginx/opentelemetry_module.conf /opt/ \ - && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ - && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ - && cd /opt/opentelemetry-webserver-sdk \ - && ./install.sh \ - && cd / - - - -# Remove unwanted files -RUN rm -rf grpc && rm -rf autoconf-${AUTOCONF_VERSION} && rm -rf automake-${AUTOMAKE_VERSION} && rm -rf cmake-${CMAKE_VERSION}-linux-x86_64 \ - && rm -rf libtool-${LIBTOOL_VERSION} && rm -rf Python-${PYTHON_VERSION} \ - && rm -f apr-${APR_VERSION}.tar.gz && rm -f apr-util-${APRUTIL_VERSION}.tar.gz \ - && 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"] diff --git a/instrumentation/otel-webserver-module/otel-config.yml b/instrumentation/otel-webserver-module/otel-config.yml index 5c62e2e3e..450cdfdd2 100644 --- a/instrumentation/otel-webserver-module/otel-config.yml +++ b/instrumentation/otel-webserver-module/otel-config.yml @@ -10,9 +10,9 @@ processors: - key: service.namespace value: "sample_namespace" action: upsert - - key: service.name - value: "sample_service" - action: upsert +# - key: service.name +# value: "sample_service" +# action: upsert receivers: otlp: protocols: From e3e10a8c367985d69fba24f509ef2cbb7ce24700 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Mon, 25 Jul 2022 12:39:41 +0530 Subject: [PATCH 09/77] Fix build failure on centos6 and centos7 (#193) --- instrumentation/otel-webserver-module/Dockerfile | 4 +++- .../otel-webserver-module/docker/centos7/Dockerfile | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/instrumentation/otel-webserver-module/Dockerfile b/instrumentation/otel-webserver-module/Dockerfile index a260c076b..10b678861 100644 --- a/instrumentation/otel-webserver-module/Dockerfile +++ b/instrumentation/otel-webserver-module/Dockerfile @@ -174,8 +174,10 @@ RUN wget --no-check-certificate https://ftpmirror.gnu.org/libtool/libtool-${LIBT && libtool --version \ && cd .. && rm -rf libtool--${LIBTOOL_VERSION}.tar.gz +RUN ls + #install log4cxx -RUN mkdir -p dependencies/apache-log4cxx/-${LOG4CXX_VERSION} \ +RUN mkdir -p dependencies/apache-log4cxx/${LOG4CXX_VERSION} \ && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ && cd apache-log4cxx-${LOG4CXX_VERSION} \ diff --git a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile index ae214fba3..1c5f14b3e 100644 --- a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile @@ -193,7 +193,7 @@ RUN wget --no-check-certificate https://ftpmirror.gnu.org/libtool/libtool-${LIBT && cd .. && rm -rf libtool--${LIBTOOL_VERSION}.tar.gz #install log4cxx -RUN mkdir -p dependencies/apache-log4cxx/-${LOG4CXX_VERSION} \ +RUN mkdir -p dependencies/apache-log4cxx/${LOG4CXX_VERSION} \ && wget https://archive.apache.org/dist/logging/log4cxx/${LOG4CXX_VERSION}/apache-log4cxx-${LOG4CXX_VERSION}.tar.gz --no-check-certificate \ && tar -xf apache-log4cxx-${LOG4CXX_VERSION}.tar.gz \ && cd apache-log4cxx-${LOG4CXX_VERSION} \ From b21e2df6a799e647fe11912ec403b98f69da03fe Mon Sep 17 00:00:00 2001 From: Siim Kallas Date: Mon, 25 Jul 2022 18:37:17 +0300 Subject: [PATCH 10/77] chore: nginx: drop Ubuntu 21.04 from CI due to end of life (#195) * chore: nginx ci: drop ubuntu 21.04 due to end of life * chore: drop ubuntu 22.10 from ci --- .github/workflows/nginx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nginx.yml b/.github/workflows/nginx.yml index e2b0c572e..1d1da55d7 100644 --- a/.github/workflows/nginx.yml +++ b/.github/workflows/nginx.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - os: [ubuntu-21.04, ubuntu-20.04, ubuntu-18.04, debian-10.11] + os: [ubuntu-20.04, ubuntu-18.04, debian-10.11] nginx-rel: [mainline, stable] steps: - name: checkout otel nginx From 624f65d5bd54b16a0e746cb2d19e97ce2b378513 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Tue, 26 Jul 2022 14:32:28 +0530 Subject: [PATCH 11/77] Updated Readme with details of Nginx instrumentation. (#196) * [otel-webserver-module] Updated Readme with Nginx details * Updated with details * Updated Readme with more details --- .../otel-webserver-module/README.md | 79 +++++++++++++++++-- .../conf/nginx/nginx.conf | 34 ++++++++ 2 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 instrumentation/otel-webserver-module/conf/nginx/nginx.conf diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 43f7a4886..510587b7c 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -67,8 +67,7 @@ A sample configuration is mentioned in [opentelemetry_module.conf](https://githu #### Platform Supported - The build is supported for **x86-64** platforms. -- Currently, it is built and tested on **Centos6** by default -- Other OS support: **Centos7, ubuntu20.04**. +- OS support: **Centos6**, **Centos7, ubuntu20.04**. #### Automatic build and Installation @@ -84,6 +83,10 @@ This would start the container alongwith the the Opentelemetry Collector and Zip #### Manual build and Installation +The artifact can be either downloaded or built manually. + +##### Generate the artifact manually + We will use Docker to run the Module. First, it is to be made sure that the Docker is up and running. Then execute the following commands -: ``` @@ -93,7 +96,16 @@ docker-compose --profile default up Next, login into the Docker container. After going inside the container run the following commands ```cd \otel-webserver-module```. After making code changes the build and installation can be done by running ```./install.sh```. -The build file can be copied at a suitable location in User's system by running the command ```docker cp :/otel-webserver-module/build/opentelemetry-webserver-sdk-x64-linux.tgz ```. The installation steps can be inferred from ```install.sh``` script. +The build file can be copied at a suitable location in User's system by running the command ```docker cp :/otel-webserver-module/build/opentelemetry-webserver-sdk-x64-linux.tgz ```. + +##### Download the artifact + +The artifact can also be downloaded from [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) of the source repository. Click on any top successful workflow runs on main branch and the artifact would be available for download. + +##### Installation Steps + +The installation steps can be referred from [instrument-apache-httpd-server](https://opentelemetry.io/blog/2022/instrument-apache-httpd-server/#installing-opentelemetry-module-in-target-system). +Please ignore the initial steps which talks about generating the artifact locally. ## Nginx Webserver Module @@ -115,7 +127,8 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get * ngx_http_autoindex_module * ngx_http_index_module * ngx_http_random_index_module -* ngx_http_log_module +* ngx_http_try_files_module +* ngx_http_mirror_module ### Third Party Dependencies @@ -164,8 +177,9 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get - Docker Desktop should be installed on the system #### Platform Supported +- Supports only Nginx v1.18.0. - The build is supported for **x86-64** platforms. -- Currently, the build is supported on **Centos6** and **Centos7** +- OS support: **Centos6**, **Centos7, ubuntu20.04**. #### Automatic build and Installation @@ -175,16 +189,67 @@ Then execute the following commands -: docker-compose --profile centos_nginx build docker-compose --profile centos_nginx up ``` -Alternatively, replace the value of *centos_nginx* from **'centos_nginx'** to **'centos7_nginx'** to build in respective supported platforms. +Alternatively, replace the value of *centos_nginx* from **'centos_nginx'** to **'centos7_nginx'** or **'ubuntu20.04_nginx'** to build in respective supported platforms. This would start the container alongwith the the Opentelemetry Collector and Zipkin. You can check the traces on Zipkin dashboard by checking the port number of Zipkin using ```docker ps``` command. Multiple requests can be sent using the browser. #### Manual build and Installation -TBD +The artifact can be either downloaded or built manually. + +##### Generate the artifact manually +We will use Docker to build the artifact. First, it is to be made sure that the Docker is up and running. +Then execute the following commands -: +``` +docker-compose --profile centos7_nginx build +docker-compose --profile centos7_nginx up +``` +Next, login into the Docker container. +After going inside the container run the following commands +``` +cd /otel-webserver-module +./gradlew assembleWebServerModule +``` +The above command builds the aritifact and the same is located at ```/otel-webserver-module/build```. + +The build file can be copied at a suitable location in User's system by running the command ```docker cp :/otel-webserver-module/build/opentelemetry-webserver-sdk-x64-linux.tgz ```. +##### Download the artifact + +The artifact can also be downloaded from [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) of the source repository. Click on any top successful workflow runs on main branch and the artifact would be available for download. + +##### Installation Steps + +In order to install, untar the artifact to /opt directory. +``` +tar -xf opentelemetry-webserver-sdk-x64-linux.tgz -C /opt +cd /opt/opentelemetry-webserver-sdk/ +./install.sh +``` +Copy the ```conf/nginx/opentelemetry_module.conf``` to /opt/. +Make sure to edit the directives values according to your need e.g NginxModuleOtelExporterEndpoint should point to collector url. +Edit the nginx.conf to provide the reference to opentelemetry_module.conf and shared library. +Please mind the order and location of the below entries by referring to ```conf/nginx/nginx.conf```. +``` +load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so; +include /opt/opentelemetry_module.conf; +``` + +Before running Nginx webserver, make sure to update LD_LIBRARY_PATH to pick up opentelemetry dependencies. +``` +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/opentelemetry-webserver-sdk/sdk_lib/lib +``` + +### Usability of the downloaded artifact +The downloaded artifact from [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) is built on CentOS7. This contains shared libraries for both apache and nginx instrumentation. The shared libraries can be located at ```WebServerModule/Apache``` or ```WebServerModule/Nginx``` for respective webservers. But, the common libraries, related to opentelemetry, are located at ```sdk_lib/lib/``` which are used by both apache and nginx instrumentation. + +Currently, artifact is generated on x86-64 is published. +**Therefore, the artifact should work on any linux distribution running on x86-64 plarform and having glibc version >= 2.17.** ### Maintainers * [Kumar Pratyush](https://github.com/kpratyus), Cisco * [Debajit Das](https://github.com/DebajitDas), Cisco +### Blogs +* [Instrument Apache HttpServer with OpenTelemetry](https://opentelemetry.io/blog/2022/instrument-apache-httpd-server/) + diff --git a/instrumentation/otel-webserver-module/conf/nginx/nginx.conf b/instrumentation/otel-webserver-module/conf/nginx/nginx.conf new file mode 100644 index 000000000..7887f6309 --- /dev/null +++ b/instrumentation/otel-webserver-module/conf/nginx/nginx.conf @@ -0,0 +1,34 @@ + +user nginx; +worker_processes 1; + +error_log /var/log/nginx/error.log warn; +pid /var/run/nginx.pid; + +load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so; + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + include /etc/nginx/conf.d/*.conf; +include /opt/opentelemetry_module.conf; +} From 9aee4bcb9233987d948bc224449f59a0358b71f5 Mon Sep 17 00:00:00 2001 From: Miguel Alexandre Date: Tue, 26 Jul 2022 14:57:29 +0200 Subject: [PATCH 12/77] nginx: fix worker process death in internal requests and 301's (#190) Fix frequent core dumps on 301's and internal requests --- instrumentation/nginx/src/otel_ngx_module.cpp | 29 +++++++++++------ instrumentation/nginx/test/conf/nginx.conf | 24 ++++++++++++++ instrumentation/nginx/test/data/trace.json | 2 ++ .../test/instrumentation_test.exs | 31 ++++++++++++++++++- 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/instrumentation/nginx/src/otel_ngx_module.cpp b/instrumentation/nginx/src/otel_ngx_module.cpp index 30c15ebd4..c8b24efe7 100644 --- a/instrumentation/nginx/src/otel_ngx_module.cpp +++ b/instrumentation/nginx/src/otel_ngx_module.cpp @@ -190,17 +190,21 @@ TraceContext* GetTraceContext(ngx_http_request_t* req) { ngx_http_variable_value_t* val = ngx_http_get_indexed_variable(req, otel_ngx_variables[0].index); if (val == nullptr || val->not_found) { - ngx_log_error(NGX_LOG_ERR, req->connection->log, 0, "TraceContext not found"); + ngx_log_error(NGX_LOG_INFO, req->connection->log, 0, "TraceContext not found"); return nullptr; } std::unordered_map* map = (std::unordered_map*)val->data; -auto it = map->find(req); -if (it != map->end()) { - return it->second; -} -ngx_log_error(NGX_LOG_ERR, req->connection->log, 0, "TraceContext not found"); -return nullptr; + if (map == nullptr){ + ngx_log_error(NGX_LOG_INFO, req->connection->log, 0, "TraceContext not found"); + return nullptr; + } + auto it = map->find(req); + if (it != map->end()) { + return it->second; + } + ngx_log_error(NGX_LOG_INFO, req->connection->log, 0, "TraceContext not found"); + return nullptr; } nostd::string_view WithoutOtelVarPrefix(ngx_str_t value) { @@ -225,7 +229,7 @@ OtelGetTraceContextVar(ngx_http_request_t* req, ngx_http_variable_value_t* v, ui if (traceContext == nullptr || !traceContext->request_span) { ngx_log_error( - NGX_LOG_ERR, req->connection->log, 0, + NGX_LOG_INFO, req->connection->log, 0, "Unable to get trace context when expanding tracecontext var"); return NGX_OK; } @@ -265,7 +269,7 @@ OtelGetTraceId(ngx_http_request_t* req, ngx_http_variable_value_t* v, uintptr_t if (traceContext == nullptr || !traceContext->request_span) { ngx_log_error( - NGX_LOG_ERR, req->connection->log, 0, + NGX_LOG_INFO, req->connection->log, 0, "Unable to get trace context when getting trace id"); return NGX_OK; } @@ -320,7 +324,7 @@ OtelGetSpanId(ngx_http_request_t* req, ngx_http_variable_value_t* v, uintptr_t d if (traceContext == nullptr || !traceContext->request_span) { ngx_log_error( - NGX_LOG_ERR, req->connection->log, 0, + NGX_LOG_INFO, req->connection->log, 0, "Unable to get trace context when getting span id"); return NGX_OK; } @@ -432,6 +436,11 @@ ngx_int_t StartNgxSpan(ngx_http_request_t* req) { return NGX_DECLINED; } + // Internal requests must be called from another location in nginx, that should already have a trace. Without this check, a call would generate an extra (unrelated) span without much information + if (req->internal) { + return NGX_DECLINED; + } + ngx_http_variable_value_t* val = ngx_http_get_indexed_variable(req, otel_ngx_variables[0].index); if (!val) { diff --git a/instrumentation/nginx/test/conf/nginx.conf b/instrumentation/nginx/test/conf/nginx.conf index ceb127a4d..8da508660 100644 --- a/instrumentation/nginx/test/conf/nginx.conf +++ b/instrumentation/nginx/test/conf/nginx.conf @@ -99,6 +99,30 @@ http { try_files $uri =404; } + location /redirect_301/ { + # Requests on /redirect_301 should result in a redirect to /redirect_301/ + # The 301 redirect will not be traced because it happens at an earlier + # processing phase. So the variable will be null and the header should not + # be set. + # This covers an issue with the worker process crashing when the variable + # was used in a 301 request + # (https://github.com/open-telemetry/opentelemetry-cpp-contrib/issues/105) + add_header Trace-Id "$opentelemetry_trace_id"; + proxy_pass http://node-backend/off; + } + + location = /route_to_internal { + rewrite /route_to_internal /internal_request last; + } + + location = /internal_request { + # This covers an issue with the worker process crashing + # (https://github.com/open-telemetry/opentelemetry-cpp-contrib/issues/105) + add_header Trace-Id "$opentelemetry_trace_id"; + internal; + return 200 ""; + } + location ~ \.php$ { include /etc/nginx/fastcgi_params; root /var/www/html/php; diff --git a/instrumentation/nginx/test/data/trace.json b/instrumentation/nginx/test/data/trace.json index e69de29bb..e2d497509 100644 --- a/instrumentation/nginx/test/data/trace.json +++ b/instrumentation/nginx/test/data/trace.json @@ -0,0 +1,2 @@ +{"resourceSpans":[{"resource":{"attributes":[{"key":"telemetry.sdk.version","value":{"stringValue":"1.3.0"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.language","value":{"stringValue":"cpp"}},{"key":"service.name","value":{"stringValue":"nginx-proxy"}}]},"instrumentationLibrarySpans":[{"instrumentationLibrary":{"name":"nginx"},"spans":[{"traceId":"777151ac132afc1975887f8a3af71d23","spanId":"60bec6e1671cee32","parentSpanId":"","name":"otel_test","kind":"SPAN_KIND_SERVER","startTimeUnixNano":"1658331753935660143","endTimeUnixNano":"1658331753935827215","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.flavor","value":{"stringValue":"1.1"}},{"key":"http.target","value":{"stringValue":"/route_to_internal"}},{"key":"http.server_name","value":{"stringValue":"otel_test"}},{"key":"http.host","value":{"stringValue":"localhost:8000"}},{"key":"http.user_agent","value":{"stringValue":"curl/7.68.0"}},{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.host.port","value":{"intValue":"8000"}},{"key":"net.peer.ip","value":{"stringValue":"172.25.0.1"}},{"key":"net.peer.port","value":{"intValue":"51608"}},{"key":"test.attrib.global","value":{"stringValue":"global"}},{"key":"test.attrib.custom","value":{"stringValue":"global-custom"}}],"status":{}}]}]}]} +{"resourceSpans":[{"resource":{"attributes":[{"key":"telemetry.sdk.version","value":{"stringValue":"1.3.0"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.language","value":{"stringValue":"cpp"}},{"key":"service.name","value":{"stringValue":"nginx-proxy"}}]},"instrumentationLibrarySpans":[{"instrumentationLibrary":{"name":"nginx"},"spans":[{"traceId":"579d297c39ddac461fbc50febd77f16a","spanId":"fecfc6a8c9b60f03","parentSpanId":"","name":"otel_test","kind":"SPAN_KIND_SERVER","startTimeUnixNano":"1658331755134563590","endTimeUnixNano":"1658331755134700342","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.flavor","value":{"stringValue":"1.1"}},{"key":"http.target","value":{"stringValue":"/route_to_internal"}},{"key":"http.server_name","value":{"stringValue":"otel_test"}},{"key":"http.host","value":{"stringValue":"localhost:8000"}},{"key":"http.user_agent","value":{"stringValue":"curl/7.68.0"}},{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.host.port","value":{"intValue":"8000"}},{"key":"net.peer.ip","value":{"stringValue":"172.25.0.1"}},{"key":"net.peer.port","value":{"intValue":"51614"}},{"key":"test.attrib.global","value":{"stringValue":"global"}},{"key":"test.attrib.custom","value":{"stringValue":"global-custom"}}],"status":{}}]}]}]} diff --git a/instrumentation/nginx/test/instrumentation/test/instrumentation_test.exs b/instrumentation/nginx/test/instrumentation/test/instrumentation_test.exs index a5df8101d..706b360bb 100644 --- a/instrumentation/nginx/test/instrumentation/test/instrumentation_test.exs +++ b/instrumentation/nginx/test/instrumentation/test/instrumentation_test.exs @@ -85,7 +85,7 @@ defmodule InstrumentationTest do [il_spans] = resource_spans["instrumentationLibrarySpans"] il_spans["spans"] end - + def values(map) do Enum.map(map, fn {k, v} -> case k do @@ -490,4 +490,33 @@ defmodule InstrumentationTest do assert header_span_id == span["spanId"] assert status == 200 end + + test "Accessing 301 redirect does not crash", %{ + trace_file: trace_file + } do + %HTTPoison.Response{status_code: status, headers: headers} = + HTTPoison.get!( + "#{@host}/redirect_301", + [], + follow_redirect: false + ) + + assert status == 301 + + {_, header_location} = Enum.find(headers, fn {k, _} -> k == "Location" end) + assert header_location == "http://#{@host}/redirect_301/" + end + + test "Accessing internal request does not crash", %{ + trace_file: trace_file + } do + %HTTPoison.Response{status_code: status, headers: headers} = + HTTPoison.get!("#{@host}/route_to_internal") + + [trace] = read_traces(trace_file, 1) + [span] = collect_spans(trace) + {_, header_trace_id} = Enum.find(headers, fn {k, _} -> k == "Trace-Id" end) + assert header_trace_id == span["traceId"] + assert status == 200 + end end From f2d10670526c88d7484abb8f7306c944171b454c Mon Sep 17 00:00:00 2001 From: Andy Davies <219090+Pondidum@users.noreply.github.com> Date: Tue, 26 Jul 2022 16:38:04 +0300 Subject: [PATCH 13/77] nginx: add debian 11.3 support (#180) Co-authored-by: Siim Kallas --- .github/workflows/nginx.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nginx.yml b/.github/workflows/nginx.yml index 1d1da55d7..130fdd3e6 100644 --- a/.github/workflows/nginx.yml +++ b/.github/workflows/nginx.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - os: [ubuntu-20.04, ubuntu-18.04, debian-10.11] + os: [ubuntu-20.04, ubuntu-18.04, debian-10.11, debian-11.3] nginx-rel: [mainline, stable] steps: - name: checkout otel nginx From cfbffa5c489d06dea9804e40201e248af27dff09 Mon Sep 17 00:00:00 2001 From: Miguel Alexandre Date: Tue, 26 Jul 2022 18:35:33 +0200 Subject: [PATCH 14/77] Update nginx docs of opentelemetry_propagate (#166) Adds a caveat about the opentelemetry_propagate inheritance rules. --- instrumentation/nginx/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/instrumentation/nginx/README.md b/instrumentation/nginx/README.md index 57057a129..7a746c1c6 100644 --- a/instrumentation/nginx/README.md +++ b/instrumentation/nginx/README.md @@ -168,6 +168,8 @@ Set the operation name when starting a new span. Enable propagation of distributed tracing headers, e.g. `traceparent`. When no parent trace is given, a new trace will be started. The default propagator is W3C. +The same inheritance rules as [`proxy_set_header`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header) apply, which means this directive is applied at the current configuration level if and only if there are no `proxy_set_header` directives defined on a lower level. + - **required**: `false` - **syntax**: `opentelemetry_propagate` or `opentelemetry_propagate b3` - **block**: `http`, `server`, `location` From a8c67e2c35c4515bc2ef40461c34c5174a27732c Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Wed, 27 Jul 2022 12:50:05 +0530 Subject: [PATCH 15/77] Updating release version for otel webserver module (#197) --- .../otel-webserver-module/dist/VERSION.txt | 2 +- .../otel-webserver-module/dist/install.sh | 16 +++++----------- .../otel-webserver-module/version.properties | 2 +- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/instrumentation/otel-webserver-module/dist/VERSION.txt b/instrumentation/otel-webserver-module/dist/VERSION.txt index 6754eb3ef..7eb75ecb1 100644 --- a/instrumentation/otel-webserver-module/dist/VERSION.txt +++ b/instrumentation/otel-webserver-module/dist/VERSION.txt @@ -1 +1 @@ -${moduleVersion}${moduleRelease}-${headSHA1} +${moduleVersion}${moduleRelease} diff --git a/instrumentation/otel-webserver-module/dist/install.sh b/instrumentation/otel-webserver-module/dist/install.sh index 413e47c81..16c157b1d 100755 --- a/instrumentation/otel-webserver-module/dist/install.sh +++ b/instrumentation/otel-webserver-module/dist/install.sh @@ -1,12 +1,6 @@ #!/bin/sh -# -# -# Copyright 2014 AppDynamics. -# All rights reserved. -# -# -# Install script for AppDynamics WebServer agent -# +# Install script for WebServer Instrumentation + usage() { cat << EOF Usage: `basename $0` @@ -71,7 +65,7 @@ fatal_error() { log_error $1 cat >&2 </dev/null` install_log=/tmp/appd_install_${datestamp}.log rm -f $install_log > /dev/null 2>&1 cat > $install_log </dev/null` @@ -127,7 +121,7 @@ Environment: ################################################################################ EOF -echo "Install script for AppDynamics WebServer Agent ${agentVersionId}" +echo "Install script for WebServer Instrumentation ${agentVersionId}" # Check for SELinux getenforce=`which getenforce 2>/dev/null` diff --git a/instrumentation/otel-webserver-module/version.properties b/instrumentation/otel-webserver-module/version.properties index b8c3f2a9e..04a5e2d09 100644 --- a/instrumentation/otel-webserver-module/version.properties +++ b/instrumentation/otel-webserver-module/version.properties @@ -1,2 +1,2 @@ -server-module-version=1.0.0-rc1 +server-module-version=1.0.0 release=GA From 523c0dcf3ee3d4d06202d75a6035ec706fedf51c Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Fri, 29 Jul 2022 14:01:45 +0530 Subject: [PATCH 16/77] [otel-webserver-module] Update Readme with downloaded link (#200) * [otel-webserver-module] Update Readme with download link * updated readme * updated readme * updated readme * updated readme --- instrumentation/otel-webserver-module/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 510587b7c..83698e4a7 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -100,7 +100,9 @@ The build file can be copied at a suitable location in User's system by running ##### Download the artifact -The artifact can also be downloaded from [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) of the source repository. Click on any top successful workflow runs on main branch and the artifact would be available for download. +The artifact can also be downloaded from either of below links +- [Releases](https://github.com/open-telemetry/opentelemetry-cpp-contrib/releases) - Make sure to download from releases/tags having ```webserver/vXX.XX.XX``` e.g [webserver/v1.0.0](https://github.com/open-telemetry/opentelemetry-cpp-contrib/releases/tag/webserver%2Fv1.0.0) +- [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) - Click on any top successful workflow runs on main branch and the artifact would be available for download. ##### Installation Steps @@ -216,7 +218,9 @@ The build file can be copied at a suitable location in User's system by running ##### Download the artifact -The artifact can also be downloaded from [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) of the source repository. Click on any top successful workflow runs on main branch and the artifact would be available for download. +The artifact can also be downloaded from either of below links +- [Releases](https://github.com/open-telemetry/opentelemetry-cpp-contrib/releases) - Make sure to download from releases/tags having ```webserver/vXX.XX.XX``` e.g [webserver/v1.0.0](https://github.com/open-telemetry/opentelemetry-cpp-contrib/releases/tag/webserver%2Fv1.0.0) +- [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) - Click on any top successful workflow runs on main branch and the artifact would be available for download. ##### Installation Steps @@ -241,7 +245,7 @@ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/opentelemetry-webserver-sdk/sdk_lib ``` ### Usability of the downloaded artifact -The downloaded artifact from [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) is built on CentOS7. This contains shared libraries for both apache and nginx instrumentation. The shared libraries can be located at ```WebServerModule/Apache``` or ```WebServerModule/Nginx``` for respective webservers. But, the common libraries, related to opentelemetry, are located at ```sdk_lib/lib/``` which are used by both apache and nginx instrumentation. +The downloaded artifact from [Release/Tag](https://github.com/open-telemetry/opentelemetry-cpp-contrib/releases) or [GitHub Actions](https://github.com/open-telemetry/opentelemetry-cpp-contrib/actions/workflows/webserver.yml) is built on CentOS7. This contains shared libraries for both apache and nginx instrumentation. The shared libraries can be located at ```WebServerModule/Apache``` or ```WebServerModule/Nginx``` for respective webservers. But, the common libraries, related to opentelemetry, are located at ```sdk_lib/lib/``` which are used by both apache and nginx instrumentation. Currently, artifact is generated on x86-64 is published. **Therefore, the artifact should work on any linux distribution running on x86-64 plarform and having glibc version >= 2.17.** From 411b08954d0ae8d1618b1f18df14573a4a7e5570 Mon Sep 17 00:00:00 2001 From: Narasimha Date: Wed, 3 Aug 2022 10:40:40 +0530 Subject: [PATCH 17/77] Set server span attributes (#179) * Set span status according to http semantics * Set span status changes part-2 * Set span status according to http semantics spaces * Review comments addressed for span status * Moved error status from Apache hooks to Request processing engine * Fixed unit test failure * Setting server span attributes https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server-semantic-conventions * Setting server span attributes part2 https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-server-semantic-conventions * Set server span attributes part-3 * Removed unwanted lines * Unit test modified * Updating UT * Changing UT * Build failure * Disable Ubuntu UT * Update null check in UT * Modified attributes as per new spec * Modified UT * Update null check in UT * Modified attributes as per new spec * Modified UT * Disable ubuntu UT * Removed payload extra atrributes Co-authored-by: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> --- .github/workflows/webserver.yml | 6 +-- .../include/core/api/Payload.h | 26 +++++++++++ .../include/core/sdkwrapper/SdkConstants.h | 17 +++++++ .../src/apache/ApacheHooks.cpp | 44 +++++++++++++++++++ .../src/core/api/RequestProcessingEngine.cpp | 11 ++++- .../unit/RequestProcessingEngine_test.cpp | 33 +++++++++++--- 6 files changed, 126 insertions(+), 11 deletions(-) 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()); From c2bef81094d4f9d69ddbc36836134d87e38b1363 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Tue, 9 Aug 2022 11:59:18 +0530 Subject: [PATCH 18/77] Updated Readme (#203) --- instrumentation/otel-webserver-module/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 83698e4a7..ae31fa368 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -1,6 +1,6 @@ # otel-webserver-module -The OTEL webserver module comprises only Apache webserver module currently. Further support for Nginx webserver would be added in future. +The OTEL webserver module comprises of both Apache and Nginx instrumentation. ## Apache Webserver Module From f6e587415cb4baba9ed429430049e1e7cb2d28b8 Mon Sep 17 00:00:00 2001 From: Max Golovanov Date: Mon, 29 Aug 2022 12:07:08 -0700 Subject: [PATCH 19/77] Resolve compatibility issues with OpenTelemetry C++ SDK v1.6.0 (#207) --- exporters/fluentd/CHANGELOG.md | 27 +++++++++++++++++++ .../fluentd/cmake/opentelemetry-cpp.cmake | 2 +- .../example/fluentd-docker/fluent.conf | 13 ++++++--- .../exporters/fluentd/log/recordable.h | 10 +++---- .../exporters/fluentd/trace/recordable.h | 6 ++--- exporters/fluentd/src/trace/recordable.cc | 10 +++---- .../test/trace/fluentd_recordable_test.cc | 6 ++--- 7 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 exporters/fluentd/CHANGELOG.md diff --git a/exporters/fluentd/CHANGELOG.md b/exporters/fluentd/CHANGELOG.md new file mode 100644 index 000000000..fcdc2bd73 --- /dev/null +++ b/exporters/fluentd/CHANGELOG.md @@ -0,0 +1,27 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## Guideline to update the version + +Increment the: + +* MAJOR version when you make incompatible API/ABI changes, +* MINOR version when you add functionality in a backwards compatible manner, and +* PATCH version when you make backwards compatible bug fixes. + +## [1.2.0] 2022-08-29 + +* [EXPORTER] OpenTelemetry SDK v1.6.0 compatibility + +## [1.1.2] 2022-06-30 + +* [EXPORTER] OpenTelemetry SDK v1.4.0 compatibility + +## [1.1.1] 2022-03-16 + +* [EXPORTER] OpenTelemetry SDK v1.1.1 compatibility + diff --git a/exporters/fluentd/cmake/opentelemetry-cpp.cmake b/exporters/fluentd/cmake/opentelemetry-cpp.cmake index af4e6a20e..b89ca175c 100644 --- a/exporters/fluentd/cmake/opentelemetry-cpp.cmake +++ b/exporters/fluentd/cmake/opentelemetry-cpp.cmake @@ -1,5 +1,5 @@ if("${opentelemetry-cpp-tag}" STREQUAL "") - set(opentelemetry-cpp-tag "96534a7c2370099ada8bd9dcdc7236c76adf47d9") # OpenTelemetry C++ v1.4.1 + set(opentelemetry-cpp-tag "v1.6.0") endif() function(target_create _target _lib) add_library(${_target} STATIC IMPORTED) diff --git a/exporters/fluentd/example/fluentd-docker/fluent.conf b/exporters/fluentd/example/fluentd-docker/fluent.conf index b86bba727..f8e21e015 100644 --- a/exporters/fluentd/example/fluentd-docker/fluent.conf +++ b/exporters/fluentd/example/fluentd-docker/fluent.conf @@ -11,6 +11,10 @@ #### ## Source descriptions: ## +# Concurrent ingestion of OpenTelemetry logs and traces requires more than one system worker thread. + + workers 3 + ## built-in TCP input ## @see http://docs.fluentd.org/articles/in_forward @@ -22,10 +26,11 @@ ## built-in UNIX socket input - - @type unix - path /tmp/fluentd/log/socket.sock - +# Uncomment for Unix Domain socket support +# +# @type unix +# path /tmp/fluentd/log/socket.sock +# # HTTP input # POST http://localhost:8888/?json= diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h index 6d26f4d33..717966bb1 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h @@ -86,12 +86,12 @@ class Recordable final : public opentelemetry::sdk::logs::Recordable { opentelemetry::common::SystemTimestamp timestamp) noexcept override; /** - * Set instrumentation_library for this log. - * @param instrumentation_library the instrumentation library to set + * Set instrumentation_scope for this log. + * @param instrumentation_scope the instrumentation scope to set */ - void SetInstrumentationLibrary( - const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary - &instrumentation_library) noexcept override {} // Not Supported + void SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept override {} // Not Supported nlohmann::json &Log() { return json_; } diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/trace/recordable.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/trace/recordable.h index e716fef52..4b3fb8294 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/trace/recordable.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/trace/recordable.h @@ -67,9 +67,9 @@ class Recordable final : public sdk::trace::Recordable { void SetDuration(std::chrono::nanoseconds duration) noexcept override; - void SetInstrumentationLibrary( - const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary - &instrumentation_library) noexcept override; + void SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept override; private: std::string tag_; diff --git a/exporters/fluentd/src/trace/recordable.cc b/exporters/fluentd/src/trace/recordable.cc index 25c8a42f0..5c0a5ed9d 100644 --- a/exporters/fluentd/src/trace/recordable.cc +++ b/exporters/fluentd/src/trace/recordable.cc @@ -136,12 +136,12 @@ void Recordable::SetSpanKind( } } -void Recordable::SetInstrumentationLibrary( - const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary - &instrumentation_library) noexcept { - options_["tags"]["otel.library.name"] = instrumentation_library.GetName(); +void Recordable::SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept { + options_["tags"]["otel.library.name"] = instrumentation_scope.GetName(); options_["tags"]["otel.library.version"] = - instrumentation_library.GetVersion(); + instrumentation_scope.GetVersion(); } } // namespace trace diff --git a/exporters/fluentd/test/trace/fluentd_recordable_test.cc b/exporters/fluentd/test/trace/fluentd_recordable_test.cc index 0b27c929e..7739ad472 100644 --- a/exporters/fluentd/test/trace/fluentd_recordable_test.cc +++ b/exporters/fluentd/test/trace/fluentd_recordable_test.cc @@ -133,9 +133,9 @@ TEST(FluentdSpanRecordable, SetDuration) EXPECT_EQ(rec.span(), j_span); } -TEST(FluentdSpanRecordable, SetInstrumentationLibrary) +TEST(FluentdSpanRecordable, SetInstrumentationScope) { - using InstrumentationLibrary = opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary; + using InstrumentationScope = opentelemetry::sdk::instrumentationscope::InstrumentationScope; const char *library_name = "otel-cpp"; const char *library_version = "0.5.0"; @@ -143,7 +143,7 @@ TEST(FluentdSpanRecordable, SetInstrumentationLibrary) {"tags", {{"otel.library.name", library_name}, {"otel.library.version", library_version}}}}; opentelemetry::exporter::fluentd::trace::Recordable rec; - rec.SetInstrumentationLibrary(*InstrumentationLibrary::Create(library_name, library_version)); + rec.SetInstrumentationScope(*InstrumentationScope::Create(library_name, library_version)); EXPECT_EQ(rec.span(), j_span); } From 786c3ad68fcfd1115627ddaccd896d3293fbe548 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Tue, 6 Sep 2022 12:07:12 +0530 Subject: [PATCH 20/77] Downstream bug fix (#204) * Downstream bug fix * Indentation * Garbage collection * Removing unused variable --- .../src/nginx/ngx_http_opentelemetry_module.c | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 0c6b619cd..45d684ca7 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -721,15 +721,42 @@ static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* propagationHeaders, int count) { + ngx_list_part_t *part; + ngx_table_elt_t *header; ngx_table_elt_t *h; ngx_http_header_t *hh; ngx_http_core_main_conf_t *cmcf; + ngx_uint_t nelts; + + part = &r->headers_in.headers.part; + header = (ngx_table_elt_t*)part->elts; + nelts = part->nelts; for(int i=0; iheaders_in.headers); - if(h == NULL){ - return; + + int header_found=0; + for(ngx_uint_t j = 0; jkey.data)==0){ + + header_found=1; + + if(h->key.data) + ngx_pfree(r->pool, h->key.data); + if(h->value.data) + ngx_pfree(r->pool, h->value.data); + + break; + } + } + if(header_found==0) + { + h = ngx_list_push(&r->headers_in.headers); } + + if(h == NULL ) + return; + h->key.len = strlen(propagationHeaders[i].name); h->key.data = ngx_pcalloc(r->pool, sizeof(char)*((h->key.len)+1)); strcpy(h->key.data, propagationHeaders[i].name); @@ -750,6 +777,7 @@ static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* p } ngx_writeTrace(r->connection->log, __func__, "Value : %s", propagationHeaders[i].value); + } ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); From c44186c708b16b1bd4a7ea8f47fa49d509015725 Mon Sep 17 00:00:00 2001 From: SaschaBrechmannVHV <77098451+SaschaBrechmannVHV@users.noreply.github.com> Date: Wed, 28 Sep 2022 10:47:50 +0200 Subject: [PATCH 21/77] do not log name "mod_appdynamics" (#214) * do not log name "mod_appdynamics" Change Logoutput to "mod_opentelemetry_wbserver_sdk" * Typo mod_opentelemetry_wbserver_sdk => mod_opentelemetry_webserver_sdk --- .../otel-webserver-module/src/apache/ApacheTracing.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp index 16af8de42..a19ba70a4 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp @@ -47,7 +47,7 @@ void ApacheTracing::writeTrace(server_rec* s, const char* funcName, const char* if (m_state == TRACE_AS_ERROR && s) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_appdynamics: %s: %s", funcName, note); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_opentelemetry_webserver_sdk: %s: %s", funcName, note); } else if (m_state == UNINITIALIZED) { @@ -69,7 +69,7 @@ void ApacheTracing::writeError(server_rec* s, const char* funcName, const char* if (s && funcName) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_appdynamics: %s: %s", funcName, note); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "mod_opentelemetry_webserver_sdk: %s: %s", funcName, note); } } From 05b755ba439b56b59df51bc373961365f52d0c80 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Thu, 6 Oct 2022 00:36:55 +0800 Subject: [PATCH 22/77] Add `PrometheusPushExporter` (#213) --- .github/workflows/prometheus.yml | 111 ++++++++++ exporters/prometheus/.bazelrc | 24 +++ exporters/prometheus/BUILD | 54 +++++ exporters/prometheus/CMakeLists.txt | 201 ++++++++++++++++++ exporters/prometheus/README.md | 46 ++++ exporters/prometheus/WORKSPACE | 30 +++ .../exporters/prometheus/push_exporter.h | 128 +++++++++++ .../opentelemetry-cpp-contrib-config.cmake.in | 36 ++++ exporters/prometheus/repository.bzl | 67 ++++++ exporters/prometheus/src/push_exporter.cc | 112 ++++++++++ exporters/prometheus/test/CMakeLists.txt | 15 ++ .../prometheus/test/prometheus_test_helper.h | 195 +++++++++++++++++ .../prometheus/test/push_exporter_test.cc | 149 +++++++++++++ 13 files changed, 1168 insertions(+) create mode 100644 .github/workflows/prometheus.yml create mode 100644 exporters/prometheus/.bazelrc create mode 100644 exporters/prometheus/BUILD create mode 100644 exporters/prometheus/CMakeLists.txt create mode 100644 exporters/prometheus/README.md create mode 100644 exporters/prometheus/WORKSPACE create mode 100644 exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h create mode 100644 exporters/prometheus/opentelemetry-cpp-contrib-config.cmake.in create mode 100644 exporters/prometheus/repository.bzl create mode 100644 exporters/prometheus/src/push_exporter.cc create mode 100644 exporters/prometheus/test/CMakeLists.txt create mode 100644 exporters/prometheus/test/prometheus_test_helper.h create mode 100644 exporters/prometheus/test/push_exporter_test.cc diff --git a/.github/workflows/prometheus.yml b/.github/workflows/prometheus.yml new file mode 100644 index 000000000..cf9539e65 --- /dev/null +++ b/.github/workflows/prometheus.yml @@ -0,0 +1,111 @@ +name: prometheus instrumentation CI + +on: + push: + branches: "*" + paths: + - "exporters/prometheus/**" + - ".github/workflows/prometheus.yml" + pull_request: + branches: [main] + paths: + - "exporters/prometheus/**" + - ".github/workflows/prometheus.yml" + +jobs: + prometheus_bazel_linux: + name: Bazel on Linux + runs-on: ubuntu-latest + steps: + - name: checkout otel contrib prometheus + uses: actions/checkout@v3 + with: + path: "otel_cpp_contrib" + - name: Mount Bazel Cache + uses: actions/cache@v3 + env: + cache-name: bazel_cache + with: + path: /home/runner/.cache/bazel + key: bazel_test + - name: run tests + run: | + cd otel_cpp_contrib/exporters/prometheus + bazel --output_user_root=$HOME/.cache/bazel build --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... + bazel --output_user_root=$HOME/.cache/bazel test --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... + prometheus_bazel_osx: + name: Bazel on MacOS + runs-on: macos-latest + steps: + - name: checkout otel contrib prometheus + uses: actions/checkout@v3 + with: + path: "otel_cpp_contrib" + - name: Mount Bazel Cache + uses: actions/cache@v3 + env: + cache-name: bazel_cache + with: + path: /Users/runner/.cache/bazel + key: bazel_osx + - name: run tests + run: | + cd otel_cpp_contrib/exporters/prometheus + bazel --output_user_root=$HOME/.cache/bazel build --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... + bazel --output_user_root=$HOME/.cache/bazel test --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... + prometheus_bazel_window: + name: Bazel on Windows + runs-on: windows-latest + steps: + - name: checkout otel contrib prometheus + uses: actions/checkout@v3 + with: + path: "otel_cpp_contrib" + - name: run tests + shell: pwsh + run: | + New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" ` + -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force + $RUNNER_ROOT_PATH = Split-Path (Split-Path (Get-Location)) + Set-Location otel_cpp_contrib/exporters/prometheus + & bazel --windows_enable_symlinks "--output_user_root=$RUNNER_ROOT_PATH/bazel_build" ` + build --copt=-DENABLE_TEST --copt=/utf-8 --sandbox_debug --@io_opentelemetry_cpp//api:with_abseil //... + & bazel --windows_enable_symlinks "--output_user_root=$RUNNER_ROOT_PATH/bazel_build" ` + test --copt=-DENABLE_TEST --copt=/utf-8 --sandbox_debug --@io_opentelemetry_cpp//api:with_abseil //... + prometheus_cmake_linux: + name: CMake on Linux + runs-on: ubuntu-latest + steps: + - name: checkout otel contrib prometheus + uses: actions/checkout@v3 + with: + path: "otel_cpp_contrib" + - name: checkout otel cpp + uses: actions/checkout@v3 + with: + repository: "open-telemetry/opentelemetry-cpp" + ref: "v1.6.1" + path: "otel_cpp" + submodules: "recursive" + - name: setup + run: | + sudo apt update -y + sudo apt install -y --no-install-recommends --no-install-suggests build-essential\ + ca-certificates wget git valgrind lcov + - name: run tests + run: | + vcpkg install prometheus-cpp[pull,push] nlohmann-json GTest Benchmark --triplet=x64-linux + mkdir -p "$GITHUB_WORKSPACE/otel_cpp/build" + cd "$GITHUB_WORKSPACE/otel_cpp/build" + cmake .. -DWITH_PROMETHEUS=ON -DWITH_METRICS_PREVIEW=OFF -DCMAKE_BUILD_TYPE=Debug \ + -DVCPKG_TARGET_TRIPLET=x64-linux \ + "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" + cmake --build . -j --config Debug + cmake --install . --prefix "$HOME/prebuilt-otel" --config Debug + mkdir -p "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build" + cd "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build" + cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" -DCMAKE_BUILD_TYPE=Debug \ + -DVCPKG_TARGET_TRIPLET=x64-linux \ + "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" + cmake --build . -j --config Debug + ctest -VV -R "opentelemetry_cpp_ecosystem_test.*" . diff --git a/exporters/prometheus/.bazelrc b/exporters/prometheus/.bazelrc new file mode 100644 index 000000000..0225b106b --- /dev/null +++ b/exporters/prometheus/.bazelrc @@ -0,0 +1,24 @@ +# bazel configurations for running tests under sanitizers. +# Based on https://github.com/bazelment/trunk/blob/master/tools/bazel.rc + +# --config=asan : Address Sanitizer. +common:asan --copt -DADDRESS_SANITIZER +common:asan --copt -fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,null,return,returns-nonnull-attribute,shift-exponent,signed-integer-overflow,unreachable,vla-bound +common:asan --copt -fsanitize-address-use-after-scope +common:asan --copt -fno-sanitize-recover=all +common:asan --linkopt -fsanitize=address,bool,float-cast-overflow,integer-divide-by-zero,null,return,returns-nonnull-attribute,shift-exponent,signed-integer-overflow,unreachable,vla-bound +common:asan --linkopt -fsanitize-address-use-after-scope +common:asan --linkopt -fno-sanitize-recover=all +common:asan --cc_output_directory_tag=asan + +# --config=tsan : Thread Sanitizer. +common:tsan --copt -fsanitize=thread +common:tsan --copt -DTHREAD_SANITIZER +common:tsan --linkopt -fsanitize=thread +common:tsan --cc_output_directory_tag=tsan +# This is needed to address false positive problem with abseil.The same setting as gRPC +# https://github.com/google/sanitizers/issues/953 +common:tsan --test_env=TSAN_OPTIONS=report_atomic_races=0 + +# --config=legacy : GCC 4.8 +common:legacy --copt=-D__STDC_NO_ATOMICS__ --copt=-Wno-error=shadow --protocopt=--experimental_allow_proto3_optional diff --git a/exporters/prometheus/BUILD b/exporters/prometheus/BUILD new file mode 100644 index 000000000..0c25dab7e --- /dev/null +++ b/exporters/prometheus/BUILD @@ -0,0 +1,54 @@ +package(default_visibility = ["//visibility:public"]) + +cc_library( + name = "prometheus_push_exporter", + srcs = [ + "src/push_exporter.cc", + ], + hdrs = [ + "include/opentelemetry/exporters/prometheus/push_exporter.h", + ], + strip_include_prefix = "include", + tags = ["prometheus"], + deps = [ + "@com_github_jupp0r_prometheus_cpp//core", + "@com_github_jupp0r_prometheus_cpp//push", + "@io_opentelemetry_cpp//api", + "@io_opentelemetry_cpp//exporters/prometheus:prometheus_collector", + "@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter_utils", + "@io_opentelemetry_cpp//sdk:headers", + ], +) + +cc_library( + name = "prometheus_test_helper", + hdrs = [ + "test/prometheus_test_helper.h", + ], + tags = ["prometheus"], + deps = [ + "@io_opentelemetry_cpp//api", + "@io_opentelemetry_cpp//sdk:headers", + "@io_opentelemetry_cpp//sdk/src/trace", + ], +) + +cc_test( + name = "prometheus_push_exporter_test", + srcs = [ + "test/push_exporter_test.cc", + ], + tags = [ + "prometheus", + "test", + ], + deps = [ + ":prometheus_push_exporter", + ":prometheus_test_helper", + "@com_google_googletest//:gtest_main", + "@io_opentelemetry_cpp//api", + "@io_opentelemetry_cpp//exporters/prometheus:prometheus_collector", + "@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter_utils", + "@io_opentelemetry_cpp//sdk:headers", + ], +) diff --git a/exporters/prometheus/CMakeLists.txt b/exporters/prometheus/CMakeLists.txt new file mode 100644 index 000000000..bf8b702a7 --- /dev/null +++ b/exporters/prometheus/CMakeLists.txt @@ -0,0 +1,201 @@ +# Copyright 2022, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +cmake_minimum_required(VERSION 3.12) + +project( + opentelemetry-cpp-contrib + VERSION "1.6.1" # opentelemetry-cpp-contrib 1.6.1 + HOMEPAGE_URL "https://github.com/open-telemetry/opentelemetry-cpp-contrib" + LANGUAGES CXX) + +if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +endif() + +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +endif() + +if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") +endif() + +link_directories(${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + +find_package(opentelemetry-cpp REQUIRED) +find_package(prometheus-cpp CONFIG REQUIRED) + +get_target_property(OPENTELEMETRY_CPP_API_DEFINITIONS opentelemetry-cpp::api + INTERFACE_COMPILE_DEFINITIONS) +if(HAVE_ABSEIL IN_LIST OPENTELEMETRY_CPP_API_DEFINITIONS) + find_package(absl REQUIRED) +endif() + +if(HAVE_GSL IN_LIST OPENTELEMETRY_CPP_API_DEFINITIONS) + find_package(Microsoft.GSL REQUIRED) +endif() + +include_directories(include) +include(CMakeDependentOption) + +cmake_dependent_option(BUILD_TESTING "Enable tests" ON + "NOT CMAKE_CROSSCOMPILING" OFF) + +if(BUILD_TESTING) + enable_testing() + add_definitions(-DENABLE_TEST) + find_package(GTest) + include(GoogleTest) + + if(TARGET GTest::gtest) + set(OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_LIB_NAME GTest::gtest) + elseif(TARGET GTest::GTest) + set(OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_LIB_NAME GTest::GTest) + else() + set(OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_LIB_NAME ${GTEST_LIBRARIES}) + endif() + + if(TARGET GTest::gtest_main) + set(OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_MAIN_NAME GTest::gtest_main) + elseif(TARGET GTest::Main) + set(OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_MAIN_NAME GTest::Main) + else() + set(OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_MAIN_NAME ${GTEST_MAIN_LIBRARIES}) + endif() +endif() + +add_library(opentelemetry_prometheus_push_exporter src/push_exporter.cc) +set_target_properties(opentelemetry_prometheus_push_exporter + PROPERTIES EXPORT_NAME prometheus_push_exporter) + +target_include_directories( + opentelemetry_prometheus_push_exporter + PUBLIC "$" + "$") + +target_link_libraries( + opentelemetry_prometheus_push_exporter + PUBLIC opentelemetry-cpp::prometheus_exporter opentelemetry-cpp::metrics + opentelemetry-cpp::resources prometheus-cpp::push prometheus-cpp::core) + +if(DEFINED VCPKG_CMAKE_SYSTEM_NAME AND VCPKG_CMAKE_SYSTEM_NAME STREQUAL + "WindowsStore") + set(OPENTELEMETRY_CPP_CONTRIB_TARGET_IS_WINDOWS ON) +elseif(MINGW OR CMAKE_SYSTEM_NAME STREQUAL "MinGW") + set(OPENTELEMETRY_CPP_CONTRIB_TARGET_IS_WINDOWS ON) +elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(OPENTELEMETRY_CPP_CONTRIB_TARGET_IS_WINDOWS ON) +endif() +if(OPENTELEMETRY_CPP_CONTRIB_TARGET_IS_WINDOWS) + target_link_libraries( + opentelemetry_prometheus_push_exporter + PUBLIC advapi32 + bcrypt + iphlpapi + psapi + user32 + wsock32 + userenv + Ws2_32 + wldap32 + crypt32) +elseif(UNIX OR MINGW) + set(OPENTELEMETRY_CPP_CONTRIB_TEST_BACKUP_CMAKE_REQUIRED_LIBRARIES + ${CMAKE_REQUIRED_LIBRARIES}) + set(OPENTELEMETRY_CPP_CONTRIB_TEST_SYSTEM_LIBRARIES m dl pthread rt gcc gcc_s) + include(CheckCXXSourceCompiles) + + foreach(LIBNAME IN LISTS OPENTELEMETRY_CPP_CONTRIB_TEST_SYSTEM_LIBRARIES) + if(OPENTELEMETRY_CPP_CONTRIB_TEST_BACKUP_CMAKE_REQUIRED_LIBRARIES) + set(CMAKE_REQUIRED_LIBRARIES + "${OPENTELEMETRY_CPP_CONTRIB_TEST_BACKUP_CMAKE_REQUIRED_LIBRARIES};${LIBNAME}" + ) + else() + set(CMAKE_REQUIRED_LIBRARIES "${LIBNAME}") + endif() + string(TOUPPER "${LIBNAME}" OPENTELEMETRY_CPP_CONTRIB_TEST_NAME) + set(OPENTELEMETRY_CPP_CONTRIB_TEST_NAME + "OPENTELEMETRY_CPP_CONTRIB_TEST_LINK_${OPENTELEMETRY_CPP_CONTRIB_TEST_NAME}" + ) + check_cxx_source_compiles("#include + int main() { return 0; }" ${OPENTELEMETRY_CPP_CONTRIB_TEST_NAME}) + if(${OPENTELEMETRY_CPP_CONTRIB_TEST_NAME}) + list(APPEND OPENTELEMETRY_CPP_CONTRIB_SYSTEM_LIBRARIES "${LIBNAME}") + endif() + endforeach() + + unset(OPENTELEMETRY_CPP_CONTRIB_TEST_NAME) + if(OPENTELEMETRY_CPP_CONTRIB_TEST_BACKUP_CMAKE_REQUIRED_LIBRARIES) + set(CMAKE_REQUIRED_LIBRARIES + "${OPENTELEMETRY_CPP_CONTRIB_TEST_BACKUP_CMAKE_REQUIRED_LIBRARIES}") + else() + unset(CMAKE_REQUIRED_LIBRARIES) + endif() + + if(OPENTELEMETRY_CPP_CONTRIB_SYSTEM_LIBRARIES) + target_link_libraries(opentelemetry_prometheus_push_exporter + PUBLIC ${OPENTELEMETRY_CPP_CONTRIB_SYSTEM_LIBRARIES}) + endif() +endif() + +install( + TARGETS opentelemetry_prometheus_push_exporter + EXPORT "${PROJECT_NAME}-target" + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install( + DIRECTORY include/opentelemetry/exporters/prometheus + DESTINATION include/opentelemetry/exporters/ + FILES_MATCHING + PATTERN "*.h") + +if(BUILD_TESTING) + add_subdirectory(test) +endif() + +include(CMakePackageConfigHelpers) +file(MAKE_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}") + +configure_package_config_file( + "${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}-config.cmake.in" + "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" + NO_CHECK_REQUIRED_COMPONENTS_MACRO) + +write_basic_package_version_file( + "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake" + VERSION "${PROJECT_VERSION}${OPENTELEMETRY_CPP_ECOSYSTEM_VERSION_TWEAK}" + COMPATIBILITY SameMajorVersion) + +install( + FILES + "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake" + "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config-version.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + +export( + EXPORT "${PROJECT_NAME}-target" + NAMESPACE ${PROJECT_NAME}:: + FILE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-target.cmake" +) +install( + EXPORT "${PROJECT_NAME}-target" + NAMESPACE ${PROJECT_NAME}:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") diff --git a/exporters/prometheus/README.md b/exporters/prometheus/README.md new file mode 100644 index 000000000..4b052768e --- /dev/null +++ b/exporters/prometheus/README.md @@ -0,0 +1,46 @@ +# Prometheus Push Exporter for OpenTelemetry C++ + +## Installation + +### CMake Install Instructions + ++ Install opentelemetry-cpp with stable metric and prometheus exporter + +```bash +mkdir build_jobs +cd build_jobs +cmake -DCMAKE_PREFIX_PATH= .. + +cmake --build . -j +``` + +### Bazel Install Instructions + +`bazel build --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //...` + +## Usage + +Install the exporter on your application and pass the options. + +```cpp +#include + +opentelemetry::exporter::metrics::PrometheusPushExporterOptions options; +options.host = "localhost"; +options.port = "80"; +options.jobname = "jobname"; + +auto exporter = std::unique_ptr( + new opentelemetry::exporter::metrics::PrometheusPushExporter(options)); + +opentelemetry::sdk::metrics::PeriodicExportingMetricReaderOptions reader_options; +auto reader = std::unique_ptr( + new opentelemetry::sdk::metrics::PeriodicExportingMetricReader(std::move(exporter), options)); + +auto provider = nostd::shared_ptr( + new opentelemetry::sdk::metrics::MeterProvider()); +static_cast(provider.get())->AddMetricReader(std::move(reader)); + +// Set the global tracer provider +opentelemetry::metrics::Provider::SetMeterProvider(provider); +``` diff --git a/exporters/prometheus/WORKSPACE b/exporters/prometheus/WORKSPACE new file mode 100644 index 000000000..955b85663 --- /dev/null +++ b/exporters/prometheus/WORKSPACE @@ -0,0 +1,30 @@ +# Copyright 2022, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +workspace(name = "io_opentelemetry_cpp_contrib") + +# Load our direct dependencies. +load("//:repository.bzl", "io_opentelemetry_cpp_contrib_deps") + +io_opentelemetry_cpp_contrib_deps() + +load("@io_opentelemetry_cpp//bazel:repository.bzl", "opentelemetry_cpp_deps") + +# Load dependencies of opentelemetry-cpp +opentelemetry_cpp_deps() + +# Load prometheus C++ dependencies. +load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories") + +prometheus_cpp_repositories() diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h new file mode 100644 index 000000000..3d6151475 --- /dev/null +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h @@ -0,0 +1,128 @@ +// Copyright 2022, OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +# ifdef _WIN32 +# include // NOLINT +# include // NOLINT +# else +# include // NOLINT +# endif + +# include +# include +# include +# include + +# include "prometheus/gateway.h" + +# include "opentelemetry/exporters/prometheus/collector.h" +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/sdk/common/env_variables.h" +# include "opentelemetry/sdk/metrics/metric_exporter.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace metrics { +/** + * Struct to hold Prometheus exporter options. + */ +struct PrometheusPushExporterOptions { + std::string host; + std::string port; + std::string jobname; + ::prometheus::Labels labels; + std::string username; + std::string password; + + ::opentelemetry::sdk::metrics::AggregationTemporality aggregation_temporality = + ::opentelemetry::sdk::metrics::AggregationTemporality::kDelta; +}; + +class PrometheusPushExporter : public ::opentelemetry::sdk::metrics::MetricExporter { + public: + /** + * Constructor - binds an exposer and collector to the exporter + * @param options: options for an exposer that exposes + * an HTTP endpoint for the exporter to connect to + */ + explicit PrometheusPushExporter(const PrometheusPushExporterOptions &options); + + /** + * Get the AggregationTemporality for Prometheus exporter + * + * @return AggregationTemporality + */ + ::opentelemetry::sdk::metrics::AggregationTemporality GetAggregationTemporality( + ::opentelemetry::sdk::metrics::InstrumentType instrument_type) const noexcept override; + + /** + * Exports a batch of Metric Records. + * @param records: a collection of records to export + * @return: returns a ReturnCode detailing a success, or type of failure + */ + ::opentelemetry::sdk::common::ExportResult Export( + const ::opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept override; + + /** + * Force flush the exporter. + */ + bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; + + /** + * Shuts down the exporter and does cleanup. + * Since Prometheus is a pull based interface, + * we cannot serve data remaining in the intermediate + * collection to to client an HTTP request being sent, + * so we flush the data. + */ + bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept override; + + /** + * @return: returns a shared_ptr to + * the PrometheusCollector instance + */ + std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector> &GetCollector(); + + /** + * @return: Gets the shutdown status of the exporter + */ + bool IsShutdown() const; + + private: + // The configuration options associated with this exporter. + const PrometheusPushExporterOptions options_; + /** + * exporter shutdown status + */ + bool is_shutdown_; + + /** + * Pointer to a + * PrometheusCollector instance + */ + std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector> collector_; + + /** + * Pointer to an + * Gateway instance + */ + std::unique_ptr<::prometheus::Gateway> gateway_; + + /** + * friend class for testing + */ + friend class PrometheusPushExporterTest; + + /** + * PrometheusPushExporter constructor with no parameters + * Used for testing only + */ + PrometheusPushExporter(); +}; + +} // namespace metrics +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/opentelemetry-cpp-contrib-config.cmake.in b/exporters/prometheus/opentelemetry-cpp-contrib-config.cmake.in new file mode 100644 index 000000000..3aadecb89 --- /dev/null +++ b/exporters/prometheus/opentelemetry-cpp-contrib-config.cmake.in @@ -0,0 +1,36 @@ +# .rst: opentelemetry-cpp-contrib.cmake +# -------- +# +# Find the native opentelemetry-cpp-contrib includes and library. +# +# ============================================================================= +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +# ============================================================================= +# (To distribute this file outside of CMake, substitute the full License text +# for the above reference.) + +set(${CMAKE_FIND_PACKAGE_NAME}_VERSION "@PROJECT_VERSION@") + +@PACKAGE_INIT@ + +# ############################################################################## +# ${CMAKE_FIND_PACKAGE_NAME} source dir + +set_and_check(${CMAKE_FIND_PACKAGE_NAME}_INCLUDE_DIRS + "@PACKAGE_INCLUDE_INSTALL_DIR@") +set_and_check(${CMAKE_FIND_PACKAGE_NAME}_LIBRARY_DIRS + "@PACKAGE_CMAKE_INSTALL_LIBDIR@") + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-target.cmake") + +# check_required_components(${CMAKE_FIND_PACKAGE_NAME}) diff --git a/exporters/prometheus/repository.bzl b/exporters/prometheus/repository.bzl new file mode 100644 index 000000000..6c6ef227e --- /dev/null +++ b/exporters/prometheus/repository.bzl @@ -0,0 +1,67 @@ +# Copyright 2022, OpenTelemetry Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe") +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +def io_opentelemetry_cpp_contrib_deps(): + maybe( + http_archive, + name = "io_opentelemetry_cpp", + sha256 = "1fc371be049b3220b8b9571c8b713f03e9a84f3c5684363f64ccc814638391a5", + strip_prefix = "opentelemetry-cpp-1.6.1", + urls = [ + "https://github.com/open-telemetry/opentelemetry-cpp/archive/v1.6.1.tar.gz", + ], + ) + + # C++ Prometheus Client library. + maybe( + http_archive, + name = "com_github_jupp0r_prometheus_cpp", + sha256 = "593e028d401d3298eada804d252bc38d8cab3ea1c9e88bcd72095281f85e6d16", + strip_prefix = "prometheus-cpp-1.0.1", + urls = [ + "https://github.com/jupp0r/prometheus-cpp/archive/refs/tags/v1.0.1.tar.gz", + ], + ) + + # Abseil cpp + # Please use 20200225.3 and enable patches below when using gcc 4.8-4.9 + maybe( + http_archive, + name = "com_google_absl", + sha256 = "91ac87d30cc6d79f9ab974c51874a704de9c2647c40f6932597329a282217ba8", + strip_prefix = "abseil-cpp-20220623.1", + urls = [ + "https://github.com/abseil/abseil-cpp/archive/20220623.1.tar.gz", + # "https://github.com/abseil/abseil-cpp/archive/20200225.3.tar.gz", + ], + ) + + # GoogleTest framework. + # Only needed for tests, not to build the OpenTelemetry library. + # Please use 1.10.0 when using gcc 4.8-4.9 + maybe( + http_archive, + name = "com_google_googletest", + sha256 = "81964fe578e9bd7c94dfdb09c8e4d6e6759e19967e397dbea48d1c10e45d0df2", + strip_prefix = "googletest-release-1.12.1", + # sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb", + # strip_prefix = "googletest-release-1.10.0", + urls = [ + "https://github.com/google/googletest/archive/release-1.12.1.tar.gz", + # "https://github.com/google/googletest/archive/release-1.10.0.tar.gz", + ], + ) diff --git a/exporters/prometheus/src/push_exporter.cc b/exporters/prometheus/src/push_exporter.cc new file mode 100644 index 000000000..1a4ca1a61 --- /dev/null +++ b/exporters/prometheus/src/push_exporter.cc @@ -0,0 +1,112 @@ +// Copyright 2022, OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +# include "opentelemetry/exporters/prometheus/push_exporter.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace exporter { +namespace metrics { +/** + * Constructor - binds an exposer and collector to the exporter + * @param address: an address for an exposer that exposes + * an HTTP endpoint for the exporter to connect to + */ +PrometheusPushExporter::PrometheusPushExporter(const PrometheusPushExporterOptions &options) + : options_(options), is_shutdown_(false) { + gateway_ = std::unique_ptr<::prometheus::Gateway>(new ::prometheus::Gateway{ + options_.host, options_.port, options_.jobname, options_.labels, options_.username, options_.password}); + collector_ = std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector>( + new ::opentelemetry::exporter::metrics::PrometheusCollector); + + gateway_->RegisterCollectable(collector_); +} + +/** + * PrometheusPushExporter constructor with no parameters + * Used for testing only + */ +PrometheusPushExporter::PrometheusPushExporter() : is_shutdown_(false) { + collector_ = std::unique_ptr<::opentelemetry::exporter::metrics::PrometheusCollector>( + new ::opentelemetry::exporter::metrics::PrometheusCollector(3)); +} + +::opentelemetry::sdk::metrics::AggregationTemporality PrometheusPushExporter::GetAggregationTemporality( + ::opentelemetry::sdk::metrics::InstrumentType instrument_type) const noexcept { + if (options_.aggregation_temporality == ::opentelemetry::sdk::metrics::AggregationTemporality::kCumulative) { + return options_.aggregation_temporality; + } + + switch (instrument_type) { + case ::opentelemetry::sdk::metrics::InstrumentType::kCounter: + case ::opentelemetry::sdk::metrics::InstrumentType::kObservableCounter: + case ::opentelemetry::sdk::metrics::InstrumentType::kHistogram: + case ::opentelemetry::sdk::metrics::InstrumentType::kObservableGauge: + return ::opentelemetry::sdk::metrics::AggregationTemporality::kDelta; + case ::opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter: + case ::opentelemetry::sdk::metrics::InstrumentType::kObservableUpDownCounter: + return ::opentelemetry::sdk::metrics::AggregationTemporality::kCumulative; + } + return ::opentelemetry::sdk::metrics::AggregationTemporality::kUnspecified; +} + +/** + * Exports a batch of Metric Records. + * @param records: a collection of records to export + * @return: returns a ReturnCode detailing a success, or type of failure + */ +::opentelemetry::sdk::common::ExportResult PrometheusPushExporter::Export( + const ::opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept { + if (is_shutdown_) { + return ::opentelemetry::sdk::common::ExportResult::kFailure; + } else if (collector_->GetCollection().size() + data.scope_metric_data_.size() > + static_cast(collector_->GetMaxCollectionSize())) { + return ::opentelemetry::sdk::common::ExportResult::kFailureFull; + } else if (data.scope_metric_data_.empty()) { + return ::opentelemetry::sdk::common::ExportResult::kFailureInvalidArgument; + } else { + collector_->AddMetricData(data); + if (gateway_) { + int http_code = gateway_->Push(); + if (http_code >= 200 && http_code < 300) { + return ::opentelemetry::sdk::common::ExportResult::kSuccess; + } + return ::opentelemetry::sdk::common::ExportResult::kFailure; + } + return ::opentelemetry::sdk::common::ExportResult::kSuccess; + } +} + +bool PrometheusPushExporter::ForceFlush(std::chrono::microseconds timeout) noexcept { return true; } + +/** + * Shuts down the exporter and does cleanup. + * Since Prometheus is a pull based interface, + * we cannot serve data remaining in the intermediate + * collection to to client an HTTP request being sent, + * so we flush the data. + */ +bool PrometheusPushExporter::Shutdown(std::chrono::microseconds timeout) noexcept { + is_shutdown_ = true; + + collector_->GetCollection().clear(); + + return true; +} + +/** + * @return: returns a shared_ptr to + * the PrometheusCollector instance + */ +std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector> &PrometheusPushExporter::GetCollector() { + return collector_; +} + +/** + * @return: Gets the shutdown status of the exporter + */ +bool PrometheusPushExporter::IsShutdown() const { return is_shutdown_; } + +} // namespace metrics +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/CMakeLists.txt b/exporters/prometheus/test/CMakeLists.txt new file mode 100644 index 000000000..65c37f2c2 --- /dev/null +++ b/exporters/prometheus/test/CMakeLists.txt @@ -0,0 +1,15 @@ +foreach(testname push_exporter_test) + add_executable(${testname} "${testname}.cc") + target_link_libraries( + ${testname} + ${OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_LIB_NAME} + ${OPENTELEMETRY_CPP_CONTRIB_GTEST_LINK_MAIN_NAME} + opentelemetry_prometheus_push_exporter + prometheus-cpp::push + ${CMAKE_THREAD_LIBS_INIT} + ${ATFRAMEWORK_CMAKE_TOOLSET_SYSTEM_LIBRARIES}) + gtest_discover_tests( + ${testname} + TEST_PREFIX opentelemetry_cpp_ecosystem_test.exporter.prometheus. + TEST_LIST prometheus_exporter_test) +endforeach() diff --git a/exporters/prometheus/test/prometheus_test_helper.h b/exporters/prometheus/test/prometheus_test_helper.h new file mode 100644 index 000000000..fbc6b7bb6 --- /dev/null +++ b/exporters/prometheus/test/prometheus_test_helper.h @@ -0,0 +1,195 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +# include +# include + +# include "opentelemetry/version.h" + +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace nostd = opentelemetry::nostd; +namespace exportermetrics = opentelemetry::exporter::metrics; + +namespace { // NOLINT +/** + * Helper function to create ResourceMetrics + */ +inline metric_sdk::ResourceMetrics CreateSumPointData() { + metric_sdk::SumPointData sum_point_data{}; + sum_point_data.value_ = 10.0; + metric_sdk::SumPointData sum_point_data2{}; + sum_point_data2.value_ = 20.0; + metric_sdk::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto instrumentation_scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + metric_sdk::MetricData metric_data{ + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentValueType::kDouble}, + metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, + opentelemetry::common::SystemTimestamp{}, + std::vector{{metric_sdk::PointAttributes{{"a1", "b1"}}, sum_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, sum_point_data2}}}; + data.scope_metric_data_ = std::vector{ + {instrumentation_scope.get(), std::vector{metric_data}}}; + return data; +} + +inline metric_sdk::ResourceMetrics CreateHistogramPointData() { + metric_sdk::HistogramPointData histogram_point_data{}; + histogram_point_data.boundaries_ = std::list{10.1, 20.2, 30.2}; + histogram_point_data.count_ = 3; + histogram_point_data.counts_ = {200, 300, 400, 500}; + histogram_point_data.sum_ = 900.5; + metric_sdk::HistogramPointData histogram_point_data2{}; + histogram_point_data2.boundaries_ = std::list{10, 20, 30}; // NOLINT + histogram_point_data2.count_ = 3; + histogram_point_data2.counts_ = {200, 300, 400, 500}; + histogram_point_data2.sum_ = 900l; + metric_sdk::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto instrumentation_scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + metric_sdk::MetricData metric_data{ + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kHistogram, + metric_sdk::InstrumentValueType::kDouble}, + metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, + opentelemetry::common::SystemTimestamp{}, + std::vector{{metric_sdk::PointAttributes{{"a1", "b1"}}, histogram_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, histogram_point_data2}}}; + data.scope_metric_data_ = std::vector{ + {instrumentation_scope.get(), std::vector{metric_data}}}; + return data; +} + +inline metric_sdk::ResourceMetrics CreateLastValuePointData() { + metric_sdk::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto instrumentation_scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + metric_sdk::LastValuePointData last_value_point_data{}; + last_value_point_data.value_ = 10.0; + last_value_point_data.is_lastvalue_valid_ = true; + last_value_point_data.sample_ts_ = opentelemetry::common::SystemTimestamp{}; + metric_sdk::LastValuePointData last_value_point_data2{}; + last_value_point_data2.value_ = 20l; + last_value_point_data2.is_lastvalue_valid_ = true; + last_value_point_data2.sample_ts_ = opentelemetry::common::SystemTimestamp{}; + metric_sdk::MetricData metric_data{ + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentValueType::kDouble}, + metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, + opentelemetry::common::SystemTimestamp{}, + std::vector{ + {metric_sdk::PointAttributes{{"a1", "b1"}}, last_value_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, last_value_point_data2}}}; + data.scope_metric_data_ = std::vector{ + {instrumentation_scope.get(), std::vector{metric_data}}}; + return data; +} + +inline metric_sdk::ResourceMetrics CreateDropPointData() { + metric_sdk::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto instrumentation_scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + metric_sdk::DropPointData drop_point_data{}; + metric_sdk::DropPointData drop_point_data2{}; + metric_sdk::MetricData metric_data{ + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentValueType::kDouble}, + metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, + opentelemetry::common::SystemTimestamp{}, + std::vector{{metric_sdk::PointAttributes{{"a1", "b1"}}, drop_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, drop_point_data2}}}; + data.scope_metric_data_ = std::vector{ + {instrumentation_scope.get(), std::vector{metric_data}}}; + return data; +} +} // namespace + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk { +namespace metrics { +inline bool operator==(const metric_sdk::MetricData &lhs, const metric_sdk::MetricData &rhs) { + if (lhs.start_ts != rhs.start_ts) { + return false; + } + if (lhs.end_ts != rhs.end_ts) { + return false; + } + + if (lhs.instrument_descriptor.description_ != rhs.instrument_descriptor.description_) { + return false; + } + if (lhs.instrument_descriptor.name_ != rhs.instrument_descriptor.name_) { + return false; + } + if (lhs.instrument_descriptor.type_ != rhs.instrument_descriptor.type_) { + return false; + } + if (lhs.instrument_descriptor.unit_ != rhs.instrument_descriptor.unit_) { + return false; + } + if (lhs.instrument_descriptor.value_type_ != rhs.instrument_descriptor.value_type_) { + return false; + } + + if (lhs.point_data_attr_.size() != rhs.point_data_attr_.size()) { + return false; + } + for (uint32_t idx = 0; idx < lhs.point_data_attr_.size(); ++idx) { + if (lhs.point_data_attr_.at(idx).attributes != rhs.point_data_attr_.at(idx).attributes) { + return false; + } + auto &lhs_point_data = lhs.point_data_attr_.at(idx).point_data; + auto &rhs_point_data = rhs.point_data_attr_.at(idx).point_data; + if (nostd::holds_alternative(lhs_point_data)) { + if (nostd::get(lhs_point_data).value_ != + nostd::get(rhs_point_data).value_) { + return false; + } + } else if (nostd::holds_alternative(lhs_point_data)) { + if (!nostd::holds_alternative(rhs_point_data)) { + return false; + } + } else if (nostd::holds_alternative(lhs_point_data)) { + auto &lhs_histogram_d = nostd::get(lhs_point_data); + auto &rhs_histogram_d = nostd::get(rhs_point_data); + if (lhs_histogram_d.count_ != rhs_histogram_d.count_) { + return false; + } + if (lhs_histogram_d.counts_ != rhs_histogram_d.counts_) { + return false; + } + if (lhs_histogram_d.boundaries_ != rhs_histogram_d.boundaries_) { + return false; + } + if (lhs_histogram_d.sum_ != rhs_histogram_d.sum_) { + return false; + } + } else if (nostd::holds_alternative(lhs_point_data)) { + auto &lhs_last_value_d = nostd::get(lhs_point_data); + auto &rhs_last_value_d = nostd::get(rhs_point_data); + if (lhs_last_value_d.is_lastvalue_valid_ != rhs_last_value_d.is_lastvalue_valid_) { + return false; + } + if (lhs_last_value_d.sample_ts_ != rhs_last_value_d.sample_ts_) { + return false; + } + if (lhs_last_value_d.value_ != rhs_last_value_d.value_) { + return false; + } + } + } + return true; +} +} // namespace metrics +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/push_exporter_test.cc b/exporters/prometheus/test/push_exporter_test.cc new file mode 100644 index 000000000..f070a677e --- /dev/null +++ b/exporters/prometheus/test/push_exporter_test.cc @@ -0,0 +1,149 @@ +// Copyright 2022, OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +# include + +# include +# include +# include +# include + +# include "opentelemetry/exporters/prometheus/collector.h" + +# include "opentelemetry/exporters/prometheus/push_exporter.h" +# include "prometheus_test_helper.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace metrics { +class PrometheusPushExporterTest { // : public ::testing::Test + public: + PrometheusPushExporter GetExporter() { return PrometheusPushExporter(); } +}; +} // namespace metrics +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE + +using opentelemetry::exporter::metrics::PrometheusCollector; +using opentelemetry::sdk::common::ExportResult; +using opentelemetry::exporter::metrics::PrometheusPushExporter; +using opentelemetry::exporter::metrics::PrometheusPushExporterTest; + +/** + * When a PrometheusPushExporter is initialized, + * isShutdown should be false. + */ +TEST(PrometheusPushExporter, InitializeConstructorIsNotShutdown) { + PrometheusPushExporterTest p; + PrometheusPushExporter exporter = p.GetExporter(); + + // // Asserts that the exporter is not shutdown. + ASSERT_TRUE(!exporter.IsShutdown()); +} + +/** + * The shutdown() function should set the isShutdown field to true. + */ +TEST(PrometheusPushExporter, ShutdownSetsIsShutdownToTrue) { + PrometheusPushExporterTest p; + PrometheusPushExporter exporter = p.GetExporter(); + + // exporter shuold not be shutdown by default + ASSERT_TRUE(!exporter.IsShutdown()); + + exporter.Shutdown(); + + // the exporter shuold be shutdown + ASSERT_TRUE(exporter.IsShutdown()); + + // shutdown function should be idempotent + exporter.Shutdown(); + ASSERT_TRUE(exporter.IsShutdown()); +} + +/** + * The Export() function should return kSuccess = 0 + * when data is exported successfully. + */ +TEST(PrometheusPushExporter, ExportSuccessfully) { + PrometheusPushExporterTest p; + PrometheusPushExporter exporter = p.GetExporter(); + + auto res = exporter.Export(CreateSumPointData()); + + // result should be kSuccess = 0 + ExportResult code = ExportResult::kSuccess; + ASSERT_EQ(res, code); +} + +/** + * If the exporter is shutdown, it cannot process + * any more export requests and returns kFailure = 1. + */ +TEST(PrometheusPushExporter, ExporterIsShutdown) { + PrometheusPushExporterTest p; + PrometheusPushExporter exporter = p.GetExporter(); + + exporter.Shutdown(); + + // send export request after shutdown + auto res = exporter.Export(CreateSumPointData()); + + // result code should be kFailure = 1 + ExportResult code = ExportResult::kFailure; + ASSERT_EQ(res, code); +} + +/** + * The Export() function should return + * kFailureFull = 2 when the collection is full, + * or when the collection is not full but does not have enough + * space to hold the batch data. + */ +TEST(PrometheusPushExporter, CollectionNotEnoughSpace) { + PrometheusPushExporterTest p; + PrometheusPushExporter exporter = p.GetExporter(); + + // prepare two collections of records to export, + // one close to max size and another one that, when added + // to the first, will exceed the size of the collection + + int max_collection_size = exporter.GetCollector()->GetMaxCollectionSize(); + + // send export request to fill the + // collection in the collector + ExportResult code = ExportResult::kSuccess; + for (int count = 1; count <= max_collection_size; ++count) { + auto res = exporter.Export(CreateSumPointData()); + ASSERT_EQ(res, code); + } + + // send export request that does not complete + // due to not enough space in the collection + auto res = exporter.Export(CreateSumPointData()); + + // the result code should be kFailureFull = 2 + code = ExportResult::kFailureFull; + ASSERT_EQ(res, code); +} + +/** + * The Export() function should return + * kFailureInvalidArgument = 3 when an empty collection + * of records is passed to the Export() function. + */ +TEST(PrometheusPushExporter, InvalidArgumentWhenPassedEmptyRecordCollection) { + PrometheusPushExporterTest p; + PrometheusPushExporter exporter = p.GetExporter(); + + // Initializes an empty colelction of records + metric_sdk::ResourceMetrics data; + + // send export request to fill the + // collection in the collector + auto res = exporter.Export(data); + + // the result code should be kFailureInvalidArgument = 3 + ExportResult code = ExportResult::kFailureInvalidArgument; + ASSERT_EQ(res, code); +} From c817ffc36a2e76e305dc87e7b1d09ef848eea39f Mon Sep 17 00:00:00 2001 From: Severin Neumann Date: Fri, 7 Oct 2022 08:28:53 +0200 Subject: [PATCH 23/77] Create README.md in instrumentation folder (#220) --- instrumentation/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 instrumentation/README.md diff --git a/instrumentation/README.md b/instrumentation/README.md new file mode 100644 index 000000000..5a50c71f0 --- /dev/null +++ b/instrumentation/README.md @@ -0,0 +1,9 @@ +# OpenTelemetry C++ instrumentations + +In this directory you will find instrumentation libraries and modules. + +| Name | Description | +|---|---| +| [httpd](./httpd) | httpd (Apache) OpenTelemetry module | +| [nginx](./nginx) | OpenTelemetry nginx module | +| [otel-webserver-module](./otel-webserver-module) | The OTEL webserver module comprises of both Apache and Nginx instrumentation. | From 39eb56348ca0e0f12c1cb9311e58f26ef1a07992 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Tue, 11 Oct 2022 12:01:58 +0530 Subject: [PATCH 24/77] Upgrade nginx instrumentation to support stable{1.22.0} and mainline{1.23.1} version. (#205) * Added some changes * Added support for multiple versions * Added dynamic build for nginx version * Removed unwanted changes * More update * Updated Dockerfile for centos7 and ubuntue --- .../otel-webserver-module/README.md | 7 +- .../otel-webserver-module/build.gradle | 133 ++++++++++-------- .../otel-webserver-module/docker-compose.yml | 2 +- .../docker/centos7/Dockerfile | 6 +- .../docker/ubuntu20.04/Dockerfile | 18 ++- .../src/nginx/ngx_http_opentelemetry_log.h | 2 +- .../src/nginx/ngx_http_opentelemetry_module.c | 5 +- .../otel-webserver-module/src/nginx/script.sh | 5 + .../otel-webserver-module/version.properties | 1 + 9 files changed, 109 insertions(+), 70 deletions(-) create mode 100755 instrumentation/otel-webserver-module/src/nginx/script.sh diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index ae31fa368..cf300c844 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -149,7 +149,7 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get | Library | Present Version | | ---------------------------------------------- | ----------- | -| Nginx | 1.18.0 | +| Nginx | 1.22.0, 1.23.0,1.23.1 | | Apr | 1.7.0 | | Apr-util | 1.6.1 | @@ -179,7 +179,8 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get - Docker Desktop should be installed on the system #### Platform Supported -- Supports only Nginx v1.18.0. +- Supports both stable(1.22.0) and mainline(1.23.1). +- Earlier support of v1.18.0 is deprecated. - The build is supported for **x86-64** platforms. - OS support: **Centos6**, **Centos7, ubuntu20.04**. @@ -235,7 +236,7 @@ Make sure to edit the directives values according to your need e.g NginxModuleOt Edit the nginx.conf to provide the reference to opentelemetry_module.conf and shared library. Please mind the order and location of the below entries by referring to ```conf/nginx/nginx.conf```. ``` -load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so; +load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx//ngx_http_opentelemetry_module.so; include /opt/opentelemetry_module.conf; ``` diff --git a/instrumentation/otel-webserver-module/build.gradle b/instrumentation/otel-webserver-module/build.gradle index ddbcf7c17..c07d8500d 100644 --- a/instrumentation/otel-webserver-module/build.gradle +++ b/instrumentation/otel-webserver-module/build.gradle @@ -1,5 +1,10 @@ +plugins { + id "de.undercouch.download" version "3.4.3" +} + apply plugin: 'cpp' apply from: 'common.gradle' +apply plugin: 'de.undercouch.download' def coverageEnabled = System.getenv('enableCoverage') def target_system = System.getProperty('targetSystem') ?: 'centos6' @@ -46,7 +51,7 @@ project.ext { apache22Version = "2.2.31" apache24Version = "2.4.23" - nginxVersion = '1.18.0' + nginxSupportedVersions=props.get("nginxSupportedVersions").split(',') libraryStageDir = "${platBuildDir}/opentelemetry-webserver-sdk" apacheStageDir = "${libraryStageDir}/WebServerModule/Apache" @@ -360,83 +365,98 @@ task assembleApacheModule(type: Tar) { } // NGINX -task extractNginx(type: Copy) { - from "build-dependencies" - into buildDir -} - -task configureNginx(type: Exec){ - group = 'OpenTelemetry module for Nginx' - description = 'Run configure to generate the build files for OpenTelemetry Module for Nginx' - - dependsOn extractNginx +nginxSupportedVersions.each { nginxVersion -> + task("downloadNginx${nginxVersion}", type: Download) { + src "http://nginx.org/download/nginx-${nginxVersion}.tar.gz" + dest buildDir + overwrite false + } - workingDir "${buildDir}/nginx-${nginxVersion}" - commandLine './configure', "--with-compat", "--with-cc-opt=-Wno-error -Wno-unused-variable -Wno-unused-but-set-variable", "--with-ld-opt=-L${libraryStageDir}/sdk_lib/lib", "--add-dynamic-module=${projectDir}/src/nginx" -} + task("extractNginx${nginxVersion}", type: Copy) { + dependsOn "downloadNginx${nginxVersion}" + from tarTree(resources.gzip("build/nginx-${nginxVersion}.tar.gz")) + into buildDir + } -task delMakefile(type: Exec){ - group = 'OpenTelemetry module for Nginx' - description = 'Deleting old Makefile' + task("configureNginx${nginxVersion}", type: Exec) { + group = 'OpenTelemetry module for Nginx' + description = 'Run configure to generate the build files for OpenTelemetry Module for Nginx' - workingDir "${buildDir}/nginx-${nginxVersion}/objs" - commandLine 'rm', '-rf', 'Makefile' -} + dependsOn "extractNginx${nginxVersion}" + workingDir "${buildDir}/nginx-${nginxVersion}" + commandLine './configure', "--with-compat", "--with-cc-opt=-Wno-error -Wno-unused-variable -Wno-unused-but-set-variable", "--with-ld-opt=-L${libraryStageDir}/sdk_lib/lib", "--add-dynamic-module=${projectDir}/src/nginx" + } -task copyMakefile(type: Copy){ - group = 'OpenTelemetry module for Nginx' - description = 'Copying Makefile for compiling Nginx Web Server Agent' + task("delMakefile${nginxVersion}", type: Exec) { + group = 'OpenTelemetry module for Nginx' + description = 'Deleting old Makefile' - dependsOn delMakefile + workingDir "${buildDir}/nginx-${nginxVersion}/objs" + commandLine 'rm', '-rf', 'Makefile' + } - from "src/nginx/Makefile" - into "${buildDir}/nginx-${nginxVersion}/objs/" -} + task("copyMakefile${nginxVersion}", type: Copy) { + group = 'OpenTelemetry module for Nginx' + description = 'Copying Makefile for compiling Nginx Web Server Agent' -task buildNginxModule(type: Exec) { - group = 'OpenTelemetry module for Nginx' - description = 'Build the Nginx Web Server Agent' + dependsOn "delMakefile${nginxVersion}" + from "src/nginx/Makefile" + into "${buildDir}/nginx-${nginxVersion}/objs/" + } - dependsOn configureNginx - dependsOn stageLibrary - dependsOn copyMakefile + task("updateMakefile${nginxVersion}", type: Exec) { + group = 'OpenTelemetry module for Nginx' + description = 'Updating the Makefile for dynamic build' - outputs.file "${buildDir}/nginx-${nginxVersion}/objs/ngx_http_opentelemetry_module.so" + commandLine 'bash', '-c', "src/nginx/script.sh ${buildDir}/nginx-${nginxVersion}/objs/Makefile" + } - workingDir "${buildDir}/nginx-${nginxVersion}" - commandLine 'make', 'modules' -} + task("buildNginxModule${nginxVersion}",type: Exec) { + group = 'OpenTelemetry module for Nginx' + description = 'Build the Nginx Web Server Agent' -task stageNginxModule(type: Copy) { - group = 'OpenTelemetry module for Nginx' - description = 'Stage the Nginx Web Server Agent distribution directory' + dependsOn "configureNginx${nginxVersion}" + dependsOn stageLibrary + dependsOn "updateMakefile${nginxVersion}" -// dependsOn stageLibrary + outputs.file "${buildDir}/nginx-${nginxVersion}/objs/ngx_http_opentelemetry_module.so" + workingDir "${buildDir}/nginx-${nginxVersion}" + commandLine 'make', 'modules' + } - from buildNginxModule - into nginxStageDir -} + task("stageNginxModule${nginxVersion}", type: Copy) { + group = 'OpenTelemetry module for Nginx' + description = 'Stage the Nginx Web Server Agent distribution directory' -task stripNginxModule(type: Exec){ - group = 'OpenTelemetry module for Nginx' - description = 'Strip the production Nginx Web Server Agent' + dependsOn "buildNginxModule${nginxVersion}" + def nginxStageDirVersion = "${nginxStageDir}/${nginxVersion}" + from "${buildDir}/nginx-${nginxVersion}/objs/ngx_http_opentelemetry_module.so" + into nginxStageDirVersion + } - dependsOn stageNginxModule + task("stripNginxModule${nginxVersion}", type: Exec) { + group = 'OpenTelemetry module for Nginx' + description = 'Strip the production Nginx Web Server Agent' - onlyIf { !debug } + dependsOn "stageNginxModule${nginxVersion}" + onlyIf { !debug } - inputs.dir stageNginxModule - outputs.file "${nginxStageDir}/ngx_http_opentelemetry_module.${sharedLibraryExt}" + inputs.dir "stageNginxModule${nginxVersion}" + outputs.file "${nginxStageDir}/${nginxVersion}/ngx_http_opentelemetry_module.${sharedLibraryExt}" - workingDir nginxStageDir - commandLine 'strip', '-x', "ngx_http_opentelemetry_module.${sharedLibraryExt}" + workingDir "${nginxStageDir}/${nginxVersion}" + commandLine 'strip', '-x', "ngx_http_opentelemetry_module.${sharedLibraryExt}" + } } task assembleNginxModule(type: Tar) { group = 'Nginx Web Server Module' description = 'Assemble the Nginx Web Server module artifact (tgz)' - dependsOn stripNginxModule + nginxSupportedVersions.each { + nginxVersion -> + dependsOn "stripNginxModule${nginxVersion}" + } from libraryStageDir baseName "opentelemetry-webserver-sdk-${osArch}-${osName}" @@ -451,7 +471,10 @@ task assembleWebServerModule(type: Tar) { description = 'Assemble the Web Server agent artifact (tgz)' dependsOn stripApacheModule - dependsOn stripNginxModule + nginxSupportedVersions.each { + nginxVersion -> + dependsOn "stripNginxModule${nginxVersion}" + } from libraryStageDir baseName "opentelemetry-webserver-sdk-${osArch}-${osName}" diff --git a/instrumentation/otel-webserver-module/docker-compose.yml b/instrumentation/otel-webserver-module/docker-compose.yml index 5ca22ce2b..8b2e431bf 100644 --- a/instrumentation/otel-webserver-module/docker-compose.yml +++ b/instrumentation/otel-webserver-module/docker-compose.yml @@ -98,7 +98,7 @@ services: - centos_nginx - centos7_nginx - ubuntu20.04_nginx - command: ["--config=/etc/otel-config.yml", "--log-level=DEBUG", "${OTELCOL_ARGS}"] + command: ["--config=/etc/otel-config.yml", "${OTELCOL_ARGS}"] volumes: - ./otel-config.yml:/etc/otel-config.yml ports: diff --git a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile index 1c5f14b3e..afd224ec5 100644 --- a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile @@ -26,7 +26,7 @@ ARG AUTOMAKE_VERSION="1.16.3" ARG PERL_VERSION="5.20.2" ARG PERL_CPANVERSION="5.0" ARG PCRE_VERSION="8.44" -ARG NGINX_VERSION="1.18.0" +ARG NGINX_VERSION="1.22.0" # create default non-root user RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser @@ -276,7 +276,7 @@ RUN echo '[nginx]' >> /etc/yum.repos.d/nginx.repo \ && echo 'baseurl=https://nginx.org/packages/centos/7/x86_64' >> /etc/yum.repos.d/nginx.repo \ && echo 'gpgcheck=0' >> /etc/yum.repos.d/nginx.repo \ && echo 'enabled=1' >> /etc/yum.repos.d/nginx.repo \ - && yum install nginx-1.18.0 -y + && yum install nginx-${NGINX_VERSION} -y RUN cd /otel-webserver-module/build \ && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \ @@ -290,7 +290,7 @@ RUN cd /otel-webserver-module/build \ && cd / RUN cp /otel-webserver-module/conf/nginx/opentelemetry_module.conf /opt/ \ - && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.22.0/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ && cd / diff --git a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile index ab84bfc8f..f694cd65d 100644 --- a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile @@ -38,7 +38,7 @@ ARG APRUTIL_VERSION="1.6.1" ARG LOG4CXX_VERSION="0.11.0" ARG GTEST_VERSION="1.10.0" ARG PCRE_VERSION="8.44" -ARG NGINX_VERSION="1.18.0" +ARG NGINX_VERSION="1.22.0" # Install GRPC RUN git clone --shallow-submodules --depth 1 --recurse-submodules -b v${GRPC_VERSION} \ @@ -180,7 +180,17 @@ RUN wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ && tar -xvf nginx-${NGINX_VERSION}.tar.gz -C /build-dependencies \ && rm -rf nginx-${NGINX_VERSION}.tar.gz -RUN apt-get install nginx -y +# Install Nginx stable version +RUN apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y \ + && curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \ + | tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null \ + && gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg; exit 0 +RUN echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \ + http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \ + | 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 # Build Webserver Module COPY . /otel-webserver-module @@ -203,8 +213,8 @@ RUN cd /otel-webserver-module/build \ RUN cd /otel-webserver-module/build \ && cp ../conf/nginx/opentelemetry_module.conf /opt/ \ - && sed -i '5i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ - && sed -i '64i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ + && sed -i '5i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.22.0/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ && cd /opt/opentelemetry-webserver-sdk \ && ./install.sh \ && cd / diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h index 1f2f6aa92..9df692435 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h @@ -15,9 +15,9 @@ */ -#include #include #include +#include #include /* diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 45d684ca7..63ede7543 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -14,13 +14,12 @@ * limitations under the License. */ +#include "ngx_http_opentelemetry_module.h" +#include "ngx_http_opentelemetry_log.h" #include #include #include -#include "ngx_http_opentelemetry_module.h" -#include "ngx_http_opentelemetry_log.h" - ngx_http_opentelemetry_worker_conf_t *worker_conf; static contextNode contexts[5]; static unsigned int c_count = 0; diff --git a/instrumentation/otel-webserver-module/src/nginx/script.sh b/instrumentation/otel-webserver-module/src/nginx/script.sh new file mode 100755 index 000000000..e6c3ef125 --- /dev/null +++ b/instrumentation/otel-webserver-module/src/nginx/script.sh @@ -0,0 +1,5 @@ +#!/bin/bash +fileName=$1 + +sed -i "s/-L\/otel-webserver-module\/build\/linux-x64\/opentelemetry-webserver-sdk\/sdk_lib\/lib\ -lopentelemetry_webserver_sdk\ -ldl\ -lpthread\ -lcrypt\ -lpcre\ -lz\ \\\/-L\/otel-webserver-module\/build\/linux-x64\/opentelemetry-webserver-sdk\/sdk_lib\/lib\ -lopentelemetry_webserver_sdk\ -ldl\ -lrt\ -lpthread\ -lcrypt\ -lpcre\ -lz\ \\\/g" $fileName +sed -i "s/-L\/otel-webserver-module\/build\/linux-x64\/opentelemetry-webserver-sdk\/sdk_lib\/lib\ \\\/-L\/otel-webserver-module\/build\/linux-x64\/opentelemetry-webserver-sdk\/sdk_lib\/lib\ -lopentelemetry_webserver_sdk\ \\\/g" $fileName diff --git a/instrumentation/otel-webserver-module/version.properties b/instrumentation/otel-webserver-module/version.properties index 04a5e2d09..cc32e12eb 100644 --- a/instrumentation/otel-webserver-module/version.properties +++ b/instrumentation/otel-webserver-module/version.properties @@ -1,2 +1,3 @@ server-module-version=1.0.0 release=GA +nginxSupportedVersions=1.22.0,1.23.0,1.23.1 From b14312b0511fc2d8ce327361457b7520f7c818c9 Mon Sep 17 00:00:00 2001 From: Emil Stolarsky Date: Fri, 14 Oct 2022 19:46:44 +0200 Subject: [PATCH 25/77] Add support for 'OTEL_SERVICE_NAME' environment variable (#221) * Add support for 'OTEL_SERVICE_NAME' environment variable * Show an example of how to configure OTLP when using the 'OTEL_EXPORTER_OTLP_ENDPOINT' env --- instrumentation/nginx/README.md | 17 +++++++++++++++++ instrumentation/nginx/src/agent_config.cpp | 8 ++++++++ 2 files changed, 25 insertions(+) diff --git a/instrumentation/nginx/README.md b/instrumentation/nginx/README.md index 7a746c1c6..9cb37fbcc 100644 --- a/instrumentation/nginx/README.md +++ b/instrumentation/nginx/README.md @@ -100,6 +100,7 @@ schedule_delay_millis = 5000 max_export_batch_size = 512 [service] +# Can also be set by the OTEL_SERVICE_NAME environment variable. name = "nginx-proxy" # Opentelemetry resource name [sampler] @@ -108,6 +109,22 @@ ratio = 0.1 parent_based = false ``` +Here's what it would look like if you used the OTLP exporter, but only set the endpoint with an environment variables (e.g. `OTEL_EXPORTER_OTLP_ENDPOINT="localhost:4317"`). +```toml +exporter = "otlp" +processor = "batch" + +[exporters.otlp] + +[processors.batch] +max_queue_size = 2048 +schedule_delay_millis = 5000 +max_export_batch_size = 512 + +[service] +name = "nginx-proxy" # Opentelemetry resource name +``` + To use other environment variables defined in the [specification](https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md), must add the "env" directive. ``` diff --git a/instrumentation/nginx/src/agent_config.cpp b/instrumentation/nginx/src/agent_config.cpp index a9543dab8..2921c2a4d 100644 --- a/instrumentation/nginx/src/agent_config.cpp +++ b/instrumentation/nginx/src/agent_config.cpp @@ -94,6 +94,14 @@ static bool SetupExporter(toml_table_t* root, ngx_log_t* log, OtelNgxAgentConfig } static bool SetupService(toml_table_t* root, ngx_log_t*, OtelNgxAgentConfig* config) { + const char *otel_service_name_env = "OTEL_SERVICE_NAME"; + auto service_name_from_env = std::getenv(otel_service_name_env); + + if (service_name_from_env) { + config->service.name = service_name_from_env; + return true; + } + toml_table_t* service = toml_table_in(root, "service"); if (service) { From 8ec88570c5d872c94bdd3c7ae981ac30402437ec Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Wed, 19 Oct 2022 15:35:11 +0530 Subject: [PATCH 26/77] Remove unnecessary baggage and unwanted headers (#222) --- .../include/core/api/Payload.h | 4 +- .../include/core/api/opentelemetry_ngx_api.h | 7 +-- .../src/apache/ApacheHooks.cpp | 3 +- .../src/core/sdkwrapper/SdkHelperFactory.cpp | 5 -- .../src/core/sdkwrapper/SdkWrapper.cpp | 2 - .../src/nginx/ngx_http_opentelemetry_module.c | 46 ++++++++++++++++++- .../src/nginx/ngx_http_opentelemetry_module.h | 2 +- 7 files changed, 51 insertions(+), 18 deletions(-) diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index c227a5384..6d24fcaad 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -45,8 +45,8 @@ class RequestPayload std::string target; std::string flavor; std::string client_ip; - long port; - long status_code; + long port = 80; + long status_code = 200; public: void set_http_headers(const std::string& key, const std::string& value) diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index ce2e2b1c5..099e9090f 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -25,11 +25,8 @@ extern "C" { #endif -#define BAGGAGE "baggage" -#define TRACEPARENT "traceparent" -#define TRACESTATE "tracestate" - -const char* httpHeaders[] = {"baggage", "traceparent", "tracestate"}; +const char* httpHeaders[] = {"traceparent", "tracestate"}; +const size_t headers_len = sizeof(httpHeaders)/sizeof(httpHeaders[0]); typedef struct{ char* name; diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index a792ac15b..c521958b0 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -264,6 +264,8 @@ APPD_SDK_STATUS_CODE ApacheHooks::appd_startInteraction( if (APPD_ISSUCCESS(res)) { + // remove the singularity header if any + apr_table_unset(r->headers_in, APPD_CORRELATION_HEADER_KEY); if (!propagationHeaders.empty()) { appd_payload_decorator(r, propagationHeaders); @@ -625,7 +627,6 @@ int ApacheHooks::appd_hook_header_parser_begin(request_rec *r) else if (res == APPD_STATUS(cfg_channel_uninitialized) || res == APPD_STATUS(bt_detection_disabled)) { ApacheTracing::writeTrace(r->server, __func__, "request begin detection disabled, result code: %d", res); - apr_table_set(r->headers_in, "singularityheader", "notxdetect=true"); } else { diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp index eba3281c1..056edbf7a 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp @@ -93,11 +93,6 @@ SdkHelperFactory::SdkHelperFactory( using MapHttpTraceCtx = opentelemetry::trace::propagation::HttpTraceContext; mPropagators.push_back( std::unique_ptr(new MapHttpTraceCtx())); - - // Adding Baggage Propagator - using BaggagePropagator = opentelemetry::baggage::propagation::BaggagePropagator; - mPropagators.push_back( - std::unique_ptr(new BaggagePropagator())); } OtelTracer SdkHelperFactory::GetTracer() diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp index e8dcde53a..bf5670172 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp @@ -26,7 +26,6 @@ namespace sdkwrapper { namespace { -constexpr const char* BAGGAGE_HEADER_NAME = "baggage"; constexpr const char* TRACEPARENT_HEADER_NAME = "traceparent"; constexpr const char* TRACESTATE_HEADER_NAME = "tracestate"; @@ -81,7 +80,6 @@ void SdkWrapper::PopulatePropagationHeaders( } // copy all relevant kv pairs into carrier - carrier[BAGGAGE_HEADER_NAME] = otelCarrier.Get(BAGGAGE_HEADER_NAME).data(); carrier[TRACEPARENT_HEADER_NAME] = otelCarrier.Get(TRACEPARENT_HEADER_NAME).data(); carrier[TRACESTATE_HEADER_NAME] = otelCarrier.Get(TRACESTATE_HEADER_NAME).data(); } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 63ede7543..3a4822998 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -700,6 +700,7 @@ static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c if (APPD_ISSUCCESS(res)) { + removeUnwantedHeader(r); otel_payload_decorator(r, propagationHeaders, ix); ngx_writeTrace(r->connection->log, __func__, "Interaction begin successful"); } @@ -1461,6 +1462,47 @@ static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t (conf->nginxModuleSegmentParameter).data); } +static void removeUnwantedHeader(ngx_http_request_t* r) +{ + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_table_elt_t *h; + ngx_http_header_t *hh; + ngx_http_core_main_conf_t *cmcf; + ngx_uint_t nelts; + + part = &r->headers_in.headers.part; + header = (ngx_table_elt_t*)part->elts; + nelts = part->nelts; + + for(ngx_uint_t j = 0; jkey.data)==0){ + if (h->value.len == 0) { + break; + } + if(h->value.data) + ngx_pfree(r->pool, h->value.data); + + char str[] = ""; + h->hash = ngx_hash_key(h->key.data, h->key.len); + + h->value.len = 0; + h->value.data = ngx_pcalloc(r->pool, sizeof(char)*((h->value.len)+1)); + strcpy(h->value.data, str); + h->lowcase_key = h->key.data; + + cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); + hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,h->lowcase_key, h->key.len); + if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { + return; + } + + break; + } + } +} + static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r, int* count){ ngx_list_part_t *part; ngx_table_elt_t *header; @@ -1502,8 +1544,8 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* header = (ngx_table_elt_t*)part->elts; nelts = part->nelts; - req_payload->headers = ngx_pcalloc(r->pool, 3 * sizeof(http_headers)); - for(int i=0; i<3; i++){ + req_payload->headers = ngx_pcalloc(r->pool, headers_len * sizeof(http_headers)); + for(int i=0; iheaders[*count].name = c; for(ngx_uint_t j = 0; j Date: Wed, 19 Oct 2022 15:39:12 -0700 Subject: [PATCH 27/77] Geneva Metrics exporter (#206) --- exporters/geneva/CMakeLists.txt | 83 ++ exporters/geneva/INSTALL.md | 129 ++ .../build_tools/0001-geneva-exporter.patch | 20 + .../build_geneva_metrics_exporter.sh | 87 ++ exporters/geneva/example/example_metrics.cc | 133 ++ exporters/geneva/example/foo_library.cc | 96 ++ exporters/geneva/example/foo_library.h | 14 + .../geneva/metrics/connection_string_parser.h | 93 ++ .../exporters/geneva/metrics/data_transport.h | 25 + .../exporters/geneva/metrics/exporter.h | 141 +++ .../geneva/metrics/exporter_options.h | 29 + .../exporters/geneva/metrics/macros.h | 54 + .../exporters/geneva/metrics/socket_tools.h | 1115 +++++++++++++++++ .../unix_domain_socket_data_transport.h | 34 + exporters/geneva/src/exporter.cc | 361 ++++++ .../src/unix_domain_socket_data_transport.cc | 73 ++ .../geneva/test/common/generate_metrics.h | 177 +++ exporters/geneva/test/common/socket_server.h | 420 +++++++ .../geneva/test/decoder/ifx_metrics_bin.cpp | 486 +++++++ .../geneva/test/decoder/ifx_metrics_bin.h | 617 +++++++++ .../geneva/test/decoder/ifx_metrics_bin.ksy | 236 ++++ .../test/decoder/kaitai/custom_decoder.h | 16 + .../geneva/test/decoder/kaitai/exceptions.h | 177 +++ .../test/decoder/kaitai/kaitaistream.cpp | 690 ++++++++++ .../geneva/test/decoder/kaitai/kaitaistream.h | 297 +++++ .../geneva/test/decoder/kaitai/kaitaistruct.h | 22 + .../geneva/test/metrics_exporter_test.cc | 217 ++++ 27 files changed, 5842 insertions(+) create mode 100644 exporters/geneva/CMakeLists.txt create mode 100644 exporters/geneva/INSTALL.md create mode 100644 exporters/geneva/build_tools/0001-geneva-exporter.patch create mode 100644 exporters/geneva/build_tools/build_geneva_metrics_exporter.sh create mode 100644 exporters/geneva/example/example_metrics.cc create mode 100644 exporters/geneva/example/foo_library.cc create mode 100644 exporters/geneva/example/foo_library.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter_options.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/macros.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h create mode 100644 exporters/geneva/src/exporter.cc create mode 100644 exporters/geneva/src/unix_domain_socket_data_transport.cc create mode 100644 exporters/geneva/test/common/generate_metrics.h create mode 100644 exporters/geneva/test/common/socket_server.h create mode 100644 exporters/geneva/test/decoder/ifx_metrics_bin.cpp create mode 100644 exporters/geneva/test/decoder/ifx_metrics_bin.h create mode 100644 exporters/geneva/test/decoder/ifx_metrics_bin.ksy create mode 100644 exporters/geneva/test/decoder/kaitai/custom_decoder.h create mode 100644 exporters/geneva/test/decoder/kaitai/exceptions.h create mode 100644 exporters/geneva/test/decoder/kaitai/kaitaistream.cpp create mode 100644 exporters/geneva/test/decoder/kaitai/kaitaistream.h create mode 100644 exporters/geneva/test/decoder/kaitai/kaitaistruct.h create mode 100644 exporters/geneva/test/metrics_exporter_test.cc diff --git a/exporters/geneva/CMakeLists.txt b/exporters/geneva/CMakeLists.txt new file mode 100644 index 000000000..db06e03af --- /dev/null +++ b/exporters/geneva/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.12) + +# MAIN_PROJECT CHECK determine if fluentd exporter is built as a subproject +# (using add_subdirectory) or if it is the main project +# +set(MAIN_PROJECT OFF) + +set(MAIN_PROJECT OFF) +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + project(opentelemetry-geneva-metrics) + set(MAIN_PROJECT ON) +endif() + +add_definitions(-DHAVE_CONSOLE_LOG) +if(MAIN_PROJECT) + find_package(opentelemetry-cpp REQUIRED) +endif() + +find_package(CURL REQUIRED) + +include_directories(include) +# create geneva metrics exporter +add_library(opentelemetry_exporter_geneva_metrics + src/exporter.cc src/unix_domain_socket_data_transport.cc) +target_include_directories(opentelemetry_exporter_geneva_metrics + PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) +target_link_libraries(opentelemetry_exporter_geneva_metrics + PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES}) +set_target_properties(opentelemetry_exporter_geneva_metrics + PROPERTIES EXPORT_NAME metrics) + +if(BUILD_TESTING) + if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) + # Prefer GTest from build tree. GTest is not always working with + # CMAKE_PREFIX_PATH + set(GTEST_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googletest/include + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googlemock/include) + set(GTEST_BOTH_LIBRARIES + ${CMAKE_BINARY_DIR}/lib/libgtest.a + ${CMAKE_BINARY_DIR}/lib/libgtest_main.a + ${CMAKE_BINARY_DIR}/lib/libgmock.a) + else() + find_package(GTest REQUIRED) + endif() + include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) + include_directories(SYSTEM test/decoder) + enable_testing() + include(GoogleTest) + # build geneva metrics tests + add_compile_definitions(KS_STR_ENCODING_NONE HAVE_UNIX_DOMAIN) + add_executable( + geneva_metrics_exporter_test + test/metrics_exporter_test.cc test/decoder/ifx_metrics_bin.cpp + test/decoder/kaitai/kaitaistream.cpp) + target_link_libraries( + geneva_metrics_exporter_test ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_exporter_geneva_metrics) + + gtest_add_tests( + TARGET geneva_metrics_exporter_test + TEST_PREFIX exporter. + TEST_LIST geneva_metrics_exporter_test) +endif() + +install( + TARGETS opentelemetry_exporter_geneva_metrics + EXPORT "${PROJECT_NAME}-target" + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install( + DIRECTORY include/opentelemetry/exporters/geneva + DESTINATION include/opentelemetry/exporters + FILES_MATCHING + PATTERN "*.h") + +if(BUILD_EXAMPLE) + add_executable(example_metrics example/example_metrics.cc + example/foo_library.cc) + target_link_libraries(example_metrics opentelemetry_exporter_geneva_metrics) +endif() diff --git a/exporters/geneva/INSTALL.md b/exporters/geneva/INSTALL.md new file mode 100644 index 000000000..f8ec96795 --- /dev/null +++ b/exporters/geneva/INSTALL.md @@ -0,0 +1,129 @@ +# Building OpenTelemetry Geneva exporter for Metrics + +[CMake](https://cmake.org/) is the build system supported +for the build + +# Prerequisite + + - The exporter requires opentelemetry-cpp already installed. + + - [GoogleTest](https://github.com/google/googletest) framework to build and run + the unittests. + +# Build instructions using CMake + +### Building as standalone CMake Project + +1. Build and Install the prerequisite opentelemetry-cpp. Refer to [INSTALL.md](https://github.com/open-telemetry/opentelemetry-cpp/blob/main/INSTALL.md#build-instructions-using-cmake) +for instructions. + +2. Getting the opentelementry-cpp-contrib source: + + ```console + # Change to the directory where you want to create the code repository + $ cd ~ + $ mkdir source && cd source + $ git clone --recursive https://github.com/open-telemetry/opentelemetry-cpp-contrib + Cloning into 'opentelemetry-cpp'... + ... + Resolving deltas: 100% (3225/3225), done. + $ + ``` + +3. Navigate to the repository cloned above, and create the `CMake` build + configuration. + + ```console + $ cd opentelemetry-cpp-contrib + $ cd exporters/geneva && mkdir build && cd build + $ cmake .. + -- The C compiler identification is GNU 9.3.0 + -- The CXX compiler identification is GNU 9.3.0 + ... + -- Configuring done + -- Generating done + -- Build files have been written to: /home//source/opentelemetry-cpp-contrib/exporters/geneva/build + $ + ``` + + Some of the available cmake build variables we can use during cmake + configuration: + + - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON` : Please note that with default + configuration, the code is compiled without `-fpic` option, so it is not + suitable for inclusion in shared libraries. To enable the code for + inclusion in shared libraries, this variable is used. + - `-DBUILD_SHARED_LIBS=ON` : To build shared libraries for the targets. + - `-DBUILD_TESTING=ON` : Build the unit-tests + - `-DBUILD_EXAMPLE=ON`: Build the example code which generates measurements and collects/exports metrics periodically + +4. Once build configuration is created, build the exporter: + + ```console + $ cmake --build . --target all + Scanning dependencies of target opentelemetry_exporter_geneva_metrics + [ 33%] Building CXX object CMakeFiles/opentelemetry_exporter_geneva_metrics.dir/src/exporter.cc.o + [ 66%] Building CXX object CMakeFiles/opentelemetry_exporter_geneva_metrics.dir/src/unix_domain_socket_data_transport.cc.o + [100%] Linking CXX static library libopentelemetry_exporter_geneva_metrics.a + [100%] Built target opentelemetry_exporter_geneva_metrics + $ + ``` + +5. If CMake tests are built, run them with `ctest` command + + ```console + $ ctest + Test project /tmp/opentelemetry-cpp-contrib/exporters/geneva/build + ... + 100% tests passed, 0 tests failed out of 380 + $ + ``` + +6. Optionally install the exporter's include headers and library at custom/default install location. + + ```console + $ cmake --install . --prefix // + Install the project... + -- Install configuration: "" + -- Installing: //lib/libopentelemetry_exporter_geneva_metrics.a + -- Installing: //include/opentelemetry/exporters/geneva + -- Installing: //include/opentelemetry/exporters/geneva/metrics + -- Installing: //include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h + -- Installing: //include/opentelemetry/exporters/geneva/metrics/exporter.h + -- Installing: //include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h + -- Installing: //include/opentelemetry/exporters/geneva/metrics/data_transport.h + -- Installing: //include/opentelemetry/exporters/geneva/metrics/macros.h + -- Installing: //include/opentelemetry/exporters/geneva/metrics/socket_tools.h + -- Installing: //include/opentelemetry/exporters/geneva/metrics/exporter_options.h + $ + ``` + +### Using shell script to build and install the Geneva exporter: + +1. Create the following directory structure in the root directory of the application. Clone the +opentelemetry-cpp and opentelemetry-cpp-contrib under the `deps` directory as given below. And +copy the script and patch file from to the `tools` directory. + + ``` + # + # | + # - tools + # | + # - build_geneva_metrics_exporter.sh + # - 001-geneva-metrics-exporter.patch + # - deps + # | + # - open-telemetry + # | + # - opentelemetry-cpp + # - opentelemetry-cpp-contrib/exporters/geneva + # + ``` +2. Execute `build_geneva_metrics_exporter.sh` script from the `tools` directory + + ```console + $ cd /tools && ./build_geneva_metrics_exporter.sh + + ``` +3. This will build the opentelemetry-cpp and Geneva exporter and install them to +`/usr`. Modify the script accordingly to change the default install location. diff --git a/exporters/geneva/build_tools/0001-geneva-exporter.patch b/exporters/geneva/build_tools/0001-geneva-exporter.patch new file mode 100644 index 000000000..d7e78155c --- /dev/null +++ b/exporters/geneva/build_tools/0001-geneva-exporter.patch @@ -0,0 +1,20 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index a1b69340..bf347198 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -442,3 +442,5 @@ install( + EXPORT "${PROJECT_NAME}-target" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") ++ ++ +diff --git a/exporters/CMakeLists.txt b/exporters/CMakeLists.txt +index 862d2c77..354bfef4 100644 +--- a/exporters/CMakeLists.txt ++++ b/exporters/CMakeLists.txt +@@ -38,3 +38,5 @@ endif() + if(WITH_JAEGER) + add_subdirectory(jaeger) + endif() ++ ++add_subdirectory(geneva) \ No newline at end of file diff --git a/exporters/geneva/build_tools/build_geneva_metrics_exporter.sh b/exporters/geneva/build_tools/build_geneva_metrics_exporter.sh new file mode 100644 index 000000000..6d522537e --- /dev/null +++ b/exporters/geneva/build_tools/build_geneva_metrics_exporter.sh @@ -0,0 +1,87 @@ +#!/bin/bash +echo Building OpenTelemetry SDK... +pushd "$(dirname "$0")" + +# +# Build OpenTelemetry C++ SDK with Geneva Metrics Exporter +# Copy this file to the tools directory of the project repo +# repo, and build below dir structure +# +# +# | +# - tools +# | +# - build_geneva_metrics_exporter.sh +# - 001-geneva-metrics-exporter.patch +# - deps +# | +# - open-telemetry +# | +# - opentelemetry-cpp +# - opentelemetry-cpp-contrib/exporters/geneva +# + +export OTEL_SDK=`realpath $(pwd)/../deps/open-telemetry/opentelemetry-cpp` +export OTEL_GENEVA_METRICS=`realpath $(pwd)/../deps/open-telemetry/opentelemetry-cpp-contrib/exporters/geneva/` +export PATCH_FILE="001-geneva-exporter.patch" + +[ ! -d $OTEL_SDK ] && echo "Error: $OTEL_SDK doesn't exist" && exit 1 +[ ! -d $OTEL_GENEVA_METRICS ] && echo "Error: $OTEL_GENEVA_METRICS doesn't exist" && exit 1 +[ ! -f $PATCH_FILE ] && echo "Error: Geneva metrics exporter patch doesn't exist" && exit 1 + +# +# Initialize submodules if necessary +# +if [ ! -f $OTEL_SDK/third_party/nlohmann-json/CMakeLists.txt ]; then + pushd $OTEL_SDK + git submodule update --init --recursive + popd +fi + +# +# Create symlink to Geneva exporter +# +if [ ! -L $OTEL_SDK/exporters/geneva/ ]; then + ln -sf $OTEL_GENEVA_METRICS/ $OTEL_SDK/exporters/geneva +fi + +# +# Build and install nlohmann-json dependency +# +pushd $OTEL_SDK/third_party/nlohmann-json +[[ "clean" == "$1" ]] && rm -rf ./build +mkdir -p build +cd build +cmake -G "Ninja" -DCMAKE_INSTALL_PREFIX:PATH=/usr -DJSON_BuildTests=OFF -DBUILD_TESTING=OFF .. +ninja +ninja install +popd + +# +# Build with Geneva exporter +# +if [ ! -f ${OTEL_SDK}/${PATCH_FILE} ]; then + # Apply patch to include geneva metrics exporter as part of the build + cp -f ${PATCH_FILE} $OTEL_SDK + pushd $OTEL_SDK + git apply ${PATCH_FILE} + popd +fi + +pushd $OTEL_SDK +[[ "clean" == "$1" ]] && rm -rf ./build +mkdir -p build +cd build +cmake -G "Ninja" \ + -DCMAKE_INSTALL_PREFIX:PATH=/usr \ + -DWITH_OTLP=OFF \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \ + -DBUILD_TESTING=OFF \ + -DBUILD_PACKAGE=ON \ + -DWITH_LOGS_PREVIEW=ON \ + .. +ninja +ninja install +popd +popd diff --git a/exporters/geneva/example/example_metrics.cc b/exporters/geneva/example/example_metrics.cc new file mode 100644 index 000000000..0fe791cf7 --- /dev/null +++ b/exporters/geneva/example/example_metrics.cc @@ -0,0 +1,133 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef ENABLE_METRICS_PREVIEW +#include "opentelemetry/exporters/geneva/metrics/exporter.h" +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +#include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h" +#include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_provider.h" +#include +#include + +#include "foo_library.h" + +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace nostd = opentelemetry::nostd; +namespace common = opentelemetry::common; +namespace geneva_exporter = opentelemetry::exporter::geneva::metrics; +namespace metrics_api = opentelemetry::metrics; + +namespace { + +const std::string kUnixDomainPath = "/tmp/ifx_unix_socket"; +const std::string kNamespaceName = "test_ns"; + +void initMetrics(const std::string &name, const std::string &account_name) { + std::string conn_string = "Endpoint=unix://" + kUnixDomainPath + + ";Account=" + account_name + + ";Namespace=" + kNamespaceName; + geneva_exporter::ExporterOptions options{conn_string}; + std::unique_ptr exporter{ + new geneva_exporter::Exporter(options)}; + + std::string version{"1.2.0"}; + std::string schema{"https://opentelemetry.io/schemas/1.2.0"}; + + // Initialize and set the global MeterProvider + metric_sdk::PeriodicExportingMetricReaderOptions reader_options; + reader_options.export_interval_millis = std::chrono::milliseconds(1000); + reader_options.export_timeout_millis = std::chrono::milliseconds(500); + std::unique_ptr reader{ + new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), + reader_options)}; + auto provider = std::shared_ptr( + new metric_sdk::MeterProvider()); + auto p = std::static_pointer_cast(provider); + p->AddMetricReader(std::move(reader)); + + // counter view + std::string counter_name = name + "_counter"; + std::unique_ptr instrument_selector{ + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, + counter_name)}; + std::unique_ptr meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr sum_view{new metric_sdk::View{ + name, "description", metric_sdk::AggregationType::kSum}}; + p->AddView(std::move(instrument_selector), std::move(meter_selector), + std::move(sum_view)); + + // observable counter view + std::string observable_counter_name = name + "_observable_counter"; + std::unique_ptr + observable_instrument_selector{new metric_sdk::InstrumentSelector( + metric_sdk::InstrumentType::kObservableCounter, + observable_counter_name)}; + std::unique_ptr observable_meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr observable_sum_view{new metric_sdk::View{ + name, "description", metric_sdk::AggregationType::kSum}}; + p->AddView(std::move(observable_instrument_selector), + std::move(observable_meter_selector), + std::move(observable_sum_view)); + + // histogram view + std::string histogram_name = name + "_histogram"; + std::unique_ptr histogram_instrument_selector{ + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kHistogram, + histogram_name)}; + std::unique_ptr histogram_meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::shared_ptr + aggregation_config{ + new opentelemetry::sdk::metrics::HistogramAggregationConfig}; + static_cast< + opentelemetry::sdk::metrics::HistogramAggregationConfig *>( + aggregation_config.get()) + ->boundaries_ = std::list{0.0, 50.0, 100.0, 250.0, 500.0, + 750.0, 1000.0, 2500.0, 5000.0, 10000.0}; + std::unique_ptr histogram_view{new metric_sdk::View{ + name, "description", metric_sdk::AggregationType::kHistogram, + aggregation_config}}; + p->AddView(std::move(histogram_instrument_selector), + std::move(histogram_meter_selector), std::move(histogram_view)); + metrics_api::Provider::SetMeterProvider(provider); +} +} // namespace + +int main(int argc, char **argv) { + std::string account_name = "TestAccount"; + std::string example_type; + if (argc >= 2) { + account_name = argv[1]; + if (argc >= 3) { + example_type = argv[2]; + } + } + + std::string name{"ostream_metric_example"}; + initMetrics(name, account_name); + + if (example_type == "counter") { + FooLibrary::counter_example(name); + } else if (example_type == "observable_counter") { + FooLibrary::observable_counter_example(name); + } else if (example_type == "histogram") { + FooLibrary::histogram_example(name); + } else { + std::thread counter_example{&FooLibrary::counter_example, name}; + std::thread observable_counter_example{ + &FooLibrary::observable_counter_example, name}; + std::thread histogram_example{&FooLibrary::histogram_example, name}; + + counter_example.join(); + observable_counter_example.join(); + histogram_example.join(); + } +} +#else +int main() {} +#endif \ No newline at end of file diff --git a/exporters/geneva/example/foo_library.cc b/exporters/geneva/example/foo_library.cc new file mode 100644 index 000000000..019bfe39f --- /dev/null +++ b/exporters/geneva/example/foo_library.cc @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifndef ENABLE_METRICS_PREVIEW +#include "foo_library.h" +#include "opentelemetry/context/context.h" +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include +#include +#include +#include +#include + +namespace nostd = opentelemetry::nostd; +namespace metrics_api = opentelemetry::metrics; + +namespace { + +std::map get_random_attr() { + static const std::vector> labels = { + {"key1", "value1"}, + {"key2", "value2"}, + {"key3", "value3"}, + {"key4", "value4"}, + {"key5", "value5"}}; + return std::map{ + labels[rand() % (labels.size() - 1)], + labels[rand() % (labels.size() - 1)]}; +} + +class MeasurementFetcher { +public: + static void Fetcher(opentelemetry::metrics::ObserverResult observer_result, + void *state) { + std::map labels = get_random_attr(); + auto labelkv = + opentelemetry::common::KeyValueIterableView{labels}; + if (nostd::holds_alternative< + nostd::shared_ptr>>( + observer_result)) { + double val = (rand() % 700) + 1.1; + nostd::get< + nostd::shared_ptr>>( + observer_result) + ->Observe(val /*, labelkv */); + } + } +}; +} // namespace + +void FooLibrary::counter_example(const std::string &name) { + std::string counter_name = name + "_counter"; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = + provider->GetMeter(name, "1.2.0"); + auto double_counter = meter->CreateDoubleCounter(counter_name); + + while (true) { + double val = (rand() % 700) + 1.1; + double_counter->Add(val); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } +} + +void FooLibrary::observable_counter_example(const std::string &name) { + std::string counter_name = name + "_observable_counter"; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = + provider->GetMeter(name, "1.2.0"); + auto counter = meter->CreateDoubleObservableCounter(counter_name); + counter->AddCallback(MeasurementFetcher::Fetcher, nullptr); + std::this_thread::sleep_until( + std::chrono::system_clock::now() + + std::chrono::hours(std::numeric_limits::max())); +} + +void FooLibrary::histogram_example(const std::string &name) { + std::string histogram_name = name + "_histogram"; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = + provider->GetMeter(name, "1.2.0"); + auto histogram_counter = + meter->CreateDoubleHistogram(histogram_name, "des", "unit"); + auto context = opentelemetry::context::Context{}; + while (true) { + double val = (rand() % 700) + 1.1; + std::map labels = get_random_attr(); + auto labelkv = + opentelemetry::common::KeyValueIterableView{labels}; + histogram_counter->Record(val, labelkv, context); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } +} + +#endif \ No newline at end of file diff --git a/exporters/geneva/example/foo_library.h b/exporters/geneva/example/foo_library.h new file mode 100644 index 000000000..cbb430bec --- /dev/null +++ b/exporters/geneva/example/foo_library.h @@ -0,0 +1,14 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifndef ENABLE_METRICS_PREVIEW +#include + +class FooLibrary { +public: + static void counter_example(const std::string &name); + static void histogram_example(const std::string &name); + static void observable_counter_example(const std::string &name); +}; +#endif \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h new file mode 100644 index 000000000..5f53ff7c8 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h @@ -0,0 +1,93 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/exporters/geneva/metrics/macros.h" +#include "opentelemetry/exporters/geneva/metrics/socket_tools.h" +#include "opentelemetry/ext/http/common/url_parser.h" +#include "opentelemetry/version.h" +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { +constexpr char kSemicolon = ';'; +constexpr char kEqual = '='; +constexpr char kEndpoint[] = "Endpoint"; +constexpr char kAccount[] = "Account"; +constexpr char kNamespace[] = "Namespace"; + +enum class TransportProtocol { kETW, kTCP, kUDP, kUNIX, kUnknown }; + +class ConnectionStringParser { + +public: + ConnectionStringParser(const std::string &connection_string) + : account_(""), namespace_(""), + url_(nullptr), transport_protocol_{TransportProtocol::kUnknown} { + std::string::size_type key_pos = 0; + std::string::size_type key_end; + std::string::size_type val_pos; + std::string::size_type val_end; + bool is_endpoint_found = false; + while ((key_end = connection_string.find(kEqual, key_pos)) != + std::string::npos) { + if ((val_pos = connection_string.find_first_not_of(kEqual, key_end)) == + std::string::npos) { + break; + } + val_end = connection_string.find(kSemicolon, val_pos); + auto key = connection_string.substr(key_pos, key_end - key_pos); + auto value = connection_string.substr(val_pos, val_end - val_pos); + key_pos = val_end; + if (key_pos != std::string::npos) { + ++key_pos; + } + if (key == kNamespace) { + namespace_ = value; + } else if (key == kAccount) { + account_ = value; + } else if (key == kEndpoint) { + is_endpoint_found = true; + url_ = std::unique_ptr( + new ext::http::common::UrlParser(value)); + if (url_->success_) { +#ifdef HAVE_UNIX_DOMAIN + if (url_->scheme_ == "unix") { + transport_protocol_ = TransportProtocol::kUNIX; + } +#else + if (url_->scheme_ == "unix") { + LOG_ERROR("Unix domain socket not supported on this platform") + } +#endif + if (url_->scheme_ == "tcp") { + transport_protocol_ = TransportProtocol::kTCP; + } + if (url_->scheme_ == "udp") { + transport_protocol_ = TransportProtocol::kUDP; + } + } + } + } +#if defined(_MSC_VER) + if (account_.size() && namespace_.size() && !is_endpoint_found) { + transport_protocol_ = TransportProtocol::kETW; + } +#endif + } + + bool IsValid() { return transport_protocol_ != TransportProtocol::kUnknown; } + + std::string account_; + std::string namespace_; + std::unique_ptr url_; + TransportProtocol transport_protocol_; +}; +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h new file mode 100644 index 000000000..66bfe5717 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h @@ -0,0 +1,25 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { +using ByteVector = std::vector; + +class DataTransport { +public: + virtual bool Connect() noexcept = 0; + virtual bool Send(const char *data, uint16_t length) noexcept = 0; + virtual bool Disconnect() noexcept = 0; +}; +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h new file mode 100644 index 000000000..d039d5478 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -0,0 +1,141 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/common/spin_lock_mutex.h" +#include "opentelemetry/exporters/geneva/metrics/connection_string_parser.h" +#include "opentelemetry/exporters/geneva/metrics/data_transport.h" +#include "opentelemetry/exporters/geneva/metrics/exporter_options.h" +#include "opentelemetry/sdk/metrics/metric_exporter.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { + +constexpr size_t kBufferSize = 65360; // the maximum ETW payload (inclusive) +constexpr size_t kMaxDimensionNameSize = 256; +constexpr size_t kMaxDimensionValueSize = 1024; +constexpr size_t kBinaryHeaderSize = 4; // event_id (2) + body_length (2) +constexpr size_t kMetricPayloadSize = + 24; // count_dimension (2) + reserverd_word (2) + reserverd_dword(4) + + // timestamp_utc (8) + metric_data (8) +constexpr size_t kExternalPayloadSize = + 40; // count_dimension (2) + reserverd_word (2) + count (4) + timestamp_utc + // (8) + metric_data_sum (8) + metric_data_min(8) + metric_data_max(8) + +// time conversion constants +constexpr uint32_t kWindowsTicksPerSecond = + 10000000; // windows ticks are in 100 ns +constexpr uint64_t kSecondsToUnixTime = + 11644473600L; // number of seconds between windows epoch start + // 1601-01-01T00:00:00Z and UNIX/Linux epoch + // (1970-01-01T00:00:00Z) + +enum class MetricsEventType : uint16_t { + ULongMetric = 50, + DoubleMetric = 55, + ExternallyAggregatedULongDistributionMetric = 56 +}; + +/** + * The Geneva metrics exporter exports metrics data to Geneva + */ +class Exporter final : public opentelemetry::sdk::metrics::MetricExporter { +public: + Exporter(const ExporterOptions &options); + + opentelemetry::sdk::common::ExportResult + Export(const opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept + override; + + sdk::metrics::AggregationTemporality GetAggregationTemporality( + sdk::metrics::InstrumentType instrument_type) const noexcept override; + + bool ForceFlush(std::chrono::microseconds timeout = + (std::chrono::microseconds::max)()) noexcept override; + + bool Shutdown(std::chrono::microseconds timeout = + (std::chrono::microseconds::max)()) noexcept override; + +private: + const ExporterOptions options_; + ConnectionStringParser connection_string_parser_; + const sdk::metrics::AggregationTemporalitySelector + aggregation_temporality_selector_; + bool is_shutdown_ = false; + mutable opentelemetry::common::SpinLockMutex lock_; + std::unique_ptr data_transport_; + + // metrics storage + char buffer_non_histogram_[kBufferSize]; + char buffer_histogram_[kBufferSize]; + uint64_t buffer_index_non_histogram_; + uint64_t buffer_index_histogram_; + + size_t InitializeBufferForNonHistogramData(); + size_t InitiaizeBufferForHistogramData(); + size_t SerializeNonHistogramMetrics(sdk::metrics::AggregationType, + MetricsEventType, + const sdk::metrics::ValueType &, + common::SystemTimestamp, + const std::string &, + const sdk::metrics::PointAttributes &); + size_t SerializeHistogramMetrics( + sdk::metrics::AggregationType, MetricsEventType, uint64_t, + const sdk::metrics::ValueType &, const sdk::metrics::ValueType &, + const sdk::metrics::ValueType &, const std::list &boundaries, + const std::vector &counts, common::SystemTimestamp, + const std::string &, const sdk::metrics::PointAttributes &); +}; + +template +static void SerializeInt(char *buffer, size_t &index, T value) { + *(reinterpret_cast(buffer + index)) = value; + index += sizeof(T); +} + +static void SerializeString(char *buffer, size_t &index, + const std::string &str) { + auto size = str.size(); + SerializeInt(buffer, index, static_cast(size)); + if (size > 0) { + memcpy(buffer + index, str.c_str(), size); + } + index += size; +} + +static std::string AttributeValueToString( + const opentelemetry::sdk::common::OwnedAttributeValue &value) { + std::string result; + if (nostd::holds_alternative(value)) { + result = nostd::get(value) ? "true" : "false"; + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = nostd::get(value); + } else { + LOG_WARN("[Geneva Metrics Exporter] AttributeValueToString - " + " Nested attributes not supported - ignored"); + } + return result; +} + +static uint64_t UnixTimeToWindowsTicks(uint64_t unix_epoch_secs) { + uint64_t secs_since_windows_epoch = unix_epoch_secs + kSecondsToUnixTime; + return (secs_since_windows_epoch * (uint64_t)kWindowsTicksPerSecond); +} + +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter_options.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter_options.h new file mode 100644 index 000000000..2abf3cad8 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter_options.h @@ -0,0 +1,29 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { + +struct ExporterOptions { + // clang-format off + /* + Format - + Windows: + Account={MetricAccount};NameSpace={MetricNamespace} + Linux: + Endpoint=unix://{UDS Path};Account={MetricAccount};Namespace={MetricNamespace} + */ +// clang-format off + std::string connection_string; +}; +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/macros.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/macros.h new file mode 100644 index 000000000..046c89812 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/macros.h @@ -0,0 +1,54 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#ifndef TOKENPASTE +#define TOKENPASTE(x, y) x##y +#endif + +#ifndef TOKENPASTE2 +#define TOKENPASTE2(x, y) TOKENPASTE(x, y) +#endif + +#ifndef LOCKGUARD +#define LOCKGUARD(macro_mutex) \ + std::lock_guard TOKENPASTE2(__guard_, \ + __LINE__)(macro_mutex) +#endif + +#if defined(HAVE_CONSOLE_LOG) && !defined(LOG_DEBUG) +// Log to console if there's no standard log facility defined +#include +#ifndef LOG_DEBUG +#define LOG_DEBUG(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__) +#define LOG_TRACE(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__) +#define LOG_INFO(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__) +#define LOG_WARN(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__) +#define LOG_ERROR(fmt_, ...) printf(" " fmt_ "\n", ##__VA_ARGS__) +#endif +#endif + +#ifndef LOG_DEBUG +// Don't log anything if there's no standard log facility defined +#define LOG_DEBUG(fmt_, ...) +#define LOG_TRACE(fmt_, ...) +#define LOG_INFO(fmt_, ...) +#define LOG_WARN(fmt_, ...) +#define LOG_ERROR(fmt_, ...) +#endif + +// Annex K macros +#if !defined(_MSC_VER) +#ifndef strncpy_s +#define strncpy_s(dest, destsz, src, count) \ + strncpy(dest, src, (destsz <= count) ? destsz : count) +#endif +#endif + +// SAL macro +#ifndef _Out_cap_ +#define _Out_cap_(size) +#endif diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h new file mode 100644 index 000000000..0031f65d7 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h @@ -0,0 +1,1115 @@ +// Copyright 2020, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#pragma warning(push) +// Disable: warning C4267: 'argument': conversion from `size_t` to `int`, +// possible loss of data. +// +// WinSock vs POSIX sockets use different definition of socket payload size, +// e.g. in definition of socket ::send 'len' argument: +// - WinSock: int len +// - Linux: size_t len +// - BSD: size_t len +// +// We keep C++ method signature identical and prefer `size_t`. It is expected +// that Windows client cann not physically attempt to send a buffer larger than +// a size of max int. +// +#pragma warning(disable : 4267) +#endif + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#include + +#ifdef min +// NOMINMAX may be a better choice. However, defining it globally may break +// other. Code that depends on macro definition in Windows SDK. +#undef min +#undef max +#endif + +// This code requires WinSock2 on Windows. +#pragma comment(lib, "ws2_32.lib") +// Workaround for libcurl redefinition of afunix.h struct : +// https://github.com/curl/curl/blob/7645324072c2f052fa662aded6f26821141ecda1/lib/config-win32.h#L721 +// Unfortunately libcurl defines a structure that should otherwise be normally +// defined by afunix.h . When that happens, we cannot build the sockets library +// with Unix domain support. +#if !defined(USE_UNIX_SOCKETS) +#ifdef __has_include +#if __has_include() +// Win 10 SDK 17063+ is necessary for Unix domain sockets support. +#include +#define HAVE_UNIX_DOMAIN +#endif +#endif +#endif + +#else +#define HAVE_UNIX_DOMAIN +#include + +#ifdef __linux__ +#include +#endif + +#if __APPLE__ +#include "TargetConditionals.h" +// Use kqueue on mac +#include +#include +#include +#endif + +// Common POSIX headers for Linux and Mac OS X +#include +#include +#include +#include +#include +#include +#include +#endif + +#if !defined(_MSC_VER) && !defined(__STDC_LIB_EXT1__) +#ifndef strncpy_s +#define strncpy_s(dest, destsz, src, count) \ + strncpy(dest, src, (destsz <= count) ? destsz : count) +#endif +#endif + +#include "opentelemetry/exporters/geneva/metrics/macros.h" + +namespace net { + +/// +/// A simple thread, derived class overloads onThread() method. +/// +struct Thread { + std::thread m_thread; + + std::atomic m_terminate{false}; + + /// + /// Thread Constructor + /// + /// Thread + Thread() {} + + /// + /// Start Thread + /// + void startThread(bool wait = true) { + m_terminate = false; + m_thread = std::thread([&]() { this->onThread(); }); + if (wait) { + waitForStart(); + } + } + + /// + /// Wait for thread start + /// + void waitForStart() { + while (!m_thread.joinable()) { + std::this_thread::yield(); + } + } + + /// + /// Join Thread + /// + void joinThread() { + m_terminate = true; + if (m_thread.joinable()) { + m_thread.join(); + } + } + + /// + /// Indicates if this thread should terminate + /// + /// + bool shouldTerminate() const { return m_terminate; } + + /// + /// Must be implemented by children + /// + virtual void onThread() = 0; + + /// + /// Thread destructor + /// + /// + virtual ~Thread() noexcept {} +}; + +}; // namespace net + +namespace SocketTools { + +#ifdef _WIN32 +// WinSocks need extra (de)initialization, solved by a global object here, +// whose constructor/destructor will be called before and after main(). +struct WsaInitializer { + WsaInitializer() { + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + } + + ~WsaInitializer() { WSACleanup(); } +}; + +static WsaInitializer g_wsaInitializer; + +#endif + +/// +/// Encapsulation of C struct sockaddr[_in|_un] with additional helper methods. +/// Both Internet and Unix Domain sockets are suported. +/// The struct may be cast directly to sockaddr: +/// - operator sockaddr *() +/// - size_t size() const - returns proper size depending on socket type. +/// +struct SocketAddr { + // The union is only as big as necessary to hold its largest data member. + // Modern OS (both Un*x and Windows) require at least sizeof(sockaddr_un). + union { + sockaddr m_data; + sockaddr_in m_data_in; + sockaddr_in6 m_data_in6; +#ifdef HAVE_UNIX_DOMAIN + sockaddr_un m_data_un; +#endif + }; + + constexpr static u_long const Loopback = 0x7F000001; + + // Indicator that the sockaddr is sockaddr_un + bool isUnixDomain; + + /// + /// SocketAddr constructor + /// + /// SocketAddr + SocketAddr() { + isUnixDomain = false; +#ifdef HAVE_UNIX_DOMAIN + memset(&m_data_un, 0, sizeof(m_data_un)); +#else + memset(&m_data_in6, 0, sizeof(m_data_in6)); +#endif + } + + SocketAddr(u_long addr, int port) { + isUnixDomain = false; + sockaddr_in &inet4 = reinterpret_cast(m_data); + inet4.sin_family = AF_INET; + inet4.sin_port = htons(static_cast(port)); + inet4.sin_addr.s_addr = htonl(addr); + } + + SocketAddr(const char *addr, bool unixDomain = false) : SocketAddr() { + isUnixDomain = unixDomain; + std::string ipAddress = addr; + auto found = ipAddress.find("://"); + if (found != std::string::npos) { + // always strip scheme + ipAddress.erase(0, found + 3); + } + +#ifdef HAVE_UNIX_DOMAIN + if (isUnixDomain) { + m_data_un.sun_family = AF_UNIX; + const char *unix_domain_path = ipAddress.data(); + // Max length of Unix domain filename is up to 108 chars + strncpy_s(m_data_un.sun_path, sizeof(m_data_un.sun_path), + unix_domain_path, sizeof(m_data_un.sun_path)); + return; + } +#endif + + // Convert {IPv4|IPv6}:{port} string to Network address and Port. + int port = 0; + + // If numColons is more than 2, then it is IPv6 address + size_t numColons = std::count(ipAddress.begin(), ipAddress.end(), ':'); + // Find last colon, which should indicate the port number + char const *lastColon = strrchr(ipAddress.data(), ':'); + if (lastColon) { + port = atoi(lastColon + 1); + // Erase port number + ipAddress.erase(lastColon - ipAddress.data()); + } + + // If there are more than two colons, it means the input is IPv6, e.g + // [fe80::c018:4a9b:3681:4e41]:3000 + if (numColons > 1) { + sockaddr_in6 &inet6 = m_data_in6; + inet6.sin6_family = AF_INET6; + inet6.sin6_port = htons(port); + void *pAddrBuf = &inet6.sin6_addr; + size_t len = ipAddress.length(); + if ((ipAddress[0] == '[') && (ipAddress[len - 1] == ']')) { + // Remove square brackets + ipAddress = ipAddress.substr(1, ipAddress.length() - 2); + } + if (!::inet_pton(inet6.sin6_family, ipAddress.c_str(), pAddrBuf)) { + LOG_ERROR("Invalid IPv6 address: %s", addr); + } + } else { + sockaddr_in &inet = m_data_in; + inet.sin_family = AF_INET; + inet.sin_port = htons(port); + void *pAddrBuf = &inet.sin_addr; + if (!::inet_pton(inet.sin_family, ipAddress.c_str(), pAddrBuf)) { + LOG_ERROR("Invalid IPv4 address: %s", addr); + } + } + } + + SocketAddr(SocketAddr const &other) = default; + + SocketAddr &operator=(SocketAddr const &other) = default; + + operator sockaddr *() { return &m_data; } + + operator const sockaddr *() const { return &m_data; } + + size_t size() const { +#ifdef HAVE_UNIX_DOMAIN + // Unix domain struct m_data_un + if (isUnixDomain) + return sizeof(m_data_un); +#endif + // IPv4 struct m_data_in + if (m_data.sa_family == AF_INET) + return sizeof(m_data_in); + // IPv6 struct m_data_in6 + if (m_data.sa_family == AF_INET6) + return sizeof(m_data_in6); + // RAW socket? + return sizeof(m_data); + } + + int port() const { +#ifdef HAVE_UNIX_DOMAIN + if (isUnixDomain) { + return -1; + } +#endif + + switch (m_data.sa_family) { + case AF_INET6: { + return ntohs(m_data_in6.sin6_port); + } + case AF_INET: { + return ntohs(m_data_in.sin_port); + } + default: + return -1; + } + } + + std::string toString() const { + std::ostringstream os; + +#ifdef HAVE_UNIX_DOMAIN + if (isUnixDomain) { + os << (const char *)(m_data_un.sun_path); + } else +#endif + { + switch (m_data.sa_family) { + case AF_INET6: { + char buff[NI_MAXHOST] = {0}; + inet_ntop(AF_INET6, &(m_data_in6.sin6_addr), buff, sizeof(buff)); + os << '[' << buff << ']'; + os << ':' << ntohs(m_data_in6.sin6_port); + break; + } + case AF_INET: { + u_long addr = ntohl(m_data_in.sin_addr.s_addr); + os << (addr >> 24) << '.' << ((addr >> 16) & 255) << '.' + << ((addr >> 8) & 255) << '.' << (addr & 255); + os << ':' << ntohs(m_data_in.sin_port); + break; + } + default: + os << "[?AF?" << m_data.sa_family << ']'; + } + }; + return os.str(); + } +}; // namespace SocketTools + +static const char *kSchemeUDP = "udp"; +static const char *kSchemeTCP = "tcp"; +static const char *kSchemeUnix = "unix"; +static const char *kSchemeUnk = "unknown"; + +struct SocketParams { + int af; // POSIX socket domain + int type; // POSIX socket type + int proto; // POSIX socket protocol + + /** + * @brief Determine connection scheme based on socket parameters: + * "tcp", "udp", "unix" or "unknown". + * + * @return Text representation of scheme. + */ + inline const char *scheme() { + if ((af == AF_INET) || (af == AF_INET6)) { + if (type == SOCK_DGRAM) + return kSchemeUDP; + if (type == SOCK_STREAM) + return kSchemeTCP; + } + if (af == AF_UNIX) { + return kSchemeUnix; + } + return kSchemeUnk; + } +}; + +/// +/// Encapsulation of a socket (non-exclusive ownership) +/// +struct Socket { +#ifdef _WIN32 + typedef SOCKET Type; + static constexpr Type const Invalid = INVALID_SOCKET; +#else + typedef int Type; /* POSIX m_sock type is int */ + static constexpr Type const Invalid = -1; +#endif + + Type m_sock; + + Socket(SocketParams params) : Socket(params.af, params.type, params.proto) {} + + Socket(Type sock = Invalid) : m_sock(sock) {} + + Socket(int af, int type, int proto) { m_sock = ::socket(af, type, proto); } + + ~Socket() {} + + operator Socket::Type() const { return m_sock; } + + bool operator==(Socket const &other) const { + return (m_sock == other.m_sock); + } + + bool operator!=(Socket const &other) const { + return (m_sock != other.m_sock); + } + + bool operator<(Socket const &other) const { return (m_sock < other.m_sock); } + + bool invalid() const { return (m_sock == Invalid); } + + void setNonBlocking() { + assert(m_sock != Invalid); +#ifdef _WIN32 + u_long value = 1; + ::ioctlsocket(m_sock, FIONBIO, &value); +#else + int flags = ::fcntl(m_sock, F_GETFL, 0); + ::fcntl(m_sock, F_SETFL, flags | O_NONBLOCK); +#endif + } + + bool setReuseAddr() { + assert(m_sock != Invalid); +#ifdef _WIN32 + BOOL value = TRUE; +#else + int value = 1; +#endif + return (::setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&value), sizeof(value)) == 0); + } + + bool setNoDelay() { + assert(m_sock != Invalid); +#ifdef _WIN32 + BOOL value = TRUE; +#else + int value = 1; +#endif + return (::setsockopt(m_sock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&value), sizeof(value)) == 0); + } + + bool connect(SocketAddr const &addr) { + assert(m_sock != Invalid); + return (::connect(m_sock, (const sockaddr *)addr, addr.size()) == 0); + } + + void close() { +#ifdef _WIN32 + ::closesocket(m_sock); +#else + ::close(m_sock); +#endif + m_sock = Invalid; + } + + int recvfrom(_Out_cap_(size) void *buffer, size_t size, int flags, + SocketAddr &clientAddr) { + assert(m_sock != Invalid); +#ifdef _WIN32 + int len = clientAddr.size(); +#else + socklen_t len = clientAddr.size(); +#endif + return static_cast(::recvfrom(m_sock, reinterpret_cast(buffer), + size, flags, clientAddr, &len)); + } + + int recv(_Out_cap_(size) void *buffer, size_t size, int flags = 0) { + assert(m_sock != Invalid); + return static_cast( + ::recv(m_sock, reinterpret_cast(buffer), size, flags)); + } + + size_t readall(char *buffer, size_t size) { + size_t total_bytes_received = 0; + int bytes_received = 0; + // Read response fully + do { + bytes_received = recv((void *)(buffer + total_bytes_received), + size - total_bytes_received); + if (bytes_received > 0) { + total_bytes_received += bytes_received; + } else if (bytes_received == 0) { +#ifndef _WIN32 + // recv() on a blocking socket may return EAGAIN in case + // if the call timed out (no data received in time period + // specified as socket timeout) + if (errno == EAGAIN) + continue; +#else + // recv() returns 0 only when 0-byte buffer is requested + // or when the other peer has gracefully disconnected. + // No data received. + break; +#endif + } else { + // recv() error occurred. + break; + } + } while ((bytes_received > 0) && (total_bytes_received < size)); + return total_bytes_received; + } + + size_t writeall(char const *buffer, size_t size) { + size_t total_bytes_sent = 0; + int bytes_sent = 0; + // Write response fully + do { + bytes_sent = + send((void *)(buffer + total_bytes_sent), size - total_bytes_sent); + if (bytes_sent > 0) { + total_bytes_sent += bytes_sent; + } else if (bytes_sent == 0) { + // No more data to send or can't send anymore. + break; + } + if (bytes_sent < 0) { + // send() error occurred. + break; + } + } while (total_bytes_sent < size); + return total_bytes_sent; + } + + int send(void const *buffer, size_t size) { + assert(m_sock != Invalid); + if ((m_sock == Invalid) || (buffer == nullptr) || (size == 0)) + return 0; + return static_cast( + ::send(m_sock, reinterpret_cast(buffer), size, 0)); + } + + int sendto(void const *buffer, size_t size, int flags, SocketAddr &destAddr) { + assert(m_sock != Invalid); + if ((m_sock == Invalid) || (buffer == nullptr) || (size == 0)) + return 0; + int len = destAddr.size(); + return static_cast(::sendto(m_sock, + reinterpret_cast(buffer), + size, flags, destAddr, len)); + } + + int bind(SocketAddr const &addr) { + assert(m_sock != Invalid); + return ::bind(m_sock, addr, addr.size()); + } + + bool getsockname(SocketAddr &addr) const { + assert(m_sock != Invalid); +#ifdef _WIN32 + int addrlen = sizeof(addr); +#else + socklen_t addrlen = sizeof(addr); +#endif + return (::getsockname(m_sock, addr, &addrlen) == 0); + } + + template int getsockopt(int level, int optname, T &optval) { +#ifdef _WIN32 + int optlen = sizeof(T); + return ::getsockopt(m_sock, level, optname, (char *)(&optval), &optlen); +#else + socklen_t optlen = sizeof(T); + return ::getsockopt(m_sock, level, optname, (void *)&optval, &optlen); +#endif + } + + bool listen(size_t backlog) { + assert(m_sock != Invalid); + return (::listen(m_sock, backlog) == 0); + } + + bool accept(Socket &csock, SocketAddr &caddr) { + assert(m_sock != Invalid); +#ifdef _WIN32 + int addrlen = sizeof(caddr); +#else + socklen_t addrlen = sizeof(caddr); +#endif + csock = ::accept(m_sock, caddr, &addrlen); + return !csock.invalid(); + } + + bool shutdown(int how) { + assert(m_sock != Invalid); + return (::shutdown(m_sock, how) == 0); + } + + int error() const { +#ifdef _WIN32 + return ::WSAGetLastError(); +#else + return errno; +#endif + } + + enum { +#ifdef _WIN32 + ErrorWouldBlock = WSAEWOULDBLOCK +#else + ErrorWouldBlock = EWOULDBLOCK +#endif + }; + + enum { +#ifdef _WIN32 + ShutdownReceive = SD_RECEIVE, + ShutdownSend = SD_SEND, + ShutdownBoth = SD_BOTH +#else + ShutdownReceive = SHUT_RD, + ShutdownSend = SHUT_WR, + ShutdownBoth = SHUT_RDWR +#endif + }; +}; + +/// +/// Socket Data +/// +struct SocketData { + Socket socket; + int flags; + + SocketData() : socket(), flags(0) {} + + bool operator==(Socket s) { return (socket == s); } +}; + +/// +/// Socket Reactor +/// +struct Reactor : protected net::Thread { + /// + /// Socket State callback + /// + class SocketCallback { + public: + virtual void onSocketReadable(Socket sock) = 0; + virtual void onSocketWritable(Socket sock) = 0; + virtual void onSocketAcceptable(Socket sock) = 0; + virtual void onSocketClosed(Socket sock) = 0; + }; + + /// + /// Socket State + /// + enum State { Readable = 1, Writable = 2, Acceptable = 4, Closed = 8 }; + + SocketCallback &m_callback; + + std::recursive_mutex m_sockets_mutex; + std::vector m_sockets; + + // Event loop is required for stream sockets + bool m_streaming{true}; + +#ifdef _WIN32 + /* use WinSock events on Windows */ + std::vector m_events{}; +#endif + +#ifdef __linux__ + /* use epoll on Linux */ + int m_epollFd; +#endif + +#ifdef TARGET_OS_MAC + /* use kqueue on Mac */ +#define KQUEUE_SIZE 32 + int kq{0}; + struct kevent m_events[KQUEUE_SIZE]; +#endif + +public: + Reactor(SocketCallback &callback) : m_callback(callback) { +#ifdef __linux__ +#ifdef ANDROID + m_epollFd = ::epoll_create(0); +#else + m_epollFd = ::epoll_create1(0); +#endif +#endif + +#ifdef TARGET_OS_MAC + bzero(&m_events[0], sizeof(m_events)); + kq = kqueue(); +#endif + } + + ~Reactor() { +#ifdef __linux__ + ::close(m_epollFd); +#endif +#ifdef TARGET_OS_MAC + ::close(kq); +#endif + } + + /// + /// Add Socket + /// + /// + /// + void addSocket(const Socket &socket, int flags) { + if (flags == 0) { + removeSocket(socket); + return; + } + + LOCKGUARD(m_sockets_mutex); + if ((flags == State::Readable) && (m_sockets.size() == 0)) { + // No listen/accept - readable UDP datagram + m_streaming = false; + LOG_TRACE("Reactor: Adding datagram socket 0x%x with flags 0x%x", + static_cast(socket), flags); + m_sockets.push_back(SocketData()); + m_sockets.back().socket = socket; + m_sockets.back().flags = 0; + return; + } + + if (m_streaming) { + auto it = std::find(m_sockets.begin(), m_sockets.end(), socket); + if (it == m_sockets.end()) { + LOG_TRACE("Reactor: Adding socket 0x%x with flags 0x%x", + static_cast(socket), flags); +#ifdef _WIN32 + m_events.push_back(::WSACreateEvent()); +#endif +#ifdef __linux__ + epoll_event event = {}; + event.data.fd = socket; + event.events = 0; + if (::epoll_ctl(m_epollFd, EPOLL_CTL_ADD, socket, &event) != 0) { + LOG_ERROR("Reactor: epoll_ctl failed! errno=%d", errno); + } +#endif +#ifdef TARGET_OS_MAC + struct kevent event; + bzero(&event, sizeof(event)); + event.ident = socket.m_sock; + EV_SET(&event, event.ident, EVFILT_READ, EV_ADD, 0, 0, NULL); + kevent(kq, &event, 1, NULL, 0, NULL); + EV_SET(&event, event.ident, EVFILT_WRITE, EV_ADD, 0, 0, NULL); + kevent(kq, &event, 1, NULL, 0, NULL); +#endif + m_sockets.push_back(SocketData()); + m_sockets.back().socket = socket; + m_sockets.back().flags = 0; + it = m_sockets.end() - 1; + } else { + LOG_TRACE("Reactor: Updating socket 0x%x with flags 0x%x", + static_cast(socket), flags); + } + + if (it->flags != flags) { + it->flags = flags; +#ifdef _WIN32 + long lNetworkEvents = 0; + if (it->flags & Readable) { + lNetworkEvents |= FD_READ; + } + if (it->flags & Writable) { + lNetworkEvents |= FD_WRITE; + } + if (it->flags & Acceptable) { + lNetworkEvents |= FD_ACCEPT; + } + if (it->flags & Closed) { + lNetworkEvents |= FD_CLOSE; + } + auto eventIt = m_events.begin() + std::distance(m_sockets.begin(), it); + ::WSAEventSelect(socket, *eventIt, lNetworkEvents); +#endif +#ifdef __linux__ + int events = 0; + if (it->flags & Readable) { + events |= EPOLLIN; + }; + if (it->flags & Writable) { + events |= EPOLLOUT; + }; + if (it->flags & Acceptable) { + events |= EPOLLIN; + }; + // if (it->flags & Closed) - always handled (EPOLLERR | EPOLLHUP) + epoll_event event = {}; + event.data.fd = socket; + event.events = events; + if (::epoll_ctl(m_epollFd, EPOLL_CTL_MOD, socket, &event) != 0) { + LOG_ERROR("Reactor: epoll_ctl failed! errno=%d", errno); + } +#endif +#ifdef TARGET_OS_MAC + // TODO: [MG] - Mac OS X socket doesn't currently support updating flags +#endif + } + } + } + + /// + /// Remove Socket + /// + /// + void removeSocket(const Socket &socket) { + LOCKGUARD(m_sockets_mutex); + LOG_TRACE("Reactor: Removing socket 0x%x", static_cast(socket)); + auto it = std::find(m_sockets.begin(), m_sockets.end(), socket); + if (it != m_sockets.end()) { + if (m_streaming) { +#ifdef _WIN32 + auto eventIt = m_events.begin() + std::distance(m_sockets.begin(), it); + ::WSAEventSelect(it->socket, *eventIt, 0); + ::WSACloseEvent(*eventIt); + m_events.erase(eventIt); +#endif +#ifdef __linux__ + if (::epoll_ctl(m_epollFd, EPOLL_CTL_DEL, socket, nullptr) != 0) { + LOG_ERROR("Reactor: epoll_ctl failed! errno=%d", errno); + }; +#endif +#ifdef TARGET_OS_MAC + struct kevent event; + bzero(&event, sizeof(event)); + event.ident = socket; + EV_SET(&event, socket, EVFILT_READ, EV_DELETE, 0, 0, NULL); + if (-1 == kevent(kq, &event, 1, NULL, 0, NULL)) { + //// Already removed? + LOG_ERROR("cannot delete fd=0x%x from kqueue!", event.ident); + } + EV_SET(&event, socket, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + if (-1 == kevent(kq, &event, 1, NULL, 0, NULL)) { + //// Already removed? + LOG_ERROR("cannot delete fd=0x%x from kqueue!", event.ident); + } +#endif + } + m_sockets.erase(it); + } + } + + /// + /// Start server + /// + void start() { + LOG_INFO("Reactor: Starting..."); + startThread(); + } + + /// + /// Stop server + /// + void stop() { + LOG_INFO("Reactor: Stopping..."); + // If UDP server, then force-close it to stop. + if (!m_streaming) { + LOCKGUARD(m_sockets_mutex); + if (m_sockets.size()) { + m_sockets[0].socket.close(); + } + } + joinThread(); + + // Only acquire the lock after the worker(s) have joined + LOCKGUARD(m_sockets_mutex); +#ifdef _WIN32 + for (auto &hEvent : m_events) { + ::WSACloseEvent(hEvent); + } +#else /* Linux and Mac */ + for (auto &sd : m_sockets) { +#ifdef __linux__ + if (::epoll_ctl(m_epollFd, EPOLL_CTL_DEL, sd.socket, nullptr) != 0) { + LOG_ERROR("Reactor: epoll_ctl failed! errno=%d", errno); + }; +#endif +#ifdef TARGET_OS_MAC + struct kevent event; + bzero(&event, sizeof(event)); + event.ident = sd.socket; + EV_SET(&event, sd.socket, EVFILT_READ, EV_DELETE, 0, 0, NULL); + if (-1 == kevent(kq, &event, 1, NULL, 0, NULL)) { + LOG_ERROR("Reactor: cannot delete fd=0x%x from kqueue!", event.ident); + } + EV_SET(&event, sd.socket, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + if (-1 == kevent(kq, &event, 1, NULL, 0, NULL)) { + LOG_ERROR("Reactor: cannot delete fd=0x%x from kqueue!", event.ident); + } +#endif + } +#endif + // unbind + if (m_sockets.size()) { + m_sockets[0].socket.close(); + } + m_sockets.clear(); + } + + /// + /// Thread Loop for async events processing + /// + virtual void onThread() override { + LOG_INFO("Reactor: Thread started"); + + if (!m_streaming) { + // UDP Server implementation. + // Process only one bound address at the moment, not many. + // This single-threaded implementation passes UDP buffers + // to onSocketReadable, that should decide what to do with + // the socket. Callback may implement its own thread pool. + Socket socket = m_sockets[0].socket; + LOG_TRACE("Reactor: socket 0x%x receive loop started...", + static_cast(socket)); + while (!shouldTerminate()) { + m_callback.onSocketReadable(socket); + } + m_callback.onSocketClosed(socket); + LOG_TRACE("Reactor: socket 0x%x closed.", static_cast(socket)); + return; + } + + while (!shouldTerminate()) { + // TCP and Unix Domain Server implementation. + // + // Use event-based notification with array of client + // bidirectional stream sockets concurrently processed + // by single thread. Facility differs depending on OS: + // + // - Windows: use WSA socket events + // - Linux: use epoll + // - Mac: use kqueue + // +#ifdef _WIN32 + DWORD dwResult = + ::WSAWaitForMultipleEvents(static_cast(m_events.size()), + m_events.data(), FALSE, 500, FALSE); + if (dwResult == WSA_WAIT_TIMEOUT) { + continue; + } + + if (dwResult > WSA_WAIT_EVENT_0 + m_events.size()) { + LOG_WARN("Reactor: stale event on closed socket dwResult=%d", + (int)dwResult); + continue; + } + + int index = dwResult - WSA_WAIT_EVENT_0; + + m_sockets_mutex.lock(); + Socket socket = m_sockets[index].socket; + int flags = m_sockets[index].flags; + m_sockets_mutex.unlock(); + + WSANETWORKEVENTS ne; + ::WSAEnumNetworkEvents(socket, m_events[index], &ne); + LOG_TRACE( + "Reactor: Handling socket 0x%x (index %d) with active flags 0x%x " + "(armed 0x%x)", + static_cast(socket), index, ne.lNetworkEvents, flags); + + if ((flags & Readable) && (ne.lNetworkEvents & FD_READ)) { + m_callback.onSocketReadable(socket); + } + if ((flags & Writable) && (ne.lNetworkEvents & FD_WRITE)) { + m_callback.onSocketWritable(socket); + } + if ((flags & Acceptable) && (ne.lNetworkEvents & FD_ACCEPT)) { + m_callback.onSocketAcceptable(socket); + } + if ((flags & Closed) && (ne.lNetworkEvents & FD_CLOSE)) { + m_callback.onSocketClosed(socket); + } +#endif + +#ifdef __linux__ + { + epoll_event events[4]; + int result = ::epoll_wait(m_epollFd, events, + sizeof(events) / sizeof(events[0]), 500); + if (result == 0) + continue; + if (result < 0) { + LOG_ERROR("Reactor: got errno=%d!", errno); + continue; + }; + assert(result >= 1 && static_cast(result) <= + sizeof(events) / sizeof(events[0])); + + LOCKGUARD(m_sockets_mutex); + for (int i = 0; i < result; i++) { + auto it = + std::find(m_sockets.begin(), m_sockets.end(), events[i].data.fd); + assert(it != m_sockets.end()); + Socket socket = it->socket; + int flags = it->flags; + + LOG_TRACE( + "Reactor: Handling socket 0x%x active flags 0x%x (armed 0x%x)", + static_cast(socket), events[i].events, flags); + + if ((flags & Readable) && (events[i].events & EPOLLIN)) { + m_callback.onSocketReadable(socket); + } + if ((flags & Writable) && (events[i].events & EPOLLOUT)) { + m_callback.onSocketWritable(socket); + } + if ((flags & Acceptable) && (events[i].events & EPOLLIN)) { + m_callback.onSocketAcceptable(socket); + } + if ((flags & Closed) && (events[i].events & (EPOLLHUP | EPOLLERR))) { + LOG_TRACE("Reactor: handling socket 0x%x onSocketClosed", + static_cast(socket)); + m_callback.onSocketClosed(socket); + } + } + } +#endif + +#if defined(TARGET_OS_MAC) + { + LOCKGUARD(m_sockets_mutex); + unsigned waitms = 500; // never block for more than 500ms + struct timespec timeout; + timeout.tv_sec = waitms / 1000; + timeout.tv_nsec = (waitms % 1000) * 1000 * 1000; + + int nev = kevent(kq, NULL, 0, m_events, KQUEUE_SIZE, &timeout); + for (int i = 0; i < nev; i++) { + struct kevent &event = m_events[i]; + int fd = (int)event.ident; + auto it = std::find(m_sockets.begin(), m_sockets.end(), fd); + assert(it != m_sockets.end()); + Socket socket = it->socket; + int flags = it->flags; + + LOG_TRACE("Handling socket 0x%x active flags 0x%x (armed 0x%x)", + static_cast(socket), event.flags, event.fflags); + + if (event.filter == EVFILT_READ) { + if (flags & Acceptable) { + m_callback.onSocketAcceptable(socket); + } + if (flags & Readable) { + m_callback.onSocketReadable(socket); + } + continue; + } + + if (event.filter == EVFILT_WRITE) { + if (flags & Writable) { + m_callback.onSocketWritable(socket); + } + continue; + } + + if ((event.flags & EV_EOF) || (event.flags & EV_ERROR)) { + LOG_TRACE("event.filter=%s", "EVFILT_WRITE"); + m_callback.onSocketClosed(socket); + it->flags = Closed; + struct kevent kevt; + EV_SET(&kevt, event.ident, EVFILT_READ, EV_DELETE, 0, 0, NULL); + if (-1 == kevent(kq, &kevt, 1, NULL, 0, NULL)) { + LOG_ERROR("cannot delete fd=0x%x from kqueue!", event.ident); + } + EV_SET(&kevt, event.ident, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + if (-1 == kevent(kq, &kevt, 1, NULL, 0, NULL)) { + LOG_ERROR("cannot delete fd=0x%x from kqueue!", event.ident); + } + continue; + } + LOG_ERROR("Reactor: unhandled kevent!"); + } + } +#endif + } + LOG_TRACE("Reactor: Thread done"); + } +}; + +} // namespace SocketTools + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h new file mode 100644 index 000000000..b36faf56d --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/exporters/geneva/metrics/connection_string_parser.h" +#include "opentelemetry/exporters/geneva/metrics/data_transport.h" +#include "opentelemetry/exporters/geneva/metrics/socket_tools.h" +#include "opentelemetry/version.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { +class UnixDomainSocketDataTransport : public DataTransport { +public: + UnixDomainSocketDataTransport(const std::string &connection_string); + bool Connect() noexcept override; + bool Send(const char *data, uint16_t length) noexcept override; + bool Disconnect() noexcept override; + +private: + // Socket connection is re-established for every batch of events + const SocketTools::SocketParams socketparams_{AF_UNIX, SOCK_STREAM, 0}; + SocketTools::Socket socket_; + std::unique_ptr addr_; + bool connected_{false}; +}; +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc new file mode 100644 index 000000000..e67a63098 --- /dev/null +++ b/exporters/geneva/src/exporter.cc @@ -0,0 +1,361 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/geneva/metrics/exporter.h" +#include "opentelemetry/exporters/geneva/metrics/macros.h" +#include "opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h" +#include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/sdk_config.h" + +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { +Exporter::Exporter(const ExporterOptions &options) + : options_(options), connection_string_parser_(options_.connection_string), + data_transport_{nullptr}, buffer_index_histogram_(0), + buffer_index_non_histogram_(0) { + if (connection_string_parser_.IsValid()) { + if (connection_string_parser_.transport_protocol_ == + TransportProtocol::kUNIX) { + data_transport_ = + std::unique_ptr(new UnixDomainSocketDataTransport( + connection_string_parser_.url_->path_)); + } + } + // Connect transport at initialization + auto status = data_transport_->Connect(); + if (!status) { + LOG_ERROR("[Geneva Exporter] Connect failed. No data would be sent."); + is_shutdown_ = true; + return; + } + // Initialize non-histogram buffer + buffer_index_non_histogram_ = InitializeBufferForNonHistogramData(); + + // Initialize histogram buffer + buffer_index_histogram_ = InitiaizeBufferForHistogramData(); +} + +sdk::metrics::AggregationTemporality Exporter::GetAggregationTemporality( + sdk::metrics::InstrumentType instrument_type) const noexcept { + return sdk::metrics::AggregationTemporality::kDelta; +} + +opentelemetry::sdk::common::ExportResult Exporter::Export( + const opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept { + auto shutdown = false; + { + const std::lock_guard locked(lock_); + shutdown = is_shutdown_; + } + + if (shutdown) { + OTEL_INTERNAL_LOG_ERROR("[Genava Exporter] Exporting " + << data.scope_metric_data_.size() + << " metric(s) failed, exporter is shutdown"); + return sdk::common::ExportResult::kFailure; + } + + if (data.scope_metric_data_.empty()) { + return sdk::common::ExportResult::kSuccess; + } + + for (auto &record : data.scope_metric_data_) { + for (const auto &metric_data : record.metric_data_) { + for (auto &point_data_with_attributes : metric_data.point_data_attr_) { + size_t body_length = 0; + if (nostd::holds_alternative( + point_data_with_attributes.point_data)) { + auto value = nostd::get( + point_data_with_attributes.point_data); + MetricsEventType event_type = MetricsEventType::ULongMetric; + if (nostd::holds_alternative(value.value_)) { + event_type = MetricsEventType::DoubleMetric; + } + + body_length = SerializeNonHistogramMetrics( + sdk::metrics::AggregationType::kSum, event_type, value.value_, + metric_data.end_ts, metric_data.instrument_descriptor.name_, + point_data_with_attributes.attributes); + data_transport_->Send(buffer_non_histogram_, + body_length + kBinaryHeaderSize); + + } else if (nostd::holds_alternative( + point_data_with_attributes.point_data)) { + auto value = nostd::get( + point_data_with_attributes.point_data); + MetricsEventType event_type = MetricsEventType::ULongMetric; + if (nostd::holds_alternative(value.value_)) { + event_type = MetricsEventType::DoubleMetric; + } + body_length = SerializeNonHistogramMetrics( + sdk::metrics::AggregationType::kLastValue, event_type, + value.value_, metric_data.end_ts, + metric_data.instrument_descriptor.name_, + point_data_with_attributes.attributes); + data_transport_->Send(buffer_non_histogram_, + body_length + kBinaryHeaderSize); + } else if (nostd::holds_alternative( + point_data_with_attributes.point_data)) { + auto value = nostd::get( + point_data_with_attributes.point_data); + MetricsEventType event_type = + MetricsEventType::ExternallyAggregatedULongDistributionMetric; + if (nostd::holds_alternative(value.sum_)) { + LOG_ERROR("Geneva Exporter::Export- Double value is not supported " + "for Histogram"); + continue; + } + body_length = SerializeHistogramMetrics( + sdk::metrics::AggregationType::kHistogram, event_type, + value.count_, value.sum_, value.min_, value.max_, + nostd::get( + point_data_with_attributes.point_data) + .boundaries_, + nostd::get( + point_data_with_attributes.point_data) + .counts_, + metric_data.end_ts, metric_data.instrument_descriptor.name_, + point_data_with_attributes.attributes); + data_transport_->Send(buffer_histogram_, + body_length + kBinaryHeaderSize); + } + } + } + } + return opentelemetry::sdk::common::ExportResult::kSuccess; +} + +bool Exporter::ForceFlush(std::chrono::microseconds timeout) noexcept { + return true; +} + +bool Exporter::Shutdown(std::chrono::microseconds timeout) noexcept { + const std::lock_guard locked(lock_); + is_shutdown_ = true; + return true; +} + +size_t Exporter::InitializeBufferForNonHistogramData() { + // The buffer format is as follows: + // -- BinaryHeader + // -- MetricPayload + // -- Variable length content + + // Leave enough space for the header and fixed payload + auto bufferIndex = kBinaryHeaderSize + kMetricPayloadSize; + SerializeString(buffer_non_histogram_, bufferIndex, + connection_string_parser_.account_); + SerializeString(buffer_non_histogram_, bufferIndex, + connection_string_parser_.namespace_); + return bufferIndex; +} + +size_t Exporter::InitiaizeBufferForHistogramData() { + // The buffer format is as follows: + // -- BinaryHeader + // -- ExternalPayload + // -- Variable length content + + // Leave enough space for the header and fixed payload + auto bufferIndex = kBinaryHeaderSize + kExternalPayloadSize; + SerializeString(buffer_histogram_, bufferIndex, + connection_string_parser_.account_); + SerializeString(buffer_histogram_, bufferIndex, + connection_string_parser_.namespace_); + return bufferIndex; +} + +size_t Exporter::SerializeNonHistogramMetrics( + sdk::metrics::AggregationType agg_type, MetricsEventType event_type, + const sdk::metrics::ValueType &value, common::SystemTimestamp ts, + const std::string& metric_name, const sdk::metrics::PointAttributes &attributes) { + auto bufferIndex = buffer_index_non_histogram_; + SerializeString(buffer_non_histogram_, bufferIndex, metric_name); + for (const auto &kv : attributes) { + if (kv.first.size() > kMaxDimensionNameSize) { + LOG_WARN("Dimension name limit overflow: %s Limit %d", kv.first.c_str(), kMaxDimensionNameSize); + continue; + } + SerializeString(buffer_non_histogram_, bufferIndex, kv.first); + } + for (const auto &kv : attributes) { + auto attr_value = AttributeValueToString(kv.second); + SerializeString(buffer_non_histogram_, bufferIndex, attr_value); + } + // length zero for auto-pilot + SerializeInt(buffer_non_histogram_, bufferIndex, 0); + + // get final size of payload to be added in front of buffer + uint16_t body_length = bufferIndex - kBinaryHeaderSize; + + // Add rest of the fields in front of buffer + bufferIndex = 0; + + // event_type + SerializeInt(buffer_non_histogram_, bufferIndex, + static_cast(event_type)); + + // body length + SerializeInt(buffer_non_histogram_, bufferIndex, + static_cast(body_length)); + + // count of dimensions. + SerializeInt(buffer_non_histogram_, bufferIndex, + static_cast(attributes.size())); + + // reserverd word (2 bytes) + SerializeInt(buffer_non_histogram_, bufferIndex, 0); + + // reserved word (4 bytes) + SerializeInt(buffer_non_histogram_, bufferIndex, 0); + + // timestamp utc (8 bytes) + auto windows_ticks = UnixTimeToWindowsTicks( + std::chrono::duration_cast>( + ts.time_since_epoch()) + .count()); + + SerializeInt(buffer_non_histogram_, bufferIndex, windows_ticks); + if (event_type == MetricsEventType::ULongMetric) { + SerializeInt(buffer_non_histogram_, bufferIndex, + static_cast(nostd::get(value))); + } else { + SerializeInt( + buffer_non_histogram_, bufferIndex, + *(reinterpret_cast(&(nostd::get(value))))); + } + return body_length; +} + +size_t Exporter::SerializeHistogramMetrics( + sdk::metrics::AggregationType agg_type, MetricsEventType event_type, + uint64_t count, const sdk::metrics::ValueType &sum, + const sdk::metrics::ValueType &min, const sdk::metrics::ValueType &max, + const std::list &boundaries, const std::vector &counts, + common::SystemTimestamp ts, const std::string &metric_name, + const sdk::metrics::PointAttributes &attributes) { + + auto bufferIndex = buffer_index_histogram_; + // metric name + SerializeString(buffer_histogram_, bufferIndex, metric_name); + + // dimentions - name + for (const auto &kv : attributes) { + if (kv.first.size() > kMaxDimensionNameSize) { + LOG_WARN("Dimension name limit overflow: %s Limit: %d", kv.first.c_str(), kMaxDimensionNameSize); + continue; + } + SerializeString(buffer_histogram_, bufferIndex, kv.first); + } + + // dimentions - value + for (const auto &kv : attributes) { + auto attr_value = AttributeValueToString(kv.second); + SerializeString(buffer_histogram_, bufferIndex, attr_value); + } + + // two bytes padding for auto-pilot + SerializeInt(buffer_histogram_, bufferIndex, 0); + + // version - set as 0 + SerializeInt(buffer_histogram_, bufferIndex, 0); + + // Meta-data + // Value-count pairs is associated with the constant value of 2 in the + // distribution_type enum. + SerializeInt(buffer_histogram_, bufferIndex, 2); + + // Keep a position to record how many buckets are added + auto itemsWrittenIndex = bufferIndex; + SerializeInt(buffer_histogram_, bufferIndex, 0); + + // bucket values + size_t index = 0; + uint16_t bucket_count = 0; + if (event_type == + MetricsEventType::ExternallyAggregatedULongDistributionMetric) { + for (auto boundary : boundaries) { + if (counts[index] > 0) { + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(boundary)); + SerializeInt(buffer_histogram_, bufferIndex, + (uint32_t)(counts[index])); + bucket_count++; + } + index++; + } + } + + // write bucket count to previous preserved index + SerializeInt(buffer_histogram_, itemsWrittenIndex, bucket_count); + + // get final size of payload to be added in front of buffer + uint16_t body_length = bufferIndex - kBinaryHeaderSize; + + // Add rest of the fields in front of buffer + bufferIndex = 0; + + // event_type + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(event_type)); + + // body length + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(body_length)); + + // count of dimensions. + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(attributes.size())); + + // reserverd word (2 bytes) + SerializeInt(buffer_histogram_, bufferIndex, 0); + + // count of events + SerializeInt(buffer_histogram_, bufferIndex, count); + + // timestamp utc (8 bytes) + auto windows_ticks = UnixTimeToWindowsTicks( + std::chrono::duration_cast>( + ts.time_since_epoch()) + .count()); + SerializeInt(buffer_histogram_, bufferIndex, windows_ticks); + + // sum, min, max + + if (event_type == + MetricsEventType::ExternallyAggregatedULongDistributionMetric) { + // sum + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(nostd::get(sum))); + // min + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(nostd::get(min))); + // max + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(nostd::get(max))); + } else { + // sum + SerializeInt( + buffer_histogram_, bufferIndex, + *(reinterpret_cast(&(nostd::get(sum))))); + // min + SerializeInt( + buffer_histogram_, bufferIndex, + *(reinterpret_cast(&(nostd::get(min))))); + // max + SerializeInt( + buffer_histogram_, bufferIndex, + *(reinterpret_cast(&(nostd::get(max))))); + } + return body_length; +} + +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/geneva/src/unix_domain_socket_data_transport.cc b/exporters/geneva/src/unix_domain_socket_data_transport.cc new file mode 100644 index 000000000..120f85e61 --- /dev/null +++ b/exporters/geneva/src/unix_domain_socket_data_transport.cc @@ -0,0 +1,73 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h" +#include "opentelemetry/exporters/geneva/metrics/macros.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { + +UnixDomainSocketDataTransport::UnixDomainSocketDataTransport( + const std::string &connection_string) { + addr_.reset(new SocketTools::SocketAddr(connection_string.c_str(), true)); +} + +bool UnixDomainSocketDataTransport::Connect() noexcept { + if (!connected_) { + socket_ = SocketTools::Socket(socketparams_); + connected_ = socket_.connect(*addr_); + if (!connected_) { + LOG_ERROR("Geneva Exporter: UDS::Connect failed"); + return false; + } + } + return true; +} + +bool UnixDomainSocketDataTransport::Send(char const *data, + uint16_t length) noexcept { + int error_code = 0; + if (connected_) { + socket_.getsockopt(SOL_SOCKET, SO_ERROR, error_code); + } else { + LOG_WARN( + "Geneva Exporter: UDS::Send Socket disconnected - Trying to connect"); + auto status = Connect(); + if (!status) { + LOG_WARN( + "Geneva Exporter: UDS::Send Socket reconnect failed. Send failed"); + } + } + if (error_code != 0) { + LOG_ERROR("Geneva Exporter: UDS::Send failed - not connected"); + connected_ = false; + } + + // try to write + size_t sent_size = socket_.writeall(data, length); + if (length == sent_size) { + // Disconnect(); + return true; + } else { + LOG_ERROR("Geneva Exporter: UDS::Send failed"); + } + return false; +} + +bool UnixDomainSocketDataTransport::Disconnect() noexcept { + if (connected_) { + connected_ = false; + if (socket_.invalid()) { + socket_.close(); + return true; + } + } + LOG_WARN("Geneva Exporter: Already disconnected"); + return false; +} +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/test/common/generate_metrics.h b/exporters/geneva/test/common/generate_metrics.h new file mode 100644 index 000000000..1f1214b4c --- /dev/null +++ b/exporters/geneva/test/common/generate_metrics.h @@ -0,0 +1,177 @@ +#include "opentelemetry/sdk/metrics/data/metric_data.h" +#include "opentelemetry/sdk/metrics/export/metric_producer.h" +#include "opentelemetry/sdk/metrics/instruments.h" +#include "opentelemetry/sdk/resource/resource.h" + +namespace { + +// Instrument Scope +const std::string kInstrumentScopeName = "test_lib"; +const std::string kInstrumentScopeVer = "1.5.0"; + +// Counter Instrument of double type +const std::string kCounterDoubleInstrumentName = + "test_instrument_couter_double_name"; +const std::string kCounterDoubleInstrumentDesc = + "test_instrument_counter_double_desc"; +const std::string kCounterDoubleInstrumentUnit = + "test_instrument_conter_double_unit"; +const double kCounterDoubleValue1 = 10.2; +const double kCounterDoubleValue2 = 20.2; +const std::string kCounterDoubleAttributeKey1 = "counter_double_key1"; +const std::string kCounterDoubleAttributeValue1 = "counter_double_value1"; +const std::string kCounterDoubleAttributeKey2 = "counter_double_key2"; +const std::string kCounterDoubleAttributeValue2 = "counter_double_value2"; +const std::string kCounterDoubleAttributeKey3 = "counter_double_key3"; +const std::string kCounterDoubleAttributeValue3 = "counter_double_value3"; +const uint16_t kCounterDoubleCountDimensions = 1; +const uint16_t kCounterDoubleEventId = 55; + +static inline opentelemetry::sdk::metrics::ResourceMetrics +GenerateSumDataDoubleMetrics() { + + opentelemetry::sdk::metrics::SumPointData sum_point_data1{}; + sum_point_data1.value_ = kCounterDoubleValue1; + opentelemetry::sdk::metrics::SumPointData sum_point_data2{}; + sum_point_data2.value_ = kCounterDoubleValue2; + opentelemetry::sdk::metrics::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::MetricData metric_data{ + opentelemetry::sdk::metrics::InstrumentDescriptor{ + kCounterDoubleInstrumentName, kCounterDoubleInstrumentDesc, + kCounterDoubleInstrumentUnit, + opentelemetry::sdk::metrics::InstrumentType::kCounter, + opentelemetry::sdk::metrics::InstrumentValueType::kDouble}, + opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + std::vector{ + {opentelemetry::sdk::metrics::PointAttributes{ + {kCounterDoubleAttributeKey1, kCounterDoubleAttributeValue1}}, + sum_point_data1}, + {opentelemetry::sdk::metrics::PointAttributes{ + {kCounterDoubleAttributeKey2, kCounterDoubleAttributeValue2}, + {kCounterDoubleAttributeKey3, kCounterDoubleAttributeValue3}}, + sum_point_data2}}}; + data.scope_metric_data_ = + std::vector{ + {scope.get(), + std::vector{metric_data}}}; + return data; +} + +// Counter Instrument of long type +const std::string kCounterLongInstrumentName = + "test_instrument_couter_long_name"; +const std::string kCounterLongInstrumentDesc = + "test_instrument_counter_long_desc"; +const std::string kCounterLongInstrumentUnit = + "test_instrument_conter_long_unit"; +const long kCounterLongValue = 102; +const std::string kCounterLongAttributeKey1 = "counter_long_key1"; +const std::string kCounterLongAttributeValue1 = "counter_long_value1"; + +const uint16_t kCounterLongCountDimensions = 1; +const uint16_t kCounterLongEventId = 50; + +static inline opentelemetry::sdk::metrics::ResourceMetrics +GenerateSumDataLongMetrics() { + + opentelemetry::sdk::metrics::SumPointData sum_point_data{}; + sum_point_data.value_ = kCounterLongValue; + opentelemetry::sdk::metrics::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::MetricData metric_data{ + opentelemetry::sdk::metrics::InstrumentDescriptor{ + kCounterLongInstrumentName, kCounterLongInstrumentDesc, + kCounterLongInstrumentUnit, + opentelemetry::sdk::metrics::InstrumentType::kCounter, + opentelemetry::sdk::metrics::InstrumentValueType::kLong}, + opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + std::vector{ + {opentelemetry::sdk::metrics::PointAttributes{ + {kCounterLongAttributeKey1, kCounterLongAttributeValue1}}, + sum_point_data}}}; + data.scope_metric_data_ = + std::vector{ + {scope.get(), + std::vector{metric_data}}}; + return data; +} + +// Histogram Instrument of type long +const std::string kHistogramLongInstrumentName = + "test_instrument_histogram_long_name"; +const std::string kHistogramLongInstrumentDesc = + "test_instrument_histogram_long_desc"; +const std::string kHistogramLongInstrumentUnit = + "test_instrument_histogram_long_unit"; + +const long kHistogramLongSum = 4024l; +const long kHistogramLongMin = 3l; +const long kHistogramLongMax = 1004l; +const size_t kHistogramLongCount = 10l; +const uint16_t kHistogramLongBucketSize = 10; +const uint16_t kHistogramLongNonEmptyBucketSize = 8; +const std::vector kHistogramLongCounts = {1, 2, 1, 0, 0, + 1, 2, 3, 4, 1}; +const std::list kHistogramLongBoundaries = std::list{ + 0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 1000.0}; + +const std::string kHistogramLongAttributeKey1 = "histogram_long_key1"; +const std::string kHistogramLongAttributeValue1 = "histogram_long_value1"; + +const uint16_t kHistogramLongCountDimensions = 1; +const uint16_t kHistogramLongEventId = 56; + +static inline opentelemetry::sdk::metrics::ResourceMetrics +GenerateHistogramDataLongMetrics() { + + opentelemetry::sdk::metrics::HistogramPointData histogram_point_data{}; + histogram_point_data.sum_ = kHistogramLongSum; + histogram_point_data.boundaries_ = kHistogramLongBoundaries; + histogram_point_data.count_ = kHistogramLongCount; + histogram_point_data.min_ = kHistogramLongMin; + histogram_point_data.max_ = kHistogramLongMax; + histogram_point_data.counts_ = kHistogramLongCounts; + + opentelemetry::sdk::metrics::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::MetricData metric_data{ + opentelemetry::sdk::metrics::InstrumentDescriptor{ + kHistogramLongInstrumentName, kHistogramLongInstrumentDesc, + kHistogramLongInstrumentUnit, + opentelemetry::sdk::metrics::InstrumentType::kHistogram, + opentelemetry::sdk::metrics::InstrumentValueType::kLong}, + opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + std::vector{ + {opentelemetry::sdk::metrics::PointAttributes{ + {kHistogramLongAttributeKey1, kHistogramLongAttributeValue1}}, + histogram_point_data}}}; + data.scope_metric_data_ = + std::vector{ + {scope.get(), + std::vector{metric_data}}}; + return data; +} + +} // namespace \ No newline at end of file diff --git a/exporters/geneva/test/common/socket_server.h b/exporters/geneva/test/common/socket_server.h new file mode 100644 index 000000000..ce4ccd1dc --- /dev/null +++ b/exporters/geneva/test/common/socket_server.h @@ -0,0 +1,420 @@ +// Copyright 2021, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef SOCKET_SERVER_H +#define SOCKET_SERVER_H + +/** + * Socket server intended to be used for local loopback test purposes. + * Default namespace is: "testing". You can override it using: + * `#define SOCKET_SERVER_NS alternate_namespace_to_use` + */ +#ifndef SOCKET_SERVER_NS +#define SOCKET_SERVER_NS testing +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "opentelemetry/exporters/geneva/metrics/macros.h" +#include "opentelemetry/exporters/geneva/metrics/socket_tools.h" + +using namespace SocketTools; + +namespace SOCKET_SERVER_NS { + +/** + * @brief Common Server for TCP, UDP and Unix Domain. + */ +struct SocketServer : public Reactor::SocketCallback { + struct Connection { + enum State { + Idle, // No data transfer initiated + Receiving, // Receiving data + Responding, // Sending data + Closing, // Closing connection + Closed, // Closed connection + Aborted // Connection aborted + }; + + Socket socket; // Active client-server socket + SocketAddr client; // Client address + + std::string request_buffer; // Receive buffer for current event + std::string response_buffer; // Send buffer for current event + + std::set state; // Current connection state + bool keepalive{true}; // Keep connection alive (reserved for future use) + }; + + SocketAddr bind_address; // Server bind address + bool is_bound{false}; + SocketParams server_socket_params; // Server socket params + Socket server_socket; // Server listening socket + Reactor reactor; // Socket event handler + + // Custom callback when server receives data + std::function onRequest; + + // Custom callback when server sends a response + std::function onResponse; + + // Active client-server connections protected by recursive mutex + std::recursive_mutex connections_mutex; + std::map connections; + + // Macro to safely obtain TEMPORARY string buffer pointer +#define CLID(conn) conn.client.toString().c_str() + + const SocketAddr &address() const { return bind_address; }; + + /** + * @brief Route to start TCP, UDP or Unix Domain socket server. + * @param addr Address or Unix domain socket name to bind to. + * @param sock Socket type. + * @param numConnections Maximum number of connections. + */ + SocketServer(SocketAddr addr, SocketParams params, int numConnections = 10) + : bind_address(addr), server_socket_params(params), reactor(*this) { + server_socket = Socket(server_socket_params); + + // Default lambda here implements an echo server + onRequest = [this](Connection &conn) { + conn.state.insert(SocketServer::Connection::Responding); + }; + + onResponse = [this](Connection &) { + // Empty response + }; + + int rc = server_socket.bind(bind_address); + if (rc != 0) { + LOG_ERROR("Server: bind failed! result=%d", rc); + return; + } + + is_bound = true; + LOG_INFO("Server: bind successful. result=%d", rc); + server_socket.getsockname(bind_address); + if (server_socket_params.type == SOCK_STREAM) { + // In TCP and Unix Domain mode we listen and accept. + reactor.addSocket(server_socket, Reactor::Acceptable); + server_socket.listen(numConnections); + } else { + // In UDP mode we read in a loop, no need to accept. + reactor.addSocket(server_socket, Reactor::Readable); + } + + LOG_INFO("Server: Listening on %s://%s", server_socket_params.scheme(), + bind_address.toString().c_str()); + } + + /** + * @brief Start server. + */ + void Start() { reactor.start(); } + + /** + * @brief Stop server. + */ + void Stop() { reactor.stop(); } + + /** + * @brief Handle Reactor::State::Acceptable event. + * @param socket Client socket. + */ + virtual void onSocketAcceptable(Socket socket) override { + LOG_TRACE("Server: accepting socket fd=0x%llx", socket.m_sock); + + Socket csocket; + SocketAddr caddr; + if (socket.accept(csocket, caddr)) { +#ifdef HAVE_UNIX_DOMAIN + // If server is Unix domain, then the client socket is also Unix domain + if (bind_address.isUnixDomain) { + caddr.isUnixDomain = bind_address.isUnixDomain; + // Sometimes AF_UNIX does not auto-populate + // the bind address on accept. Thus, copy. + std::copy(std::begin(bind_address.m_data_un.sun_path), + std::end(bind_address.m_data_un.sun_path), + std::begin(caddr.m_data_un.sun_path)); + }; +#endif + + LOCKGUARD(connections_mutex); + csocket.setNonBlocking(); + Connection &conn = connections[csocket]; + conn.socket = csocket; + conn.state = {Connection::Idle}; + conn.client = caddr; + reactor.addSocket(csocket, Reactor::Readable | Reactor::Closed); + LOG_TRACE("Server: [%s] accepted", CLID(conn)); + } + } + + /** + * @brief Handle Reactor::State::Reasable event. + * @param socket Client socket. + */ + virtual void onSocketReadable(Socket socket) override { + LOG_TRACE("Server: reading socket fd=0x%x", + static_cast(socket.m_sock)); + int size = 0; + decltype(connections)::iterator it; + { + LOCKGUARD(connections_mutex); + it = connections.find(socket); + } + if (it != connections.end()) { + // TCP or Unix domain connection. + Connection &conn_tcp = it->second; + ReadStreamBuffer(conn_tcp); + onRequest(conn_tcp); + HandleConnection(conn_tcp); + } else { + // UDP datagram connection. + // Read the contents in one shot. + Connection conn_udp; + conn_udp.socket = socket; + conn_udp.state = {Connection::Receiving}; + ReadDatagramBuffer(conn_udp); + onRequest(conn_udp); + HandleConnection(conn_udp); + } + } + + /** + * @brief Event triggered when server may write data back to client. + * @param socket Client socket. + */ + virtual void onSocketWritable(Socket socket) override { + LOG_TRACE("Server: writing socket fd=0x%llx", socket.m_sock); + decltype(connections)::iterator it; + { + LOCKGUARD(connections_mutex); + it = connections.find(socket); + if (it == connections.end()) { + LOG_ERROR("Server: socket not found in connections map!"); + return; + } + } + Connection &conn = it->second; + conn.state.insert(Connection::Responding); + HandleConnection(conn); + } + + /** + * @brief Handle event when socket is closed. + * @param socket + */ + virtual void onSocketClosed(Socket socket) override { + LOG_TRACE("Server: closing socket fd=0x%llx", socket.m_sock); + LOCKGUARD(connections_mutex); + auto it = connections.find(socket); + if (it != connections.end()) { + Connection &conn = it->second; + conn.state.insert(Connection::Closing); + HandleConnection(conn); + return; + } + LOG_ERROR("Server: socket not found in connections map!"); + } + + /** + * @brief Read from TCP or Unix Domain connection into request_buffer. + * This function invokes `HandleConnection` to process the buffer. + * + * @param conn_tcp Connection object. + */ + virtual void ReadStreamBuffer(Connection &conn_tcp) { + conn_tcp.request_buffer.clear(); + conn_tcp.request_buffer.resize(4096, 0); + size_t size = conn_tcp.socket.readall( + const_cast(conn_tcp.request_buffer.data()), + conn_tcp.request_buffer.size()); + if (size > 0) { + LOG_TRACE("Server: [%s] stream read %zu bytes", CLID(conn_tcp), size); + conn_tcp.request_buffer.resize(size); + // Handle connection: process request_buffer + conn_tcp.state.insert(Connection::Receiving); + } else { + conn_tcp.request_buffer.resize(0); + LOG_ERROR("Server: [%s] failed to read client stream, errno=%d", + CLID(conn_tcp), errno); + conn_tcp.state.insert(Connection::Closing); + } + } + + /** + * @brief Read from UDP connection into request_buffer. + * This function invokes `HandleConnection` to process the buffer. + * + * @param conn_udp + */ + virtual void ReadDatagramBuffer(Connection &conn_udp) { + // Maximum size is 0xffff - (sizeof(IP Header) + sizeof(UDP Header)). + // Try to read the entire datagram. + conn_udp.request_buffer.resize(0xffff); + int size = conn_udp.socket.recvfrom( + (void *)(conn_udp.request_buffer.data()), 0xffff, 0, conn_udp.client); + if (size > 0) { + LOG_ERROR("Server: [%s] datagram read %d bytes", CLID(conn_udp), size); + conn_udp.request_buffer.resize(size); + // Handle connection: process request_buffer + conn_udp.state.insert(Connection::Receiving); + } else { + conn_udp.request_buffer.resize(0); + LOG_ERROR("Server: [%s] failed to read client datagram", CLID(conn_udp)); + } + } + + /** + * @brief Handle a timeslice of sending data back to client. If sending is + * blocked, but not all data has been sent, then this function returns with an + * indication that it needs to be called for the same connection again. + * + * @param conn Client-server connection. + * + * @return true if not all data has been bytes_sent. + */ + bool WriteResponseBuffer(Connection &conn) { + if (conn.response_buffer.empty()) { + LOG_TRACE("Server: [%s] response blocked, empty response buffer!", + CLID(conn)); + return false; + } + + size_t total_bytes_sent = 0; + uint32_t optval = 0; + + conn.socket.getsockopt(SOL_SOCKET, SO_TYPE, optval); + + // Handle UDP response + if (optval == SOCK_DGRAM) { + total_bytes_sent = conn.socket.sendto( + conn.response_buffer.data(), + static_cast(conn.response_buffer.size()), 0, conn.client); + LOG_TRACE("Server: [%s] datagram sent %zu bytes", CLID(conn), + total_bytes_sent); + return false; + } + + // Handle TCP and Unix Domain response + reactor.addSocket(conn.socket, SocketTools::Reactor::Writable); + total_bytes_sent = conn.socket.writeall(conn.response_buffer.data(), + conn.request_buffer.size()); + if (conn.response_buffer.size() != total_bytes_sent) { + conn.response_buffer.erase(0, total_bytes_sent); + LOG_WARN("Server: [%s] response blocked, total sent %zu bytes", + CLID(conn), total_bytes_sent); + // Need to send more + conn.state.insert(Connection::Responding); + return true; + } + + // Done sending + conn.state.erase(Connection::Responding); + conn.state.insert(Connection::Idle); + LOG_TRACE("Server: [%s] response complete, total sent %zu bytes", + CLID(conn), total_bytes_sent); + return false; + } + + /** + * @brief Handle event when connection is closed. + * @param conn + */ + void onConnectionClosed(Connection &conn) { + LOG_TRACE("Server: [%s] connection closing...", CLID(conn)); + if ((!conn.state.count(Connection::Idle)) && + (!conn.state.count(Connection::Closing))) { + conn.state = {Connection::Aborted}; + onConnectionAborted(conn); + } + + // reactor.addSocket(conn.socket, SocketTools::Reactor::Closed); + + reactor.removeSocket(conn.socket); + LOCKGUARD(connections_mutex); + auto it = connections.find(conn.socket); + conn.socket.close(); + conn.state.clear(); + conn.state.insert(Connection::Closed); + LOG_TRACE("Server: [%s] connection closed.", CLID(conn)); + if (it != connections.end()) { + connections.erase(it); + } + } + + void onConnectionAborted(Connection &conn) { + LOG_WARN("Server: [%s] connection closed unexpectedly", CLID(conn)); + } + + void CloseConnection(Connection &conn) { + LOG_TRACE("Server: [%s] closing connection...", CLID(conn)); + conn.socket.shutdown(SocketTools::Socket::ShutdownSend); + onConnectionClosed(conn); + } + + /** + * @brief Handle connection state update. + * + * Connection states: + * - Idle - start receiving. + * - Receiving - handle client request. + * - Responding - respond back to client. + * - Closing - closing connection. + * - Closed - connection closed. + * + * @param conn + */ + void HandleConnection(Connection &conn) { + + if (conn.state.count(Connection::Responding)) { + reactor.addSocket(conn.socket, Reactor::Writable | Reactor::Closed); + // Got data to send back + LOG_TRACE("Server: [%s] responding...", CLID(conn)); + // If WriteResponseBuffer returns true, then more data to send. + if (WriteResponseBuffer(conn)) { + return; + } + // No more data to send. Stop responding. + conn.state.erase(Connection::Responding); + reactor.addSocket(conn.socket, Reactor::Readable | Reactor::Closed); + } + + if (conn.state.count(Connection::Closing)) { + onConnectionClosed(conn); + return; + } + + // If we are done responding, we may need to keep the socket open + if (conn.keepalive) { + LOG_TRACE("Server: [%s] idle (keep-alive)", CLID(conn)); + reactor.addSocket(conn.socket, + SocketTools::Reactor::Readable | Reactor::Closed); + conn.state.insert(Connection::Idle); + } + } +}; +} // namespace SOCKET_SERVER_NS +#endif diff --git a/exporters/geneva/test/decoder/ifx_metrics_bin.cpp b/exporters/geneva/test/decoder/ifx_metrics_bin.cpp new file mode 100644 index 000000000..7ed70c4d2 --- /dev/null +++ b/exporters/geneva/test/decoder/ifx_metrics_bin.cpp @@ -0,0 +1,486 @@ +// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild + +#include "ifx_metrics_bin.h" + +ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = this; + m_body = 0; + m__io__raw_body = 0; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::_read() { + m_event_id = m__io->read_u2le(); + m_len_body = m__io->read_u2le(); + m__raw_body = m__io->read_bytes(len_body()); + m__io__raw_body = new kaitai::kstream(m__raw_body); + m_body = new userdata_t(event_id(), m__io__raw_body, this, m__root); +} + +ifx_metrics_bin_t::~ifx_metrics_bin_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::_clean_up() { + if (m__io__raw_body) { + delete m__io__raw_body; m__io__raw_body = 0; + } + if (m_body) { + delete m_body; m_body = 0; + } +} + +ifx_metrics_bin_t::userdata_t::userdata_t(uint16_t p_event_id, kaitai::kstream* p__io, ifx_metrics_bin_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + m_event_id = p_event_id; + m_metric_account = 0; + m_metric_namespace = 0; + m_metric_name = 0; + m_dimensions_names = 0; + m_dimensions_values = 0; + m_ap_container = 0; + m_histogram = 0; + f_event_type = false; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::userdata_t::_read() { + m_num_dimensions = m__io->read_u2le(); + m_padding = m__io->read_bytes(2); + n_value_section = true; + switch (event_type()) { + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_SCALED_TO_LONG_DISTRIBUTION_METRIC: { + n_value_section = false; + m_value_section = new ext_aggregated_double_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_DOUBLE_METRIC: { + n_value_section = false; + m_value_section = new single_double_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_ULONG_METRIC: { + n_value_section = false; + m_value_section = new ext_aggregated_uint64_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_ULONG_DISTRIBUTION_METRIC: { + n_value_section = false; + m_value_section = new ext_aggregated_uint64_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_DISTRIBUTION_METRIC: { + n_value_section = false; + m_value_section = new ext_aggregated_double_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_DOUBLE_SCALED_TO_LONG_METRIC: { + n_value_section = false; + m_value_section = new single_double_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_UINT64_METRIC: { + n_value_section = false; + m_value_section = new single_uint64_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_METRIC: { + n_value_section = false; + m_value_section = new ext_aggregated_double_value_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::METRIC_EVENT_TYPE_OLD_IFX: { + n_value_section = false; + m_value_section = new single_uint64_value_t(m__io, this, m__root); + break; + } + } + m_metric_account = new len_string_t(m__io, this, m__root); + m_metric_namespace = new len_string_t(m__io, this, m__root); + m_metric_name = new len_string_t(m__io, this, m__root); + int l_dimensions_names = num_dimensions(); + m_dimensions_names = new std::vector(); + m_dimensions_names->reserve(l_dimensions_names); + for (int i = 0; i < l_dimensions_names; i++) { + m_dimensions_names->push_back(new len_string_t(m__io, this, m__root)); + } + int l_dimensions_values = num_dimensions(); + m_dimensions_values = new std::vector(); + m_dimensions_values->reserve(l_dimensions_values); + for (int i = 0; i < l_dimensions_values; i++) { + m_dimensions_values->push_back(new len_string_t(m__io, this, m__root)); + } + n_ap_container = true; + if (!(_io()->is_eof())) { + n_ap_container = false; + m_ap_container = new len_string_t(m__io, this, m__root); + } + n_histogram = true; + if ( (( ((event_type() == ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_ULONG_DISTRIBUTION_METRIC) || (event_type() == ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_DISTRIBUTION_METRIC) || (event_type() == ifx_metrics_bin_t::METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_SCALED_TO_LONG_DISTRIBUTION_METRIC)) ) && (!(_io()->is_eof()))) ) { + n_histogram = false; + m_histogram = new histogram_t(m__io, this, m__root); + } +} + +ifx_metrics_bin_t::userdata_t::~userdata_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::userdata_t::_clean_up() { + if (!n_value_section) { + if (m_value_section) { + delete m_value_section; m_value_section = 0; + } + } + if (m_metric_account) { + delete m_metric_account; m_metric_account = 0; + } + if (m_metric_namespace) { + delete m_metric_namespace; m_metric_namespace = 0; + } + if (m_metric_name) { + delete m_metric_name; m_metric_name = 0; + } + if (m_dimensions_names) { + for (std::vector::iterator it = m_dimensions_names->begin(); it != m_dimensions_names->end(); ++it) { + delete *it; + } + delete m_dimensions_names; m_dimensions_names = 0; + } + if (m_dimensions_values) { + for (std::vector::iterator it = m_dimensions_values->begin(); it != m_dimensions_values->end(); ++it) { + delete *it; + } + delete m_dimensions_values; m_dimensions_values = 0; + } + if (!n_ap_container) { + if (m_ap_container) { + delete m_ap_container; m_ap_container = 0; + } + } + if (!n_histogram) { + if (m_histogram) { + delete m_histogram; m_histogram = 0; + } + } +} + +ifx_metrics_bin_t::metric_event_type_t ifx_metrics_bin_t::userdata_t::event_type() { + if (f_event_type) + return m_event_type; + m_event_type = static_cast(event_id()); + f_event_type = true; + return m_event_type; +} + +ifx_metrics_bin_t::pair_value_count_t::pair_value_count_t(kaitai::kstream* p__io, ifx_metrics_bin_t::histogram_value_count_pairs_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::pair_value_count_t::_read() { + m_value = m__io->read_u8le(); + m_count = m__io->read_u4le(); +} + +ifx_metrics_bin_t::pair_value_count_t::~pair_value_count_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::pair_value_count_t::_clean_up() { +} + +ifx_metrics_bin_t::histogram_uint16_bucketed_t::histogram_uint16_bucketed_t(kaitai::kstream* p__io, ifx_metrics_bin_t::histogram_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + m_columns = 0; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::histogram_uint16_bucketed_t::_read() { + m_min = m__io->read_u8le(); + m_bucket_size = m__io->read_u4le(); + m_bucket_count = m__io->read_u4le(); + m_distribution_size = m__io->read_u2le(); + int l_columns = distribution_size(); + m_columns = new std::vector(); + m_columns->reserve(l_columns); + for (int i = 0; i < l_columns; i++) { + m_columns->push_back(new pair_uint16_t(m__io, this, m__root)); + } +} + +ifx_metrics_bin_t::histogram_uint16_bucketed_t::~histogram_uint16_bucketed_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::histogram_uint16_bucketed_t::_clean_up() { + if (m_columns) { + for (std::vector::iterator it = m_columns->begin(); it != m_columns->end(); ++it) { + delete *it; + } + delete m_columns; m_columns = 0; + } +} + +ifx_metrics_bin_t::histogram_value_count_pairs_t::histogram_value_count_pairs_t(kaitai::kstream* p__io, ifx_metrics_bin_t::histogram_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + m_columns = 0; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::histogram_value_count_pairs_t::_read() { + m_distribution_size = m__io->read_u2le(); + int l_columns = distribution_size(); + m_columns = new std::vector(); + m_columns->reserve(l_columns); + for (int i = 0; i < l_columns; i++) { + m_columns->push_back(new pair_value_count_t(m__io, this, m__root)); + } +} + +ifx_metrics_bin_t::histogram_value_count_pairs_t::~histogram_value_count_pairs_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::histogram_value_count_pairs_t::_clean_up() { + if (m_columns) { + for (std::vector::iterator it = m_columns->begin(); it != m_columns->end(); ++it) { + delete *it; + } + delete m_columns; m_columns = 0; + } +} + +ifx_metrics_bin_t::histogram_t::histogram_t(kaitai::kstream* p__io, ifx_metrics_bin_t::userdata_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::histogram_t::_read() { + m_version = m__io->read_u1(); + m_type = static_cast(m__io->read_u1()); + n_body = true; + switch (type()) { + case ifx_metrics_bin_t::DISTRIBUTION_TYPE_IFX_BUCKETED: { + n_body = false; + m_body = new histogram_uint16_bucketed_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::DISTRIBUTION_TYPE_MON_AGENT_BUCKETED: { + n_body = false; + m_body = new histogram_uint16_bucketed_t(m__io, this, m__root); + break; + } + case ifx_metrics_bin_t::DISTRIBUTION_TYPE_VALUE_COUNT_PAIRS: { + n_body = false; + m_body = new histogram_value_count_pairs_t(m__io, this, m__root); + break; + } + } +} + +ifx_metrics_bin_t::histogram_t::~histogram_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::histogram_t::_clean_up() { + if (!n_body) { + if (m_body) { + delete m_body; m_body = 0; + } + } +} + +ifx_metrics_bin_t::pair_uint16_t::pair_uint16_t(kaitai::kstream* p__io, ifx_metrics_bin_t::histogram_uint16_bucketed_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::pair_uint16_t::_read() { + m_index = m__io->read_u2le(); + m_count = m__io->read_u2le(); +} + +ifx_metrics_bin_t::pair_uint16_t::~pair_uint16_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::pair_uint16_t::_clean_up() { +} + +ifx_metrics_bin_t::single_uint64_value_t::single_uint64_value_t(kaitai::kstream* p__io, ifx_metrics_bin_t::userdata_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::single_uint64_value_t::_read() { + m_padding = m__io->read_bytes(4); + m_timestamp = m__io->read_u8le(); + m_value = m__io->read_u8le(); +} + +ifx_metrics_bin_t::single_uint64_value_t::~single_uint64_value_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::single_uint64_value_t::_clean_up() { +} + +ifx_metrics_bin_t::ext_aggregated_double_value_t::ext_aggregated_double_value_t(kaitai::kstream* p__io, ifx_metrics_bin_t::userdata_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::ext_aggregated_double_value_t::_read() { + m_count = m__io->read_u4le(); + m_timestamp = m__io->read_u8le(); + m_sum = m__io->read_f8le(); + m_min = m__io->read_f8le(); + m_max = m__io->read_f8le(); +} + +ifx_metrics_bin_t::ext_aggregated_double_value_t::~ext_aggregated_double_value_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::ext_aggregated_double_value_t::_clean_up() { +} + +ifx_metrics_bin_t::ext_aggregated_uint64_value_t::ext_aggregated_uint64_value_t(kaitai::kstream* p__io, ifx_metrics_bin_t::userdata_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::ext_aggregated_uint64_value_t::_read() { + m_count = m__io->read_u4le(); + m_timestamp = m__io->read_u8le(); + m_sum = m__io->read_u8le(); + m_min = m__io->read_u8le(); + m_max = m__io->read_u8le(); +} + +ifx_metrics_bin_t::ext_aggregated_uint64_value_t::~ext_aggregated_uint64_value_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::ext_aggregated_uint64_value_t::_clean_up() { +} + +ifx_metrics_bin_t::single_double_value_t::single_double_value_t(kaitai::kstream* p__io, ifx_metrics_bin_t::userdata_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::single_double_value_t::_read() { + m_padding = m__io->read_bytes(4); + m_timestamp = m__io->read_u8le(); + m_value = m__io->read_f8le(); +} + +ifx_metrics_bin_t::single_double_value_t::~single_double_value_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::single_double_value_t::_clean_up() { +} + +ifx_metrics_bin_t::len_string_t::len_string_t(kaitai::kstream* p__io, ifx_metrics_bin_t::userdata_t* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + m__parent = p__parent; + m__root = p__root; + + try { + _read(); + } catch(...) { + _clean_up(); + throw; + } +} + +void ifx_metrics_bin_t::len_string_t::_read() { + m_len_value = m__io->read_u2le(); + m_value = kaitai::kstream::bytes_to_str(m__io->read_bytes(len_value()), std::string("UTF-8")); +} + +ifx_metrics_bin_t::len_string_t::~len_string_t() { + _clean_up(); +} + +void ifx_metrics_bin_t::len_string_t::_clean_up() { +} diff --git a/exporters/geneva/test/decoder/ifx_metrics_bin.h b/exporters/geneva/test/decoder/ifx_metrics_bin.h new file mode 100644 index 000000000..3f8e4374f --- /dev/null +++ b/exporters/geneva/test/decoder/ifx_metrics_bin.h @@ -0,0 +1,617 @@ +#ifndef IFX_METRICS_BIN_H_ +#define IFX_METRICS_BIN_H_ + +// This is a generated file! Please edit source .ksy file and use +// kaitai-struct-compiler to rebuild + +#include "kaitai/kaitaistruct.h" +#include +#include + +#if KAITAI_STRUCT_VERSION < 9000L +#error \ + "Incompatible Kaitai Struct C++/STL API: version 0.9 or later is required" +#endif + +/** + * Ifx Metrics binary protocol provides efficient way to emit metrics + * data to Geneva Metrics. This particular version of protocol is best suited + * for transfer over networked transport (UDP, TCP, UNIX domain sockets) and/or + * file storage, as it is completely self-contained. "Body" of this protocol + * closely matches "UserData" portion of IfxMetrics-over-ETW messages + * (typically emitted by IfxMetrics.dll or compatible apps/libraries on + * Windows). + */ + +class ifx_metrics_bin_t : public kaitai::kstruct { + +public: + class userdata_t; + class pair_value_count_t; + class histogram_uint16_bucketed_t; + class histogram_value_count_pairs_t; + class histogram_t; + class pair_uint16_t; + class single_uint64_value_t; + class ext_aggregated_double_value_t; + class ext_aggregated_uint64_value_t; + class single_double_value_t; + class len_string_t; + + enum metric_event_type_t { + METRIC_EVENT_TYPE_OLD_IFX = 0, + METRIC_EVENT_TYPE_UINT64_METRIC = 50, + METRIC_EVENT_TYPE_DOUBLE_SCALED_TO_LONG_METRIC = 51, + METRIC_EVENT_TYPE_BATCH_METRIC = 52, + METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_ULONG_METRIC = 53, + METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_METRIC = 54, + METRIC_EVENT_TYPE_DOUBLE_METRIC = 55, + METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_ULONG_DISTRIBUTION_METRIC = 56, + METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_DISTRIBUTION_METRIC = 57, + METRIC_EVENT_TYPE_EXTERNALLY_AGGREGATED_DOUBLE_SCALED_TO_LONG_DISTRIBUTION_METRIC = + 58 + }; + + enum distribution_type_t { + DISTRIBUTION_TYPE_IFX_BUCKETED = 0, + DISTRIBUTION_TYPE_MON_AGENT_BUCKETED = 1, + DISTRIBUTION_TYPE_VALUE_COUNT_PAIRS = 2 + }; + + ifx_metrics_bin_t(kaitai::kstream *p__io, kaitai::kstruct *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + +private: + void _read(); + void _clean_up(); + +public: + ~ifx_metrics_bin_t(); + + /** + * This type represents "UserData" or "body" portion of Ifx Metrics message. + */ + + class userdata_t : public kaitai::kstruct { + + public: + userdata_t(uint16_t p_event_id, kaitai::kstream *p__io, + ifx_metrics_bin_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~userdata_t(); + + private: + bool f_event_type; + metric_event_type_t m_event_type; + + public: + metric_event_type_t event_type(); + + private: + uint16_t m_num_dimensions; + std::string m_padding; + kaitai::kstruct *m_value_section; + bool n_value_section; + + public: + bool _is_null_value_section() { + value_section(); + return n_value_section; + }; + + private: + len_string_t *m_metric_account; + len_string_t *m_metric_namespace; + len_string_t *m_metric_name; + std::vector *m_dimensions_names; + std::vector *m_dimensions_values; + len_string_t *m_ap_container; + bool n_ap_container; + + public: + bool _is_null_ap_container() { + ap_container(); + return n_ap_container; + }; + + private: + histogram_t *m_histogram; + bool n_histogram; + + public: + bool _is_null_histogram() { + histogram(); + return n_histogram; + }; + + private: + uint16_t m_event_id; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t *m__parent; + + public: + /** + * Number of dimensions specified in this event. + */ + uint16_t num_dimensions() const { return m_num_dimensions; } + std::string padding() const { return m_padding; } + + /** + * Value section of the body, stores fixed numeric metric value(s), as per + * event type. + */ + kaitai::kstruct *value_section() const { return m_value_section; } + + /** + * Geneva Metrics account name to be used for this metric. + */ + len_string_t *metric_account() const { return m_metric_account; } + + /** + * Geneva Metrics namespace name to be used for this metric. + */ + len_string_t *metric_namespace() const { return m_metric_namespace; } + + /** + * Geneva Metrics metric name to be used. + */ + len_string_t *metric_name() const { return m_metric_name; } + + /** + * Dimension names strings ("key" parts of key-value pairs). Must be sorted, + * unless MetricsExtenion's option `enableDimensionSortingOnIngestion` is + * enabled. + */ + std::vector *dimensions_names() const { + return m_dimensions_names; + } + + /** + * Dimension values strings ("value" parts of key-value pairs). + */ + std::vector *dimensions_values() const { + return m_dimensions_values; + } + + /** + * AutoPilot container string, required for correct AP PKI certificate + * loading in AutoPilot containers environment. + */ + len_string_t *ap_container() const { return m_ap_container; } + histogram_t *histogram() const { return m_histogram; } + + /** + * Type of message, affects format of the body. + */ + uint16_t event_id() const { return m_event_id; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t *_parent() const { return m__parent; } + }; + + /** + * Bucket with an explicitly-defined value coordinate `value`, claiming to + * hold `count` hits. Normally used to represent non-linear (e.g. exponential) + * histograms payloads. + */ + + class pair_value_count_t : public kaitai::kstruct { + + public: + pair_value_count_t( + kaitai::kstream *p__io, + ifx_metrics_bin_t::histogram_value_count_pairs_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~pair_value_count_t(); + + private: + uint64_t m_value; + uint32_t m_count; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::histogram_value_count_pairs_t *m__parent; + + public: + uint64_t value() const { return m_value; } + uint32_t count() const { return m_count; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::histogram_value_count_pairs_t *_parent() const { + return m__parent; + } + }; + + /** + * Payload of a histogram with linear distribution of buckets. Such histogram + * is defined by the parameters specified in `min`, `bucket_size` and + * `bucket_count`. It is modelled as a series of buckets. First (index 0) and + * last (indexed `bucket_count - 1`) buckets are special and are supposed to + * catch all "underflow" and "overflow" values. Buckets with indexes 1 up to + * `bucket_count - 2` are regular buckets of size `bucket_size`. + */ + + class histogram_uint16_bucketed_t : public kaitai::kstruct { + + public: + histogram_uint16_bucketed_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::histogram_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~histogram_uint16_bucketed_t(); + + private: + uint64_t m_min; + uint32_t m_bucket_size; + uint32_t m_bucket_count; + uint16_t m_distribution_size; + std::vector *m_columns; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::histogram_t *m__parent; + + public: + uint64_t min() const { return m_min; } + uint32_t bucket_size() const { return m_bucket_size; } + uint32_t bucket_count() const { return m_bucket_count; } + uint16_t distribution_size() const { return m_distribution_size; } + std::vector *columns() const { return m_columns; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::histogram_t *_parent() const { return m__parent; } + }; + + class histogram_value_count_pairs_t : public kaitai::kstruct { + + public: + histogram_value_count_pairs_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::histogram_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~histogram_value_count_pairs_t(); + + private: + uint16_t m_distribution_size; + std::vector *m_columns; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::histogram_t *m__parent; + + public: + uint16_t distribution_size() const { return m_distribution_size; } + std::vector *columns() const { return m_columns; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::histogram_t *_parent() const { return m__parent; } + }; + + class histogram_t : public kaitai::kstruct { + + public: + histogram_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::userdata_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~histogram_t(); + + private: + uint8_t m_version; + distribution_type_t m_type; + kaitai::kstruct *m_body; + bool n_body; + + public: + bool _is_null_body() { + body(); + return n_body; + }; + + private: + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::userdata_t *m__parent; + + public: + uint8_t version() const { return m_version; } + distribution_type_t type() const { return m_type; } + kaitai::kstruct *body() const { return m_body; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::userdata_t *_parent() const { return m__parent; } + }; + + /** + * Bucket #index, claiming to hold exactly `count` hits. See notes in + * `histogram_uint16_bucketed` for interpreting index. + */ + + class pair_uint16_t : public kaitai::kstruct { + + public: + pair_uint16_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::histogram_uint16_bucketed_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~pair_uint16_t(); + + private: + uint16_t m_index; + uint16_t m_count; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::histogram_uint16_bucketed_t *m__parent; + + public: + uint16_t index() const { return m_index; } + uint16_t count() const { return m_count; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::histogram_uint16_bucketed_t *_parent() const { + return m__parent; + } + }; + + class single_uint64_value_t : public kaitai::kstruct { + + public: + single_uint64_value_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::userdata_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~single_uint64_value_t(); + + private: + std::string m_padding; + uint64_t m_timestamp; + uint64_t m_value; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::userdata_t *m__parent; + + public: + std::string padding() const { return m_padding; } + + /** + * Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed + * since 1601-01-01 00:00:00 UTC. + */ + uint64_t timestamp() const { return m_timestamp; } + + /** + * Metric value as 64-bit unsigned integer. + */ + uint64_t value() const { return m_value; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::userdata_t *_parent() const { return m__parent; } + }; + + class ext_aggregated_double_value_t : public kaitai::kstruct { + + public: + ext_aggregated_double_value_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::userdata_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~ext_aggregated_double_value_t(); + + private: + uint32_t m_count; + uint64_t m_timestamp; + double m_sum; + double m_min; + double m_max; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::userdata_t *m__parent; + + public: + /** + * Count of events aggregated in this event. + */ + uint32_t count() const { return m_count; } + + /** + * Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed + * since 1601-01-01 00:00:00 UTC. + */ + uint64_t timestamp() const { return m_timestamp; } + + /** + * Sum of all metric values aggregated in this event. + */ + double sum() const { return m_sum; } + + /** + * Minimum of all metric values aggregated in this event. + */ + double min() const { return m_min; } + + /** + * Maximum of all metric values aggregated in this event. + */ + double max() const { return m_max; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::userdata_t *_parent() const { return m__parent; } + }; + + class ext_aggregated_uint64_value_t : public kaitai::kstruct { + + public: + ext_aggregated_uint64_value_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::userdata_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~ext_aggregated_uint64_value_t(); + + private: + uint32_t m_count; + uint64_t m_timestamp; + uint64_t m_sum; + uint64_t m_min; + uint64_t m_max; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::userdata_t *m__parent; + + public: + /** + * Count of events aggregated in this event. + */ + uint32_t count() const { return m_count; } + + /** + * Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed + * since 1601-01-01 00:00:00 UTC. + */ + uint64_t timestamp() const { return m_timestamp; } + + /** + * Sum of all metric values aggregated in this event. + */ + uint64_t sum() const { return m_sum; } + + /** + * Minimum of all metric values aggregated in this event. + */ + uint64_t min() const { return m_min; } + + /** + * Maximum of all metric values aggregated in this event. + */ + uint64_t max() const { return m_max; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::userdata_t *_parent() const { return m__parent; } + }; + + class single_double_value_t : public kaitai::kstruct { + + public: + single_double_value_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::userdata_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~single_double_value_t(); + + private: + std::string m_padding; + uint64_t m_timestamp; + double m_value; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::userdata_t *m__parent; + + public: + std::string padding() const { return m_padding; } + + /** + * Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed + * since 1601-01-01 00:00:00 UTC. + */ + uint64_t timestamp() const { return m_timestamp; } + + /** + * Metric value as double. + */ + double value() const { return m_value; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::userdata_t *_parent() const { return m__parent; } + }; + + /** + * A simple string, length-prefixed with a 2-byte integer. + */ + + class len_string_t : public kaitai::kstruct { + + public: + len_string_t(kaitai::kstream *p__io, + ifx_metrics_bin_t::userdata_t *p__parent = 0, + ifx_metrics_bin_t *p__root = 0); + + private: + void _read(); + void _clean_up(); + + public: + ~len_string_t(); + + private: + uint16_t m_len_value; + std::string m_value; + ifx_metrics_bin_t *m__root; + ifx_metrics_bin_t::userdata_t *m__parent; + + public: + uint16_t len_value() const { return m_len_value; } + std::string value() const { return m_value; } + ifx_metrics_bin_t *_root() const { return m__root; } + ifx_metrics_bin_t::userdata_t *_parent() const { return m__parent; } + }; + +private: + uint16_t m_event_id; + uint16_t m_len_body; + userdata_t *m_body; + ifx_metrics_bin_t *m__root; + kaitai::kstruct *m__parent; + std::string m__raw_body; + kaitai::kstream *m__io__raw_body; + +public: + /** + * Type of message, affects format of the body. + */ + uint16_t event_id() const { return m_event_id; } + + /** + * Size of body in bytes. + */ + uint16_t len_body() const { return m_len_body; } + + /** + * Body of IfxMetrics binary protocol message. + */ + userdata_t *body() const { return m_body; } + ifx_metrics_bin_t *_root() const { return m__root; } + kaitai::kstruct *_parent() const { return m__parent; } + std::string _raw_body() const { return m__raw_body; } + kaitai::kstream *_io__raw_body() const { return m__io__raw_body; } +}; + +#endif // IFX_METRICS_BIN_H_ diff --git a/exporters/geneva/test/decoder/ifx_metrics_bin.ksy b/exporters/geneva/test/decoder/ifx_metrics_bin.ksy new file mode 100644 index 000000000..b4849cfa1 --- /dev/null +++ b/exporters/geneva/test/decoder/ifx_metrics_bin.ksy @@ -0,0 +1,236 @@ +meta: + id: ifx_metrics_bin + encoding: UTF-8 + endian: le +doc: | + Ifx Metrics binary protocol provides efficient way to emit metrics + data to Geneva Metrics. This particular version of protocol is best suited + for transfer over networked transport (UDP, TCP, UNIX domain sockets) and/or + file storage, as it is completely self-contained. "Body" of this protocol + closely matches "UserData" portion of IfxMetrics-over-ETW messages + (typically emitted by IfxMetrics.dll or compatible apps/libraries on Windows). +seq: + - id: event_id + type: u2 + doc: Type of message, affects format of the body. + - id: len_body + type: u2 + doc: Size of body in bytes. + - id: body + size: len_body + type: userdata(event_id) + doc: Body of IfxMetrics binary protocol message. +types: + userdata: + doc: | + This type represents "UserData" or "body" portion of Ifx Metrics message. + params: + - id: event_id + type: u2 + doc: Type of message, affects format of the body. + seq: + - id: num_dimensions + type: u2 + doc: Number of dimensions specified in this event. + - id: padding + size: 2 + - id: value_section + type: + switch-on: event_type + cases: + 'metric_event_type::old_ifx': single_uint64_value + 'metric_event_type::uint64_metric': single_uint64_value + 'metric_event_type::double_scaled_to_long_metric': single_double_value + 'metric_event_type::externally_aggregated_ulong_metric': ext_aggregated_uint64_value + 'metric_event_type::externally_aggregated_double_metric': ext_aggregated_double_value + 'metric_event_type::double_metric': single_double_value + 'metric_event_type::externally_aggregated_ulong_distribution_metric': ext_aggregated_uint64_value + 'metric_event_type::externally_aggregated_double_distribution_metric': ext_aggregated_double_value + 'metric_event_type::externally_aggregated_double_scaled_to_long_distribution_metric': ext_aggregated_double_value + doc: Value section of the body, stores fixed numeric metric value(s), as per event type. + - id: metric_account + type: len_string + doc: Geneva Metrics account name to be used for this metric. + - id: metric_namespace + type: len_string + doc: Geneva Metrics namespace name to be used for this metric. + - id: metric_name + type: len_string + doc: Geneva Metrics metric name to be used. + - id: dimensions_names + type: len_string + repeat: expr + repeat-expr: num_dimensions + doc: | + Dimension names strings ("key" parts of key-value pairs). Must be sorted, + unless MetricsExtenion's option `enableDimensionSortingOnIngestion` is + enabled. + - id: dimensions_values + type: len_string + repeat: expr + repeat-expr: num_dimensions + doc: Dimension values strings ("value" parts of key-value pairs). + - id: ap_container + type: len_string + if: not _io.eof + doc: | + AutoPilot container string, required for correct AP PKI certificate loading + in AutoPilot containers environment. + - id: histogram + type: histogram + if: > + (event_type == metric_event_type::externally_aggregated_ulong_distribution_metric or + event_type == metric_event_type::externally_aggregated_double_distribution_metric or + event_type == metric_event_type::externally_aggregated_double_scaled_to_long_distribution_metric) + and not _io.eof + instances: + event_type: + value: event_id + enum: metric_event_type + histogram: + -orig-id: 'IfxProcessor::ReadDistribution' + seq: + - id: version + type: u1 + - id: type + type: u1 + enum: distribution_type + - id: body + type: + switch-on: type + cases: + 'distribution_type::ifx_bucketed': histogram_uint16_bucketed + 'distribution_type::mon_agent_bucketed': histogram_uint16_bucketed + 'distribution_type::value_count_pairs': histogram_value_count_pairs + histogram_uint16_bucketed: + doc: | + Payload of a histogram with linear distribution of buckets. Such histogram + is defined by the parameters specified in `min`, `bucket_size` and + `bucket_count`. It is modelled as a series of buckets. First (index 0) and + last (indexed `bucket_count - 1`) buckets are special and are supposed to + catch all "underflow" and "overflow" values. Buckets with indexes 1 up to + `bucket_count - 2` are regular buckets of size `bucket_size`. + -orig-id: 'IfxProcessor::ReadUint16BucketedDistribution' + seq: + - id: min + type: u8 + - id: bucket_size + type: u4 + - id: bucket_count + type: u4 + - id: distribution_size + type: u2 + - id: columns + type: pair_uint16 + repeat: expr + repeat-expr: distribution_size + histogram_value_count_pairs: + -orig-id: 'IfxProcessor::ReadValueCountPairsDistribution' + seq: + - id: distribution_size + type: u2 + - id: columns + type: pair_value_count + repeat: expr + repeat-expr: distribution_size + pair_uint16: + doc: | + Bucket #index, claiming to hold exactly `count` hits. See notes in + `histogram_uint16_bucketed` for interpreting index. + seq: + - id: index + type: u2 + - id: count + type: u2 + pair_value_count: + doc: | + Bucket with an explicitly-defined value coordinate `value`, claiming to + hold `count` hits. Normally used to represent non-linear (e.g. exponential) + histograms payloads. + seq: + - id: value + type: u8 + - id: count + type: u4 + single_uint64_value: + -orig-id: MDM_EVENT_PAYLOAD + seq: + - id: padding + size: 4 + - id: timestamp + type: u8 + doc: Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed since 1601-01-01 00:00:00 UTC. + - id: value + type: u8 + doc: Metric value as 64-bit unsigned integer. + single_double_value: + -orig-id: MDM_EVENT_PAYLOAD + seq: + - id: padding + size: 4 + - id: timestamp + type: u8 + doc: Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed since 1601-01-01 00:00:00 UTC. + - id: value + type: f8 + doc: Metric value as double. + ext_aggregated_uint64_value: + -orig-id: MDM_EXTERNAL_AGG_EVENT_PAYLOAD + seq: + - id: count + type: u4 + doc: Count of events aggregated in this event. + - id: timestamp + type: u8 + doc: Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed since 1601-01-01 00:00:00 UTC. + - id: sum + type: u8 + doc: Sum of all metric values aggregated in this event. + - id: min + type: u8 + doc: Minimum of all metric values aggregated in this event. + - id: max + type: u8 + doc: Maximum of all metric values aggregated in this event. + ext_aggregated_double_value: + -orig-id: MDM_EXTERNAL_AGG_EVENT_PAYLOAD + seq: + - id: count + type: u4 + doc: Count of events aggregated in this event. + - id: timestamp + type: u8 + doc: Timestamp in Windows FILETIME format, i.e. number of 100 ns ticks passed since 1601-01-01 00:00:00 UTC. + - id: sum + type: f8 + doc: Sum of all metric values aggregated in this event. + - id: min + type: f8 + doc: Minimum of all metric values aggregated in this event. + - id: max + type: f8 + doc: Maximum of all metric values aggregated in this event. + len_string: + doc: A simple string, length-prefixed with a 2-byte integer. + seq: + - id: len_value + type: u2 + - id: value + size: len_value + type: str +enums: + metric_event_type: + 0: old_ifx + 50: uint64_metric + 51: double_scaled_to_long_metric + 52: batch_metric + 53: externally_aggregated_ulong_metric + 54: externally_aggregated_double_metric + 55: double_metric + 56: externally_aggregated_ulong_distribution_metric + 57: externally_aggregated_double_distribution_metric + 58: externally_aggregated_double_scaled_to_long_distribution_metric + distribution_type: + 0: ifx_bucketed + 1: mon_agent_bucketed + 2: value_count_pairs diff --git a/exporters/geneva/test/decoder/kaitai/custom_decoder.h b/exporters/geneva/test/decoder/kaitai/custom_decoder.h new file mode 100644 index 000000000..e4460682f --- /dev/null +++ b/exporters/geneva/test/decoder/kaitai/custom_decoder.h @@ -0,0 +1,16 @@ +#ifndef KAITAI_CUSTOM_DECODER_H +#define KAITAI_CUSTOM_DECODER_H + +#include + +namespace kaitai { + +class custom_decoder { +public: + virtual ~custom_decoder(){}; + virtual std::string decode(std::string src) = 0; +}; + +} // namespace kaitai + +#endif diff --git a/exporters/geneva/test/decoder/kaitai/exceptions.h b/exporters/geneva/test/decoder/kaitai/exceptions.h new file mode 100644 index 000000000..8adf57ebd --- /dev/null +++ b/exporters/geneva/test/decoder/kaitai/exceptions.h @@ -0,0 +1,177 @@ +#ifndef KAITAI_EXCEPTIONS_H +#define KAITAI_EXCEPTIONS_H + +#include + +#include +#include + +// We need to use "noexcept" in virtual destructor of our exceptions +// subclasses. Different compilers have different ideas on how to +// achieve that: C++98 compilers prefer `throw()`, C++11 and later +// use `noexcept`. We define KS_NOEXCEPT macro for that. + +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#define KS_NOEXCEPT noexcept +#else +#define KS_NOEXCEPT throw() +#endif + +namespace kaitai { + +/** + * Common ancestor for all error originating from Kaitai Struct usage. + * Stores KSY source path, pointing to an element supposedly guilty of + * an error. + */ +class kstruct_error : public std::runtime_error { +public: + kstruct_error(const std::string what, const std::string src_path) + : std::runtime_error(src_path + ": " + what), m_src_path(src_path) {} + + virtual ~kstruct_error() KS_NOEXCEPT{}; + +protected: + const std::string m_src_path; +}; + +/** + * Error that occurs when default endianness should be decided with + * a switch, but nothing matches (although using endianness expression + * implies that there should be some positive result). + */ +class undecided_endianness_error : public kstruct_error { +public: + undecided_endianness_error(const std::string src_path) + : kstruct_error("unable to decide on endianness for a type", src_path) {} + + virtual ~undecided_endianness_error() KS_NOEXCEPT{}; +}; + +/** + * Common ancestor for all validation failures. Stores pointer to + * KaitaiStream IO object which was involved in an error. + */ +class validation_failed_error : public kstruct_error { +public: + validation_failed_error(const std::string what, kstream *io, + const std::string src_path) + : kstruct_error("at pos " + kstream::to_string(io->pos()) + + ": validation failed: " + what, + src_path), + m_io(io) {} + + // "at pos #{io.pos}: validation failed: #{msg}" + + virtual ~validation_failed_error() KS_NOEXCEPT{}; + +protected: + kstream *m_io; +}; + +/** + * Signals validation failure: we required "actual" value to be equal to + * "expected", but it turned out that it's not. + */ +template +class validation_not_equal_error : public validation_failed_error { +public: + validation_not_equal_error(const T &expected, const T &actual, kstream *io, + const std::string src_path) + : validation_failed_error("not equal", io, src_path), + m_expected(expected), m_actual(actual) {} + + // "not equal, expected #{expected.inspect}, but got #{actual.inspect}" + + virtual ~validation_not_equal_error() KS_NOEXCEPT{}; + +protected: + const T &m_expected; + const T &m_actual; +}; + +/** + * Signals validation failure: we required "actual" value to be greater + * than or equal to "min", but it turned out that it's not. + */ +template +class validation_less_than_error : public validation_failed_error { +public: + validation_less_than_error(const T &min, const T &actual, kstream *io, + const std::string src_path) + : validation_failed_error("not in range", io, src_path), m_min(min), + m_actual(actual) {} + + // "not in range, min #{min.inspect}, but got #{actual.inspect}" + + virtual ~validation_less_than_error() KS_NOEXCEPT{}; + +protected: + const T &m_min; + const T &m_actual; +}; + +/** + * Signals validation failure: we required "actual" value to be less + * than or equal to "max", but it turned out that it's not. + */ +template +class validation_greater_than_error : public validation_failed_error { +public: + validation_greater_than_error(const T &max, const T &actual, kstream *io, + const std::string src_path) + : validation_failed_error("not in range", io, src_path), m_max(max), + m_actual(actual) {} + + // "not in range, max #{max.inspect}, but got #{actual.inspect}" + + virtual ~validation_greater_than_error() KS_NOEXCEPT{}; + +protected: + const T &m_max; + const T &m_actual; +}; + +/** + * Signals validation failure: we required "actual" value to be from + * the list, but it turned out that it's not. + */ +template +class validation_not_any_of_error : public validation_failed_error { +public: + validation_not_any_of_error(const T &actual, kstream *io, + const std::string src_path) + : validation_failed_error("not any of the list", io, src_path), + m_actual(actual) {} + + // "not any of the list, got #{actual.inspect}" + + virtual ~validation_not_any_of_error() KS_NOEXCEPT{}; + +protected: + const T &m_actual; +}; + +/** + * Signals validation failure: we required "actual" value to match + * the expression, but it turned out that it doesn't. + */ +template +class validation_expr_error : public validation_failed_error { +public: + validation_expr_error(const T &actual, kstream *io, + const std::string src_path) + : validation_failed_error("not matching the expression", io, src_path), + m_actual(actual) {} + + // "not matching the expression, got #{actual.inspect}" + + virtual ~validation_expr_error() KS_NOEXCEPT{}; + +protected: + const T &m_actual; +}; + +} // namespace kaitai + +#endif diff --git a/exporters/geneva/test/decoder/kaitai/kaitaistream.cpp b/exporters/geneva/test/decoder/kaitai/kaitaistream.cpp new file mode 100644 index 000000000..c033285ce --- /dev/null +++ b/exporters/geneva/test/decoder/kaitai/kaitaistream.cpp @@ -0,0 +1,690 @@ +#include + +#if defined(__APPLE__) +#include +#include +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN +#elif defined(_MSC_VER) // !__APPLE__ +#include +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __BYTE_ORDER __LITTLE_ENDIAN +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) +#else // !__APPLE__ or !_MSC_VER +#include +#include +#endif + +#include +#include +#include + +kaitai::kstream::kstream(std::istream *io) { + m_io = io; + init(); +} + +kaitai::kstream::kstream(const std::string &data) : m_io_str(data) { + m_io = &m_io_str; + init(); +} + +void kaitai::kstream::init() { + exceptions_enable(); + align_to_byte(); +} + +void kaitai::kstream::close() { + // m_io->close(); +} + +void kaitai::kstream::exceptions_enable() const { + m_io->exceptions( + std::istream::eofbit | + std::istream::failbit | + std::istream::badbit + ); +} + +// ======================================================================== +// Stream positioning +// ======================================================================== + +bool kaitai::kstream::is_eof() const { + if (m_bits_left > 0) { + return false; + } + char t; + m_io->exceptions(std::istream::badbit); + m_io->get(t); + if (m_io->eof()) { + m_io->clear(); + exceptions_enable(); + return true; + } else { + m_io->unget(); + exceptions_enable(); + return false; + } +} + +void kaitai::kstream::seek(uint64_t pos) { + m_io->seekg(pos); +} + +uint64_t kaitai::kstream::pos() { + return m_io->tellg(); +} + +uint64_t kaitai::kstream::size() { + std::iostream::pos_type cur_pos = m_io->tellg(); + m_io->seekg(0, std::ios::end); + std::iostream::pos_type len = m_io->tellg(); + m_io->seekg(cur_pos); + return len; +} + +// ======================================================================== +// Integer numbers +// ======================================================================== + +// ------------------------------------------------------------------------ +// Signed +// ------------------------------------------------------------------------ + +int8_t kaitai::kstream::read_s1() { + char t; + m_io->get(t); + return t; +} + +// ........................................................................ +// Big-endian +// ........................................................................ + +int16_t kaitai::kstream::read_s2be() { + int16_t t; + m_io->read(reinterpret_cast(&t), 2); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_16(t); +#endif + return t; +} + +int32_t kaitai::kstream::read_s4be() { + int32_t t; + m_io->read(reinterpret_cast(&t), 4); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_32(t); +#endif + return t; +} + +int64_t kaitai::kstream::read_s8be() { + int64_t t; + m_io->read(reinterpret_cast(&t), 8); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_64(t); +#endif + return t; +} + +// ........................................................................ +// Little-endian +// ........................................................................ + +int16_t kaitai::kstream::read_s2le() { + int16_t t; + m_io->read(reinterpret_cast(&t), 2); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_16(t); +#endif + return t; +} + +int32_t kaitai::kstream::read_s4le() { + int32_t t; + m_io->read(reinterpret_cast(&t), 4); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_32(t); +#endif + return t; +} + +int64_t kaitai::kstream::read_s8le() { + int64_t t; + m_io->read(reinterpret_cast(&t), 8); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_64(t); +#endif + return t; +} + +// ------------------------------------------------------------------------ +// Unsigned +// ------------------------------------------------------------------------ + +uint8_t kaitai::kstream::read_u1() { + char t; + m_io->get(t); + return t; +} + +// ........................................................................ +// Big-endian +// ........................................................................ + +uint16_t kaitai::kstream::read_u2be() { + uint16_t t; + m_io->read(reinterpret_cast(&t), 2); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_16(t); +#endif + return t; +} + +uint32_t kaitai::kstream::read_u4be() { + uint32_t t; + m_io->read(reinterpret_cast(&t), 4); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_32(t); +#endif + return t; +} + +uint64_t kaitai::kstream::read_u8be() { + uint64_t t; + m_io->read(reinterpret_cast(&t), 8); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_64(t); +#endif + return t; +} + +// ........................................................................ +// Little-endian +// ........................................................................ + +uint16_t kaitai::kstream::read_u2le() { + uint16_t t; + m_io->read(reinterpret_cast(&t), 2); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_16(t); +#endif + return t; +} + +uint32_t kaitai::kstream::read_u4le() { + uint32_t t; + m_io->read(reinterpret_cast(&t), 4); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_32(t); +#endif + return t; +} + +uint64_t kaitai::kstream::read_u8le() { + uint64_t t; + m_io->read(reinterpret_cast(&t), 8); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_64(t); +#endif + return t; +} + +// ======================================================================== +// Floating point numbers +// ======================================================================== + +// ........................................................................ +// Big-endian +// ........................................................................ + +float kaitai::kstream::read_f4be() { + uint32_t t; + m_io->read(reinterpret_cast(&t), 4); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_32(t); +#endif + return reinterpret_cast(t); +} + +double kaitai::kstream::read_f8be() { + uint64_t t; + m_io->read(reinterpret_cast(&t), 8); +#if __BYTE_ORDER == __LITTLE_ENDIAN + t = bswap_64(t); +#endif + return reinterpret_cast(t); +} + +// ........................................................................ +// Little-endian +// ........................................................................ + +float kaitai::kstream::read_f4le() { + uint32_t t; + m_io->read(reinterpret_cast(&t), 4); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_32(t); +#endif + return reinterpret_cast(t); +} + +double kaitai::kstream::read_f8le() { + uint64_t t; + m_io->read(reinterpret_cast(&t), 8); +#if __BYTE_ORDER == __BIG_ENDIAN + t = bswap_64(t); +#endif + return reinterpret_cast(t); +} + +// ======================================================================== +// Unaligned bit values +// ======================================================================== + +void kaitai::kstream::align_to_byte() { + m_bits_left = 0; + m_bits = 0; +} + +uint64_t kaitai::kstream::read_bits_int_be(int n) { + uint64_t res = 0; + + int bits_needed = n - m_bits_left; + m_bits_left = -bits_needed & 7; // `-bits_needed mod 8` + + if (bits_needed > 0) { + // 1 bit => 1 byte + // 8 bits => 1 byte + // 9 bits => 2 bytes + int bytes_needed = ((bits_needed - 1) / 8) + 1; // `ceil(bits_needed / 8)` + if (bytes_needed > 8) + throw std::runtime_error("read_bits_int_be: more than 8 bytes requested"); + uint8_t buf[8]; + m_io->read(reinterpret_cast(buf), bytes_needed); + for (int i = 0; i < bytes_needed; i++) { + res = res << 8 | buf[i]; + } + + uint64_t new_bits = res; + res = res >> m_bits_left | (bits_needed < 64 ? m_bits << bits_needed : 0); // avoid undefined behavior of `x << 64` + m_bits = new_bits; // will be masked at the end of the function + } else { + res = m_bits >> -bits_needed; // shift unneeded bits out + } + + uint64_t mask = (UINT64_C(1) << m_bits_left) - 1; // `m_bits_left` is in range 0..7, so `(1 << 64)` does not have to be considered + m_bits &= mask; + + return res; +} + +// Deprecated, use read_bits_int_be() instead. +uint64_t kaitai::kstream::read_bits_int(int n) { + return read_bits_int_be(n); +} + +uint64_t kaitai::kstream::read_bits_int_le(int n) { + uint64_t res = 0; + int bits_needed = n - m_bits_left; + + if (bits_needed > 0) { + // 1 bit => 1 byte + // 8 bits => 1 byte + // 9 bits => 2 bytes + int bytes_needed = ((bits_needed - 1) / 8) + 1; // `ceil(bits_needed / 8)` + if (bytes_needed > 8) + throw std::runtime_error("read_bits_int_le: more than 8 bytes requested"); + uint8_t buf[8]; + m_io->read(reinterpret_cast(buf), bytes_needed); + for (int i = 0; i < bytes_needed; i++) { + res |= static_cast(buf[i]) << (i * 8); + } + + // NB: for bit shift operators in C++, "if the value of the right operand is + // negative or is greater or equal to the number of bits in the promoted left + // operand, the behavior is undefined." (see + // https://en.cppreference.com/w/cpp/language/operator_arithmetic#Bitwise_shift_operators) + // So we define our desired behavior here. + uint64_t new_bits = bits_needed < 64 ? res >> bits_needed : 0; + res = res << m_bits_left | m_bits; + m_bits = new_bits; + } else { + res = m_bits; + m_bits >>= n; + } + + m_bits_left = -bits_needed & 7; // `-bits_needed mod 8` + + if (n < 64) { + uint64_t mask = (UINT64_C(1) << n) - 1; + res &= mask; + } + // if `n == 64`, do nothing + return res; +} + +// ======================================================================== +// Byte arrays +// ======================================================================== + +std::string kaitai::kstream::read_bytes(std::streamsize len) { + std::vector result(len); + + // NOTE: streamsize type is signed, negative values are only *supposed* to not be used. + // http://en.cppreference.com/w/cpp/io/streamsize + if (len < 0) { + throw std::runtime_error("read_bytes: requested a negative amount"); + } + + if (len > 0) { + m_io->read(&result[0], len); + } + + return std::string(result.begin(), result.end()); +} + +std::string kaitai::kstream::read_bytes_full() { + std::iostream::pos_type p1 = m_io->tellg(); + m_io->seekg(0, std::ios::end); + std::iostream::pos_type p2 = m_io->tellg(); + size_t len = p2 - p1; + + // Note: this requires a std::string to be backed with a + // contiguous buffer. Officially, it's a only requirement since + // C++11 (C++98 and C++03 didn't have this requirement), but all + // major implementations had contiguous buffers anyway. + std::string result(len, ' '); + m_io->seekg(p1); + m_io->read(&result[0], len); + + return result; +} + +std::string kaitai::kstream::read_bytes_term(char term, bool include, bool consume, bool eos_error) { + std::string result; + std::getline(*m_io, result, term); + if (m_io->eof()) { + // encountered EOF + if (eos_error) { + throw std::runtime_error("read_bytes_term: encountered EOF"); + } + } else { + // encountered terminator + if (include) + result.push_back(term); + if (!consume) + m_io->unget(); + } + return result; +} + +std::string kaitai::kstream::ensure_fixed_contents(std::string expected) { + std::string actual = read_bytes(expected.length()); + + if (actual != expected) { + // NOTE: I think printing it outright is not best idea, it could contain non-ASCII characters + // like backspace and beeps and whatnot. It would be better to print hexlified version, and + // also to redirect it to stderr. + throw std::runtime_error("ensure_fixed_contents: actual data does not match expected data"); + } + + return actual; +} + +std::string kaitai::kstream::bytes_strip_right(std::string src, char pad_byte) { + std::size_t new_len = src.length(); + + while (new_len > 0 && src[new_len - 1] == pad_byte) + new_len--; + + return src.substr(0, new_len); +} + +std::string kaitai::kstream::bytes_terminate(std::string src, char term, bool include) { + std::size_t new_len = 0; + std::size_t max_len = src.length(); + + while (new_len < max_len && src[new_len] != term) + new_len++; + + if (include && new_len < max_len) + new_len++; + + return src.substr(0, new_len); +} + +// ======================================================================== +// Byte array processing +// ======================================================================== + +std::string kaitai::kstream::process_xor_one(std::string data, uint8_t key) { + size_t len = data.length(); + std::string result(len, ' '); + + for (size_t i = 0; i < len; i++) + result[i] = data[i] ^ key; + + return result; +} + +std::string kaitai::kstream::process_xor_many(std::string data, std::string key) { + size_t len = data.length(); + size_t kl = key.length(); + std::string result(len, ' '); + + size_t ki = 0; + for (size_t i = 0; i < len; i++) { + result[i] = data[i] ^ key[ki]; + ki++; + if (ki >= kl) + ki = 0; + } + + return result; +} + +std::string kaitai::kstream::process_rotate_left(std::string data, int amount) { + size_t len = data.length(); + std::string result(len, ' '); + + for (size_t i = 0; i < len; i++) { + uint8_t bits = data[i]; + result[i] = (bits << amount) | (bits >> (8 - amount)); + } + + return result; +} + +#ifdef KS_ZLIB +#include + +std::string kaitai::kstream::process_zlib(std::string data) { + int ret; + + unsigned char *src_ptr = reinterpret_cast(&data[0]); + std::stringstream dst_strm; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + ret = inflateInit(&strm); + if (ret != Z_OK) + throw std::runtime_error("process_zlib: inflateInit error"); + + strm.next_in = src_ptr; + strm.avail_in = data.length(); + + unsigned char outbuffer[ZLIB_BUF_SIZE]; + std::string outstring; + + // get the decompressed bytes blockwise using repeated calls to inflate + do { + strm.next_out = reinterpret_cast(outbuffer); + strm.avail_out = sizeof(outbuffer); + + ret = inflate(&strm, 0); + + if (outstring.size() < strm.total_out) + outstring.append(reinterpret_cast(outbuffer), strm.total_out - outstring.size()); + } while (ret == Z_OK); + + if (ret != Z_STREAM_END) { // an error occurred that was not EOF + std::ostringstream exc_msg; + exc_msg << "process_zlib: error #" << ret << "): " << strm.msg; + throw std::runtime_error(exc_msg.str()); + } + + if (inflateEnd(&strm) != Z_OK) + throw std::runtime_error("process_zlib: inflateEnd error"); + + return outstring; +} +#endif + +// ======================================================================== +// Misc utility methods +// ======================================================================== + +int kaitai::kstream::mod(int a, int b) { + if (b <= 0) + throw std::invalid_argument("mod: divisor b <= 0"); + int r = a % b; + if (r < 0) + r += b; + return r; +} + +#include +void kaitai::kstream::unsigned_to_decimal(uint64_t number, char *buffer) { + // Implementation from https://ideone.com/nrQfA8 by Alf P. Steinbach + // (see https://www.zverovich.net/2013/09/07/integer-to-string-conversion-in-cplusplus.html#comment-1033931478) + if (number == 0) { + *buffer++ = '0'; + } else { + char *p_first = buffer; + while (number != 0) { + *buffer++ = static_cast('0' + number % 10); + number /= 10; + } + std::reverse(p_first, buffer); + } + *buffer = '\0'; +} + +std::string kaitai::kstream::reverse(std::string val) { + std::reverse(val.begin(), val.end()); + + return val; +} + +uint8_t kaitai::kstream::byte_array_min(const std::string val) { + uint8_t min = 0xff; // UINT8_MAX + std::string::const_iterator end = val.end(); + for (std::string::const_iterator it = val.begin(); it != end; ++it) { + uint8_t cur = static_cast(*it); + if (cur < min) { + min = cur; + } + } + return min; +} + +uint8_t kaitai::kstream::byte_array_max(const std::string val) { + uint8_t max = 0; // UINT8_MIN + std::string::const_iterator end = val.end(); + for (std::string::const_iterator it = val.begin(); it != end; ++it) { + uint8_t cur = static_cast(*it); + if (cur > max) { + max = cur; + } + } + return max; +} + +// ======================================================================== +// Other internal methods +// ======================================================================== + +#ifndef KS_STR_DEFAULT_ENCODING +#define KS_STR_DEFAULT_ENCODING "UTF-8" +#endif + +#ifdef KS_STR_ENCODING_ICONV + +#include +#include +#include + +std::string kaitai::kstream::bytes_to_str(std::string src, std::string src_enc) { + iconv_t cd = iconv_open(KS_STR_DEFAULT_ENCODING, src_enc.c_str()); + + if (cd == (iconv_t)-1) { + if (errno == EINVAL) { + throw std::runtime_error("bytes_to_str: invalid encoding pair conversion requested"); + } else { + throw std::runtime_error("bytes_to_str: error opening iconv"); + } + } + + size_t src_len = src.length(); + size_t src_left = src_len; + + // Start with a buffer length of double the source length. + size_t dst_len = src_len * 2; + std::string dst(dst_len, ' '); + size_t dst_left = dst_len; + + char *src_ptr = &src[0]; + char *dst_ptr = &dst[0]; + + while (true) { + size_t res = iconv(cd, &src_ptr, &src_left, &dst_ptr, &dst_left); + + if (res == (size_t)-1) { + if (errno == E2BIG) { + // dst buffer is not enough to accomodate whole string + // enlarge the buffer and try again + size_t dst_used = dst_len - dst_left; + dst_left += dst_len; + dst_len += dst_len; + dst.resize(dst_len); + + // dst.resize might have allocated destination buffer in another area + // of memory, thus our previous pointer "dst" will be invalid; re-point + // it using "dst_used". + dst_ptr = &dst[dst_used]; + } else { + throw std::runtime_error("bytes_to_str: iconv error"); + } + } else { + // conversion successful + dst.resize(dst_len - dst_left); + break; + } + } + + if (iconv_close(cd) != 0) { + throw std::runtime_error("bytes_to_str: iconv close error"); + } + + return dst; +} +#elif defined(KS_STR_ENCODING_NONE) +std::string kaitai::kstream::bytes_to_str(std::string src, std::string src_enc) { + return src; +} +#else +#error Need to decide how to handle strings: please define one of: KS_STR_ENCODING_ICONV, KS_STR_ENCODING_NONE +#endif diff --git a/exporters/geneva/test/decoder/kaitai/kaitaistream.h b/exporters/geneva/test/decoder/kaitai/kaitaistream.h new file mode 100644 index 000000000..3a6cff5fc --- /dev/null +++ b/exporters/geneva/test/decoder/kaitai/kaitaistream.h @@ -0,0 +1,297 @@ +#ifndef KAITAI_STREAM_H +#define KAITAI_STREAM_H + +// Kaitai Struct runtime API version: x.y.z = 'xxxyyyzzz' decimal +#define KAITAI_STRUCT_VERSION 9000L + +#include +#include +#include +#include +#include + +namespace kaitai { + +/** + * Kaitai Stream class (kaitai::kstream) is an implementation of + * Kaitai Struct stream API + * for C++/STL. It's implemented as a wrapper over generic STL std::istream. + * + * It provides a wide variety of simple methods to read (parse) binary + * representations of primitive types, such as integer and floating + * point numbers, byte arrays and strings, and also provides stream + * positioning / navigation methods with unified cross-language and + * cross-toolkit semantics. + * + * Typically, end users won't access Kaitai Stream class manually, but would + * describe a binary structure format using .ksy language and then would use + * Kaitai Struct compiler to generate source code in desired target language. + * That code, in turn, would use this class and API to do the actual parsing + * job. + */ +class kstream { +public: + /** + * Constructs new Kaitai Stream object, wrapping a given std::istream. + * \param io istream object to use for this Kaitai Stream + */ + kstream(std::istream *io); + + /** + * Constructs new Kaitai Stream object, wrapping a given in-memory data + * buffer. + * \param data data buffer to use for this Kaitai Stream + */ + kstream(const std::string &data); + + void close(); + + /** @name Stream positioning */ + //@{ + /** + * Check if stream pointer is at the end of stream. Note that the semantics + * are different from traditional STL semantics: one does *not* need to do a + * read (which will fail) after the actual end of the stream to trigger EOF + * flag, which can be accessed after that read. It is sufficient to just be + * at the end of the stream for this method to return true. + * \return "true" if we are located at the end of the stream. + */ + bool is_eof() const; + + /** + * Set stream pointer to designated position. + * \param pos new position (offset in bytes from the beginning of the stream) + */ + void seek(uint64_t pos); + + /** + * Get current position of a stream pointer. + * \return pointer position, number of bytes from the beginning of the stream + */ + uint64_t pos(); + + /** + * Get total size of the stream in bytes. + * \return size of the stream in bytes + */ + uint64_t size(); + //@} + + /** @name Integer numbers */ + //@{ + + // ------------------------------------------------------------------------ + // Signed + // ------------------------------------------------------------------------ + + int8_t read_s1(); + + // ........................................................................ + // Big-endian + // ........................................................................ + + int16_t read_s2be(); + int32_t read_s4be(); + int64_t read_s8be(); + + // ........................................................................ + // Little-endian + // ........................................................................ + + int16_t read_s2le(); + int32_t read_s4le(); + int64_t read_s8le(); + + // ------------------------------------------------------------------------ + // Unsigned + // ------------------------------------------------------------------------ + + uint8_t read_u1(); + + // ........................................................................ + // Big-endian + // ........................................................................ + + uint16_t read_u2be(); + uint32_t read_u4be(); + uint64_t read_u8be(); + + // ........................................................................ + // Little-endian + // ........................................................................ + + uint16_t read_u2le(); + uint32_t read_u4le(); + uint64_t read_u8le(); + + //@} + + /** @name Floating point numbers */ + //@{ + + // ........................................................................ + // Big-endian + // ........................................................................ + + float read_f4be(); + double read_f8be(); + + // ........................................................................ + // Little-endian + // ........................................................................ + + float read_f4le(); + double read_f8le(); + + //@} + + /** @name Unaligned bit values */ + //@{ + + void align_to_byte(); + uint64_t read_bits_int_be(int n); + uint64_t read_bits_int(int n); + uint64_t read_bits_int_le(int n); + + //@} + + /** @name Byte arrays */ + //@{ + + std::string read_bytes(std::streamsize len); + std::string read_bytes_full(); + std::string read_bytes_term(char term, bool include, bool consume, + bool eos_error); + std::string ensure_fixed_contents(std::string expected); + + static std::string bytes_strip_right(std::string src, char pad_byte); + static std::string bytes_terminate(std::string src, char term, bool include); + static std::string bytes_to_str(std::string src, std::string src_enc); + + //@} + + /** @name Byte array processing */ + //@{ + + /** + * Performs a XOR processing with given data, XORing every byte of input with + * a single given value. + * @param data data to process + * @param key value to XOR with + * @return processed data + */ + static std::string process_xor_one(std::string data, uint8_t key); + + /** + * Performs a XOR processing with given data, XORing every byte of input with + * a key array, repeating key array many times, if necessary (i.e. if data + * array is longer than key array). + * @param data data to process + * @param key array of bytes to XOR with + * @return processed data + */ + static std::string process_xor_many(std::string data, std::string key); + + /** + * Performs a circular left rotation shift for a given buffer by a given + * amount of bits, using groups of 1 bytes each time. Right circular rotation + * should be performed using this procedure with corrected amount. + * @param data source data to process + * @param amount number of bits to shift by + * @return copy of source array with requested shift applied + */ + static std::string process_rotate_left(std::string data, int amount); + +#ifdef KS_ZLIB + /** + * Performs an unpacking ("inflation") of zlib-compressed data with usual zlib + * headers. + * @param data data to unpack + * @return unpacked data + * @throws IOException + */ + static std::string process_zlib(std::string data); +#endif + + //@} + + /** + * Performs modulo operation between two integers: dividend `a` + * and divisor `b`. Divisor `b` is expected to be positive. The + * result is always 0 <= x <= b - 1. + */ + static int mod(int a, int b); + + /** + * Converts given integer `val` to a decimal string representation. + * Should be used in place of std::to_string() (which is available only + * since C++11) in older C++ implementations. + */ + template +// check for C++11 support - https://stackoverflow.com/a/40512515 +#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) + // https://stackoverflow.com/a/27913885 + typename std::enable_if< + std::is_integral::value && + // check if we don't have something too large like GCC's `__int128_t` + std::numeric_limits::max() >= 0 && + std::numeric_limits::max() <= std::numeric_limits::max(), + std::string>::type +#else + std::string +#endif + static to_string(I val) { + // in theory, `digits10 + 3` would be enough (minus sign + leading digit + // + null terminator), but let's add a little more to be safe + char buf[std::numeric_limits::digits10 + 5]; + if (val < 0) { + buf[0] = '-'; + // get absolute value without undefined behavior + // (https://stackoverflow.com/a/12231604) + unsigned_to_decimal(-static_cast(val), &buf[1]); + } else { + unsigned_to_decimal(val, buf); + } + return std::string(buf); + } + + /** + * Reverses given string `val`, so that the first character becomes the + * last and the last one becomes the first. This should be used to avoid + * the need of local variables at the caller. + */ + static std::string reverse(std::string val); + + /** + * Finds the minimal byte in a byte array, treating bytes as + * unsigned values. + * @param val byte array to scan + * @return minimal byte in byte array as integer + */ + static uint8_t byte_array_min(const std::string val); + + /** + * Finds the maximal byte in a byte array, treating bytes as + * unsigned values. + * @param val byte array to scan + * @return maximal byte in byte array as integer + */ + static uint8_t byte_array_max(const std::string val); + +private: + std::istream *m_io; + std::istringstream m_io_str; + int m_bits_left; + uint64_t m_bits; + + void init(); + void exceptions_enable() const; + + static void unsigned_to_decimal(uint64_t number, char *buffer); + + static const int ZLIB_BUF_SIZE = 128 * 1024; +}; + +} // namespace kaitai + +#endif diff --git a/exporters/geneva/test/decoder/kaitai/kaitaistruct.h b/exporters/geneva/test/decoder/kaitai/kaitaistruct.h new file mode 100644 index 000000000..e6de42444 --- /dev/null +++ b/exporters/geneva/test/decoder/kaitai/kaitaistruct.h @@ -0,0 +1,22 @@ +#ifndef KAITAI_STRUCT_H +#define KAITAI_STRUCT_H + +#include + +namespace kaitai { + +class kstruct { +public: + kstruct(kstream *_io) { m__io = _io; } + virtual ~kstruct() {} + +protected: + kstream *m__io; + +public: + kstream *_io() { return m__io; } +}; + +} // namespace kaitai + +#endif diff --git a/exporters/geneva/test/metrics_exporter_test.cc b/exporters/geneva/test/metrics_exporter_test.cc new file mode 100644 index 000000000..2381b183e --- /dev/null +++ b/exporters/geneva/test/metrics_exporter_test.cc @@ -0,0 +1,217 @@ +#include + +#include +#include +#include + +#include "opentelemetry/exporters/geneva/metrics/exporter.h" + +#include "common/generate_metrics.h" +#include "common/socket_server.h" +#include "decoder/ifx_metrics_bin.h" +#include "decoder/kaitai/kaitaistream.h" +#include + +using namespace SOCKET_SERVER_NS; +using namespace kaitai; +using namespace opentelemetry::sdk::metrics; +using namespace opentelemetry::exporter::geneva::metrics; + +const std::string kUnixDomainPath = "/tmp/ifx_unix_socket"; +const std::string kNamespaceName = "test_ns"; +const std::string kAccountName = "test_account"; + +// "busy sleep" while suggesting that other threads run +// for a small amount of time +template void yield_for(timeunit duration) { + auto start = std::chrono::high_resolution_clock::now(); + auto end = start + duration; + do { + std::this_thread::yield(); + } while (std::chrono::high_resolution_clock::now() < end); +} + +struct TestServer { + SocketServer &server; + std::atomic count{0}; + size_t count_counter_double = 0; + size_t count_counter_long = 0; + size_t count_histogram_long = 0; + + TestServer(SocketServer &server) : server(server) { + server.onRequest = [&](SocketServer::Connection &conn) { + try { + std::stringstream ss{conn.request_buffer}; + kaitai::kstream ks(&ss); + try { + ifx_metrics_bin_t event_bin = ifx_metrics_bin_t(&ks); + if (event_bin.event_id() == kCounterDoubleEventId) { + EXPECT_EQ(event_bin.event_id(), kCounterDoubleEventId); + auto event_body = event_bin.body(); + if (static_cast( + event_body->value_section()) + ->value() == kCounterDoubleValue1) { + EXPECT_EQ(event_body->num_dimensions(), + kCounterDoubleCountDimensions); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kCounterDoubleAttributeValue1); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kCounterDoubleAttributeKey1); + } + if (static_cast( + event_body->value_section()) + ->value() == kCounterDoubleValue2) { + EXPECT_EQ(event_body->num_dimensions(), + kCounterDoubleCountDimensions + 1); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kCounterDoubleAttributeValue2); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kCounterDoubleAttributeKey2); + EXPECT_EQ(event_body->dimensions_values()->at(1)->value(), + kCounterDoubleAttributeValue3); + EXPECT_EQ(event_body->dimensions_names()->at(1)->value(), + kCounterDoubleAttributeKey3); + } + EXPECT_EQ(event_body->metric_account()->value(), kAccountName); + EXPECT_EQ(event_body->metric_namespace()->value(), kNamespaceName); + EXPECT_EQ(event_body->metric_name()->value(), + kCounterDoubleInstrumentName); + count_counter_double++; + } else if (event_bin.event_id() == kCounterLongEventId) { + EXPECT_EQ(event_bin.event_id(), kCounterLongEventId); + auto event_body = event_bin.body(); + EXPECT_EQ(static_cast( + event_body->value_section()) + ->value(), + kCounterLongValue); + EXPECT_EQ(event_body->num_dimensions(), + kCounterLongCountDimensions); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kCounterLongAttributeValue1); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kCounterLongAttributeKey1); + count_counter_long++; + } else if (event_bin.event_id() == kHistogramLongEventId) { + EXPECT_EQ(event_bin.event_id(), kHistogramLongEventId); + auto event_body = event_bin.body(); + EXPECT_EQ(event_body->num_dimensions(), + kCounterLongCountDimensions); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kHistogramLongAttributeValue1); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kHistogramLongAttributeKey1); + EXPECT_EQ( + static_cast( + event_body->value_section()) + ->sum(), + kHistogramLongSum); + EXPECT_EQ( + static_cast( + event_body->value_section()) + ->min(), + kHistogramLongMin); + EXPECT_EQ( + static_cast( + event_body->value_section()) + ->max(), + kHistogramLongMax); + EXPECT_EQ( + static_cast( + event_body->histogram()->body()) + ->distribution_size(), + kHistogramLongNonEmptyBucketSize); + + size_t index_all_buckets = 0; + size_t index_nonempty_buckets = 0; + for (auto value : kHistogramLongBoundaries) { + if (kHistogramLongCounts[index_all_buckets] > 0) { + EXPECT_EQ( + static_cast( + static_cast< + ifx_metrics_bin_t::histogram_value_count_pairs_t *>( + event_body->histogram()->body()) + ->columns() + ->at(index_nonempty_buckets)) + ->count(), + kHistogramLongCounts[index_all_buckets]); + EXPECT_EQ( + static_cast( + static_cast< + ifx_metrics_bin_t::histogram_value_count_pairs_t *>( + event_body->histogram()->body()) + ->columns() + ->at(index_nonempty_buckets)) + ->value(), + value); + index_nonempty_buckets++; + } + index_all_buckets++; + } + + count_histogram_long++; + } + + } catch (...) { + EXPECT_NE("READ FAILED", "READ FAILED"); + } + conn.state.insert(SocketServer::Connection::Responding); + conn.request_buffer.clear(); + } catch (std::exception &) { + conn.state.insert(SocketServer::Connection::Receiving); + // skip invalid payload + } + }; + } + + void Start() { server.Start(); } + + void Stop() { server.Stop(); } + + void WaitForEvents(uint32_t expectedCount, uint32_t timeout) { + if (count.load() != expectedCount) { + yield_for(std::chrono::milliseconds(timeout)); + } + EXPECT_EQ(count.load(), expectedCount); + } +}; + +TEST(GenevaMetricsExporter, BasicTests) { + bool isRunning = true; + + // Start test server + SocketAddr destination(kUnixDomainPath.data(), true); + SocketParams params{AF_UNIX, SOCK_STREAM, 0}; + SocketServer socketServer(destination, params); + TestServer testServer(socketServer); + testServer.Start(); + yield_for(std::chrono::milliseconds(500)); + + // conn_string: + // `Endpoint=unix:{udsPath};Account={MetricAccount};Namespace={MetricNamespace}` + std::string conn_string = "Endpoint=unix://" + kUnixDomainPath + + ";Account=" + kAccountName + + ";Namespace=" + kNamespaceName; + ExporterOptions options{conn_string}; + opentelemetry::exporter::geneva::metrics::Exporter exporter(options); + + // export sum aggregation - double + auto metric_data = GenerateSumDataDoubleMetrics(); + exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(500)); + + // export sum aggregation - long + metric_data = GenerateSumDataLongMetrics(); + exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(500)); + + // export histogram aggregation - long + metric_data = GenerateHistogramDataLongMetrics(); + exporter.Export(metric_data); + + yield_for(std::chrono::milliseconds(5000)); + // EXPECT_EQ(testServer.count_counter_double, 2); + // EXPECT_EQ(testServer.count_counter_long, 1); + EXPECT_EQ(testServer.count_histogram_long, 1); + + testServer.Stop(); +} From 6ba63e0d16c90df9a908dad51e1632ce9c18f88f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 1 Nov 2022 09:32:34 -0700 Subject: [PATCH 28/77] [Geneva exporter] Upgrade to use opentelemetry-cpp v1.7.0 (#226) --- exporters/geneva/INSTALL.md | 2 +- exporters/geneva/example/example_metrics.cc | 6 +++--- .../opentelemetry/exporters/geneva/metrics/exporter.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/exporters/geneva/INSTALL.md b/exporters/geneva/INSTALL.md index f8ec96795..04df8444e 100644 --- a/exporters/geneva/INSTALL.md +++ b/exporters/geneva/INSTALL.md @@ -5,7 +5,7 @@ for the build # Prerequisite - - The exporter requires opentelemetry-cpp already installed. + - The exporter requires opentelemetry-cpp (version v1.7.0 or higher) already installed. - [GoogleTest](https://github.com/google/googletest) framework to build and run the unittests. diff --git a/exporters/geneva/example/example_metrics.cc b/exporters/geneva/example/example_metrics.cc index 0fe791cf7..350d8d36f 100644 --- a/exporters/geneva/example/example_metrics.cc +++ b/exporters/geneva/example/example_metrics.cc @@ -30,7 +30,7 @@ void initMetrics(const std::string &name, const std::string &account_name) { ";Account=" + account_name + ";Namespace=" + kNamespaceName; geneva_exporter::ExporterOptions options{conn_string}; - std::unique_ptr exporter{ + std::unique_ptr exporter{ new geneva_exporter::Exporter(options)}; std::string version{"1.2.0"}; @@ -83,9 +83,9 @@ void initMetrics(const std::string &name, const std::string &account_name) { new metric_sdk::MeterSelector(name, version, schema)}; std::shared_ptr aggregation_config{ - new opentelemetry::sdk::metrics::HistogramAggregationConfig}; + new opentelemetry::sdk::metrics::HistogramAggregationConfig()}; static_cast< - opentelemetry::sdk::metrics::HistogramAggregationConfig *>( + opentelemetry::sdk::metrics::HistogramAggregationConfig*>( aggregation_config.get()) ->boundaries_ = std::list{0.0, 50.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 10000.0}; diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h index d039d5478..efeeb3b74 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -7,7 +7,7 @@ #include "opentelemetry/exporters/geneva/metrics/connection_string_parser.h" #include "opentelemetry/exporters/geneva/metrics/data_transport.h" #include "opentelemetry/exporters/geneva/metrics/exporter_options.h" -#include "opentelemetry/sdk/metrics/metric_exporter.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { @@ -42,7 +42,7 @@ enum class MetricsEventType : uint16_t { /** * The Geneva metrics exporter exports metrics data to Geneva */ -class Exporter final : public opentelemetry::sdk::metrics::MetricExporter { +class Exporter final : public opentelemetry::sdk::metrics::PushMetricExporter { public: Exporter(const ExporterOptions &options); From 163a4eb8146bf48f664b3700e9eadb5f6b063f67 Mon Sep 17 00:00:00 2001 From: debasis9dash Date: Fri, 4 Nov 2022 12:26:17 +0530 Subject: [PATCH 29/77] added tests to run as merge check on Zipkin (#227) * added basic tests to be validated on Zipkin * resolved rview comments * added newline for gradle file * minr change as per latest collector image * added sleep after docker-compose * cloned forked repo to run the tests as its not merged to baserepo * added log to debug error * added logging level and minor change in tests * minor change * adding action to get the test report * adding action to get the test report * minr changes * fixed workflow error * changes for debug * changed collector host name on apache opentelemetry_module.conf * added newline char * removed git clone and used checkout action * removed temp code for debug --- .github/workflows/webserver.yml | 8 +++ .../otel-webserver-module/docker-compose.yml | 2 +- .../opentelemetry_module.conf | 2 +- .../otel-webserver-module/settings.gradle | 5 ++ .../test/integration/build.gradle | 34 +++++++++ .../src/test/java/restutils/BaseTest.java | 24 +++++++ .../src/test/java/restutils/LoadGenUtils.java | 19 +++++ .../src/test/java/restutils/RestClient.java | 17 +++++ .../test/java/restutils/ValidationUtils.java | 70 +++++++++++++++++++ .../src/test/java/utils/Constants.java | 13 ++++ .../src/test/java/utils/JsonUtils.java | 47 +++++++++++++ .../test/java/zipkin/TraceCreationTest.java | 26 +++++++ .../test/resources/testngsuites/testng.xml | 9 +++ 13 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 instrumentation/otel-webserver-module/settings.gradle create mode 100644 instrumentation/otel-webserver-module/test/integration/build.gradle create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/BaseTest.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/LoadGenUtils.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/RestClient.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/utils/Constants.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/utils/JsonUtils.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/java/zipkin/TraceCreationTest.java create mode 100644 instrumentation/otel-webserver-module/test/integration/src/test/resources/testngsuites/testng.xml diff --git a/.github/workflows/webserver.yml b/.github/workflows/webserver.yml index 5cf6746f1..6aa2af8b6 100644 --- a/.github/workflows/webserver.yml +++ b/.github/workflows/webserver.yml @@ -114,6 +114,14 @@ jobs: with: name: opentelemetry-webserver-sdk-x64-linux.tgz path: /tmp/apache_centos7/opentelemetry-webserver-sdk-x64-linux.tgz + - name: run integrationtest + run: | + docker rm -f apache_centos7_container + cd instrumentation/otel-webserver-module + docker-compose --profile centos7 up -d + docker ps -a + sleep 30 + ./gradlew :test:integration:integrationTests -i webserver-build-test-centos6: name: webserver-centos6-build diff --git a/instrumentation/otel-webserver-module/docker-compose.yml b/instrumentation/otel-webserver-module/docker-compose.yml index 8b2e431bf..6c35ac6ac 100644 --- a/instrumentation/otel-webserver-module/docker-compose.yml +++ b/instrumentation/otel-webserver-module/docker-compose.yml @@ -98,7 +98,7 @@ services: - centos_nginx - centos7_nginx - ubuntu20.04_nginx - command: ["--config=/etc/otel-config.yml", "${OTELCOL_ARGS}"] + command: ["--config=/etc/otel-config.yml"] volumes: - ./otel-config.yml:/etc/otel-config.yml ports: diff --git a/instrumentation/otel-webserver-module/opentelemetry_module.conf b/instrumentation/otel-webserver-module/opentelemetry_module.conf index b2b62ca22..efdc21d5d 100755 --- a/instrumentation/otel-webserver-module/opentelemetry_module.conf +++ b/instrumentation/otel-webserver-module/opentelemetry_module.conf @@ -13,7 +13,7 @@ ApacheModuleEnabled ON #ApacheModule Otel Exporter details ApacheModuleOtelSpanExporter otlp -ApacheModuleOtelExporterEndpoint docker.for.mac.localhost:4317 +ApacheModuleOtelExporterEndpoint collector:4317 # SSL Certificates #ApacheModuleOtelSslEnabled ON diff --git a/instrumentation/otel-webserver-module/settings.gradle b/instrumentation/otel-webserver-module/settings.gradle new file mode 100644 index 000000000..f71d3691d --- /dev/null +++ b/instrumentation/otel-webserver-module/settings.gradle @@ -0,0 +1,5 @@ +rootProject.name = 'otel-webserver-module' + +include 'test:integration' +findProject(':test:integration')?.name = 'integration' + diff --git a/instrumentation/otel-webserver-module/test/integration/build.gradle b/instrumentation/otel-webserver-module/test/integration/build.gradle new file mode 100644 index 000000000..b992de609 --- /dev/null +++ b/instrumentation/otel-webserver-module/test/integration/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'java' +} + +version '1.0' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.projectlombok:lombok:1.18.16' + implementation 'org.testng:testng:7.1.0' + annotationProcessor 'org.projectlombok:lombok:1.18.16' + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' + implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '1.7.36' + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5' + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.13.2' + implementation group: 'javax.ws.rs', name: 'javax.ws.rs-api', version: '2.1.1' + testImplementation group: 'io.rest-assured', name: 'rest-assured', version: '4.5.1' + testImplementation group: 'org.testng', name: 'testng', version: '6.14.3' + testImplementation group: 'io.rest-assured', name: 'json-schema-validator', version: '4.3.0' + implementation group: 'org.json', name: 'json', version: '20160810' + +} + +task integrationTests(type: Test) { + useTestNG() { + useDefaultListeners = true + suites 'src/test/resources/testngsuites/testng.xml' + } +} diff --git a/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/BaseTest.java b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/BaseTest.java new file mode 100644 index 000000000..7d04a1967 --- /dev/null +++ b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/BaseTest.java @@ -0,0 +1,24 @@ +package restutils; + +import io.restassured.RestAssured; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeSuite; + +import static utils.Constants.WEBSERVER_URL; +import static utils.Constants.ZIPKIN_URL; + +public class BaseTest { + + private String ZIPKIN_SERVICE_NAME = "zipkin"; + private LoadGenUtils loadGenUtils = new LoadGenUtils(); + + @BeforeSuite + public void setup() { + RestAssured.baseURI = ZIPKIN_URL; + } + + @BeforeClass + public void generateLoad(){ + loadGenUtils.generateLoad(WEBSERVER_URL, 90); + } +} diff --git a/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/LoadGenUtils.java b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/LoadGenUtils.java new file mode 100644 index 000000000..281b5755a --- /dev/null +++ b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/LoadGenUtils.java @@ -0,0 +1,19 @@ +package restutils; + +import io.restassured.RestAssured; + +public class LoadGenUtils { + + public void generateLoad(String Uri, int count) { + while(count > 0){ + RestAssured.given().get(Uri); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + count --; + } + + } +} diff --git a/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/RestClient.java b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/RestClient.java new file mode 100644 index 000000000..bb4cc7337 --- /dev/null +++ b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/RestClient.java @@ -0,0 +1,17 @@ +package restutils; + +import io.restassured.RestAssured; +import io.restassured.response.Response; +import static io.restassured.RestAssured.given; + +public class RestClient { + + public static Response getResponse(String Uri){ + given().when().get(Uri).then().log() + .all() + .assertThat() + .statusCode(200); + + return RestAssured.given().get(Uri); + } +} \ No newline at end of file diff --git a/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java new file mode 100644 index 000000000..24020d64d --- /dev/null +++ b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java @@ -0,0 +1,70 @@ +package restutils; + +import io.restassured.response.Response; +import org.json.JSONArray; +import org.json.JSONObject; +import org.testng.Assert; +import java.util.logging.Logger; +import static utils.Constants.*; + + +public class ValidationUtils extends BaseTest{ + + private static final Logger LOGGER = Logger.getLogger(ValidationUtils.class.getName()); + public RestClient restClient = new RestClient(); + public Response response; + + public void valiateResponseWithKey(Response response, String key) { + + } + + public void verifyAllTraces() { + response = restClient.getResponse(ZIPKIN_URL + TRACES); + LOGGER.info(response.body().asString()); + JSONArray jsonArray = new JSONArray(response.getBody().asString()); + for(int i=0; i keys; + String nextKeys; + + if(!exists) { + keys = json.keys(); + while(keys.hasNext()){ + nextKeys = (String)keys.next(); + try{ + if(json.get(nextKeys) instanceof JSONObject) { + if(!exists) { + validateComplexJson(json.getJSONObject(nextKeys), key); + } else if (json.get(nextKeys) instanceof JsonArray) { + JSONArray jsonArray = json.getJSONArray(nextKeys); + for(int i=0; i + + + + + + + + From 17237adc1cef483cce37c9720fcb907b9b15b5dd Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Fri, 4 Nov 2022 16:10:08 +0530 Subject: [PATCH 30/77] Support to capture http headers and set as Span attributes. (#224) * Support for Capturing http Headers for Nginx * Corrected the build failure * Capture request and response headers only if headers are specified * Changed the delimiter to comma --- .../include/core/api/Payload.h | 13 ++ .../core/api/RequestProcessingEngine.h | 7 +- .../include/core/api/WSAgent.h | 3 +- .../include/core/api/opentelemetry_ngx_api.h | 18 ++- .../src/core/api/RequestProcessingEngine.cpp | 21 ++- .../src/core/api/WSAgent.cpp | 4 +- .../src/core/api/opentelemetry_ngx_api.cpp | 63 +++++++-- .../src/nginx/ngx_http_opentelemetry_module.c | 122 ++++++++++++++---- .../src/nginx/ngx_http_opentelemetry_module.h | 5 +- .../test/unit/WSAgent_test.cpp | 2 +- .../unit/mocks/mock_RequestProcessingEngine.h | 3 +- 11 files changed, 215 insertions(+), 46 deletions(-) diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index 6d24fcaad..cc743b95b 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -38,6 +38,7 @@ class RequestPayload std::string http_request_method; /* Request method (eg. GET, HEAD, POST, etc.) */ std::unordered_map http_headers; /* HTTP Request headers: Cookie, Referer, SM_USER*/ + std::unordered_map request_headers; std::string server_name; std::string scheme; @@ -53,6 +54,10 @@ class RequestPayload { http_headers[key] = value; } + void set_request_headers(const std::string& key, const std::string& value) + { + request_headers[key] = value; + } void set_uri(const char* URI) { uri = URI; } void set_request_protocol(const char* requestProtocol) {request_protocol = requestProtocol; } void set_http_get_parameter(const char* httpGetParameter) {http_get_parameter = httpGetParameter; } @@ -82,6 +87,14 @@ class RequestPayload std::string get_client_ip() {return client_ip; } long get_port() {return port; } long get_status_code() {return status_code; } + std::unordered_map& get_request_headers() { + return request_headers; + } +}; + +struct ResponsePayload +{ + std::unordered_map response_headers; }; struct InteractionPayload diff --git a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h index fa114cb8f..4b83d0df8 100644 --- a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h +++ b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h @@ -29,6 +29,7 @@ namespace core { class TenantConfig; class RequestPayload; +class ResponsePayload; class InteractionPayload; class EndInteractionPayload; @@ -50,7 +51,8 @@ class IRequestProcessingEngine { APPD_SDK_HANDLE_REQ* reqHandle) = 0; virtual APPD_SDK_STATUS_CODE endRequest( APPD_SDK_HANDLE_REQ reqHandle, - const char* error) = 0; + const char* error, + const ResponsePayload* payload = nullptr) = 0; virtual APPD_SDK_STATUS_CODE startInteraction( APPD_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, @@ -75,7 +77,8 @@ class RequestProcessingEngine : public IRequestProcessingEngine { APPD_SDK_HANDLE_REQ* reqHandle) override; APPD_SDK_STATUS_CODE endRequest( APPD_SDK_HANDLE_REQ reqHandle, - const char* error) override; + const char* error, + const ResponsePayload* payload = nullptr) override; APPD_SDK_STATUS_CODE startInteraction( APPD_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, diff --git a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h index 2a7ad29c4..c9dc5eab5 100644 --- a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h +++ b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h @@ -62,7 +62,8 @@ class WSAgent APPD_SDK_STATUS_CODE endRequest( APPD_SDK_HANDLE_REQ reqHandle, - const char* error); + const char* error, + const ResponsePayload* payload = nullptr ); APPD_SDK_STATUS_CODE startInteraction( APPD_SDK_HANDLE_REQ reqHandle, diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index 099e9090f..7b2e29f83 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -40,9 +40,18 @@ typedef struct { const char* http_get_param; const char* http_post_param; const char* request_method; - http_headers* headers; + http_headers* propagation_headers; + http_headers* request_headers; + + int propagation_count; + int request_headers_count; }request_payload; +typedef struct { + http_headers* response_headers; + int response_headers_count; +}response_payload; + typedef struct{ const char* cName; const char* sNamespace; @@ -56,12 +65,13 @@ struct cNode{ }; void initDependency(); -void populatePayload(request_payload* req_payload, void* payload, int count); +void populatePayload(request_payload* req_payload, void* payload); +void setRequestResponseHeaders(const char* request, const char* response); APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN); -APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle, int count); +APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle); APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int* ix); APPD_SDK_STATUS_CODE stopModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg); -APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg); +APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg, response_payload* payload); #ifdef __cplusplus } diff --git a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp index 8d4f3cfc0..f8faa33cc 100644 --- a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp @@ -35,6 +35,9 @@ namespace core { using namespace sdkwrapper; +constexpr const char* http_request_header = "http.request.header."; +constexpr const char* http_response_header = "http.response.header."; + RequestProcessingEngine::RequestProcessingEngine() : mLogger(getLogger(std::string(LogContext::AGENT) + ".RequestProcessingEngine")) { @@ -73,6 +76,13 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startRequest( keyValueMap[kAttrHTTPFlavor] = payload->get_flavor(); keyValueMap[kAttrHTTPStatusCode] = payload->get_status_code(); keyValueMap[kAttrHTTPClientIP] = payload->get_client_ip(); + + auto& request_headers = payload->get_request_headers(); + for (auto itr = request_headers.begin(); itr != request_headers.end(); itr++) { + std::string key = std::string(http_request_header) + + std::string(itr->first); + keyValueMap[key] = itr->second; + } auto span = m_sdkWrapper->CreateSpan(spanName, sdkwrapper::SpanKind::SERVER, keyValueMap, payload->get_http_headers()); LOG4CXX_TRACE(mLogger, "Span started for context: [" << wscontext @@ -89,7 +99,8 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startRequest( APPD_SDK_STATUS_CODE RequestProcessingEngine::endRequest( APPD_SDK_HANDLE_REQ reqHandle, - const char* error) { + const char* error, + const ResponsePayload* payload) { if (!reqHandle) { LOG4CXX_ERROR(mLogger, "Invalid request, can't end request"); @@ -139,6 +150,14 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::endRequest( } else { rootSpan->SetStatus(StatusCode::Ok); } + if (payload != nullptr) { + for (auto itr = payload->response_headers.begin(); + itr != payload->response_headers.end(); itr++) { + std::string key = std::string(http_response_header) + + std::string(itr->first); + rootSpan->AddAttribute(key, itr->second); + } + } LOG4CXX_TRACE(mLogger, "Ending root span with id: " << rootSpan.get()); rootSpan->End(); diff --git a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp index 6e163ed94..0e8107904 100644 --- a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp @@ -110,7 +110,7 @@ WSAgent::startRequest( APPD_SDK_STATUS_CODE WSAgent::endRequest( APPD_SDK_HANDLE_REQ reqHandle, - const char* error) + const char* error, const ResponsePayload* payload) { // TODO: How to get the context here? // one solution is get it from reqHandle. @@ -121,7 +121,7 @@ WSAgent::endRequest( auto *engine = mAgentCore->getRequestProcessor(context); if (nullptr != engine) { - return engine->endRequest(reqHandle, error); + return engine->endRequest(reqHandle, error, payload); } return APPD_STATUS(fail); } diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index 5e4580c1d..d3126800c 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -18,11 +18,16 @@ #include "api/WSAgent.h" #include "api/Payload.h" #include - +#include +#include +#include appd::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic +std::unordered_set requestHeadersToCapture; +std::unordered_set responseHeadersToCapture; +constexpr char delimiter = ','; -void populatePayload(request_payload* req_payload, void* load, int count) +void populatePayload(request_payload* req_payload, void* load) { appd::core::RequestPayload* payload = (appd::core::RequestPayload*)load; payload->set_uri(req_payload->uri); @@ -31,8 +36,35 @@ void populatePayload(request_payload* req_payload, void* load, int count) payload->set_http_get_parameter(req_payload->http_get_param); payload->set_http_request_method(req_payload->request_method); - for(int i=0; iset_http_headers(req_payload->headers[i].name, req_payload->headers[i].value); + for(int i=0; ipropagation_count; i++){ + payload->set_http_headers(req_payload->propagation_headers[i].name, req_payload->propagation_headers[i].value); + } + + for (int i = 0; i < req_payload->request_headers_count; i++) { + std::string key(req_payload->request_headers[i].name); + if (requestHeadersToCapture.find(key) + != requestHeadersToCapture.end()) { + payload->set_request_headers(key, + req_payload->request_headers[i].value); + } + } +} + +void setRequestResponseHeaders(const char* request, const char* response) +{ + std::string token; + std::stringstream ss; + + ss.str(std::string(request)); + while(getline(ss, token, delimiter)) { + requestHeadersToCapture.insert(token); + } + + token.clear(); + ss.clear(); + ss.str(std::string(response)); + while(getline(ss, token, delimiter)) { + responseHeadersToCapture.insert(token); } } @@ -60,21 +92,36 @@ APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned return res; } -APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle, int count) +APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle) { APPD_SDK_STATUS_CODE res = APPD_SUCCESS; std::unique_ptr requestPayload(new appd::core::RequestPayload); - populatePayload(req_payload, requestPayload.get(), count); + populatePayload(req_payload, requestPayload.get()); res = wsAgent.startRequest(wscontext, requestPayload.get(), reqHandle); return res; } -APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg) +APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg, + response_payload* payload) { APPD_SDK_STATUS_CODE res = APPD_SUCCESS; - res = wsAgent.endRequest(req_handle_key, errMsg); + + std::unique_ptr + responsePayload(new appd::core::ResponsePayload); + if (payload != NULL) { + for (int i = 0; i < payload->response_headers_count; i++) { + std::string key(payload->response_headers[i].name); + if (responseHeadersToCapture.find(key) + != responseHeadersToCapture.end()) { + responsePayload->response_headers[key] + = payload->response_headers[i].value; + } + } + } + + res = wsAgent.endRequest(req_handle_key, errMsg, responsePayload.get()); return res; } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 3a4822998..8aee79189 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -355,6 +355,20 @@ static ngx_command_t ngx_http_opentelemetry_commands[] = { offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleSegmentParameter), NULL}, + { ngx_string("NginxModuleRequestHeaders"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleRequestHeaders), + NULL}, + + { ngx_string("NginxModuleResponseHeaders"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleResponseHeaders), + NULL}, + ngx_null_command /* command termination */ }; @@ -454,6 +468,8 @@ static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, ngx_conf_merge_str_value(conf->nginxModuleSegmentType, prev->nginxModuleSegmentType, "First"); ngx_conf_merge_str_value(conf->nginxModuleSegmentParameter, prev->nginxModuleSegmentParameter, "2"); + ngx_conf_merge_str_value(conf->nginxModuleRequestHeaders, prev->nginxModuleRequestHeaders, ""); + ngx_conf_merge_str_value(conf->nginxModuleResponseHeaders, prev->nginxModuleResponseHeaders, ""); return NGX_CONF_OK; } @@ -1013,7 +1029,8 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) cn = cn->next; } } - + setRequestResponseHeaders((const char*)(conf->nginxModuleRequestHeaders).data, + (const char*)(conf->nginxModuleResponseHeaders).data); res = opentelemetry_core_init(env_config, ix, rootCN); free(qs); free(sd); @@ -1071,6 +1088,13 @@ static void stopMonitoringRequest(ngx_http_request_t* r, ngx_writeTrace(r->connection->log, __func__, "Stopping the Request Monitoring"); + response_payload* res_payload = NULL; + if (r->pool) { + res_payload = ngx_pcalloc(r->pool, sizeof(response_payload)); + res_payload->response_headers_count = 0; + fillResponsePayload(res_payload, r); + } + APPD_SDK_STATUS_CODE res; unsigned int errCode=0; char* msg = NULL; @@ -1080,11 +1104,11 @@ static void stopMonitoringRequest(ngx_http_request_t* r, errCode=(unsigned int)otel_getErrorCode(r); msg = (char*)malloc(6); sprintf(msg, "%d", errCode); - res = endRequest(otel_req_handle_key, msg); + res = endRequest(otel_req_handle_key, msg, res_payload); } else { - res = endRequest(otel_req_handle_key, msg); + res = endRequest(otel_req_handle_key, msg, res_payload); } if (APPD_ISSUCCESS(res)) @@ -1152,10 +1176,9 @@ static void startMonitoringRequest(ngx_http_request_t* r){ { ngx_writeError(r->connection->log, __func__, "Not able to get memory for request payload"); } - int header_count = 0; - fillRequestPayload(req_payload, r, &header_count); + fillRequestPayload(req_payload, r); - res = startRequest(wscontext, req_payload, &reqHandle, header_count); + res = startRequest(wscontext, req_payload, &reqHandle); if (APPD_ISSUCCESS(res)) { @@ -1503,7 +1526,7 @@ static void removeUnwantedHeader(ngx_http_request_t* r) } } -static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r, int* count){ +static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r){ ngx_list_part_t *part; ngx_table_elt_t *header; ngx_uint_t nelts; @@ -1540,23 +1563,72 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* } } - part = &r->headers_in.headers.part; - header = (ngx_table_elt_t*)part->elts; - nelts = part->nelts; + ngx_http_opentelemetry_loc_conf_t *conf = + ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + part = &r->headers_in.headers.part; + header = (ngx_table_elt_t*)part->elts; + nelts = part->nelts; + + req_payload->propagation_headers = ngx_pcalloc(r->pool, nelts * sizeof(http_headers)); + req_payload->request_headers = ngx_pcalloc(r->pool, nelts * sizeof(http_headers)); + int request_headers_idx = 0; + int propagation_headers_idx = 0; + for (ngx_uint_t j = 0; j < nelts; j++) { + + h = &header[j]; + for (int i = 0; i < headers_len; i++) { + + if (strcmp(h->key.data, httpHeaders[i]) == 0) { + req_payload->propagation_headers[propagation_headers_idx].name = httpHeaders[i]; + req_payload->propagation_headers[propagation_headers_idx].value = (const char*)(h->value).data; + if (req_payload->propagation_headers[propagation_headers_idx].value == NULL) { + req_payload->propagation_headers[propagation_headers_idx].value = ""; + } + propagation_headers_idx++; + break; + } + } - req_payload->headers = ngx_pcalloc(r->pool, headers_len * sizeof(http_headers)); - for(int i=0; iheaders[*count].name = c; - for(ngx_uint_t j = 0; jkey.data)==0){ - req_payload->headers[*count].value = (const char*)(h->value).data; - } - } - if(!req_payload->headers[*count].value){ - req_payload->headers[*count].value = "No Param"; - } - ++(*count); - } + req_payload->request_headers[request_headers_idx].name = (const char*)(h->key).data; + req_payload->request_headers[request_headers_idx].value = (const char*)(h->value).data; + if (req_payload->request_headers[request_headers_idx].value == NULL) { + req_payload->request_headers[request_headers_idx].value = ""; + } + request_headers_idx++; + } + req_payload->propagation_count = propagation_headers_idx; + req_payload->request_headers_count = request_headers_idx; +} + +static void fillResponsePayload(response_payload* res_payload, ngx_http_request_t* r) +{ + if (!r->pool) { + return; + } + + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_uint_t nelts; + ngx_table_elt_t *h; + + part = &r->headers_out.headers.part; + header = (ngx_table_elt_t*)part->elts; + nelts = part->nelts; + + res_payload->response_headers = ngx_pcalloc(r->pool, nelts * sizeof(http_headers)); + ngx_uint_t headers_count = 0; + + for (ngx_uint_t j = 0; j < nelts; j++) { + h = &header[j]; + + if (headers_count < nelts) { + res_payload->response_headers[headers_count].name = (const char*)(h->key).data; + res_payload->response_headers[headers_count].value = (const char*)(h->value).data; + if (res_payload->response_headers[headers_count].value == NULL) { + res_payload->response_headers[headers_count].value = ""; + } + headers_count++; + } + } + res_payload->response_headers_count = headers_count; } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h index 980920b20..9149649c3 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -98,6 +98,8 @@ typedef struct { ngx_str_t nginxModuleMatchpattern; ngx_str_t nginxModuleSegmentType; ngx_str_t nginxModuleSegmentParameter; + ngx_str_t nginxModuleRequestHeaders; + ngx_str_t nginxModuleResponseHeaders; } ngx_http_opentelemetry_loc_conf_t; /* @@ -135,7 +137,8 @@ static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf); static ngx_int_t ngx_http_opentelemetry_init_worker(ngx_cycle_t *cycle); static void ngx_http_opentelemetry_exit_worker(ngx_cycle_t *cycle); static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r); -static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r, int* count); +static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* r); +static void fillResponsePayload(response_payload* res_payload, ngx_http_request_t* r); static void startMonitoringRequest(ngx_http_request_t* r); static void stopMonitoringRequest(ngx_http_request_t* r, APPD_SDK_HANDLE_REQ request_handle_key); diff --git a/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp b/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp index ba7f542b6..18d9fb2fa 100644 --- a/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp @@ -468,7 +468,7 @@ TEST(WSAgent, end_request_returns_success) })); APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; - EXPECT_CALL(mockProcessor, endRequest(_,_)) + EXPECT_CALL(mockProcessor, endRequest(_,_,_)) .Times(1) .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ return res1; diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h index 224e1f471..cb8c376c8 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h @@ -32,7 +32,8 @@ class MockRequestProcessingEngine : public appd::core::IRequestProcessingEngine MOCK_METHOD(APPD_SDK_STATUS_CODE, endRequest, ( APPD_SDK_HANDLE_REQ reqHandle, - const char* error), (override)); + const char* error, + const appd::core::ResponsePayload* payload), (override)); APPD_SDK_STATUS_CODE startInteraction( APPD_SDK_HANDLE_REQ reqHandle, From 0ffedb3406a42627aa5e20aed77e5d21ad133888 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:00:21 +0530 Subject: [PATCH 31/77] Adding License (#233) --- .../include/apache/ApacheConfig.h | 2 +- .../include/apache/ApacheHooks.h | 2 +- .../include/apache/ExcludedModules.h | 2 +- .../include/apache/HookContainer.h | 2 +- .../include/core/AgentCore.h | 2 +- .../include/core/AgentLogger.h | 2 +- .../include/core/RequestContext.h | 2 +- .../include/core/api/ApiUtils.h | 2 +- .../include/core/api/AppdynamicsSdk.h | 2 +- .../include/core/api/Interface.h | 2 +- .../include/core/api/Payload.h | 2 +- .../include/core/api/RequestProcessingEngine.h | 2 +- .../include/core/api/SpanNamer.h | 2 +- .../include/core/api/TenantConfig.h | 2 +- .../include/core/api/WSAgent.h | 2 +- .../include/core/api/opentelemetry_ngx_api.h | 2 +- .../include/core/sdkwrapper/IScopedSpan.h | 2 +- .../include/core/sdkwrapper/ISdkHelperFactory.h | 2 +- .../include/core/sdkwrapper/ISdkWrapper.h | 2 +- .../include/core/sdkwrapper/ScopedSpan.h | 2 +- .../include/core/sdkwrapper/SdkConstants.h | 2 +- .../include/core/sdkwrapper/SdkEnums.h | 2 +- .../include/core/sdkwrapper/SdkHelperFactory.h | 2 +- .../include/core/sdkwrapper/SdkUtils.h | 2 +- .../include/core/sdkwrapper/SdkWrapper.h | 2 +- .../include/core/sdkwrapper/ServerSpan.h | 2 +- .../include/util/SpanNamingUtils.h | 2 +- .../src/apache/ApacheConfig.cpp | 2 +- .../src/apache/ApacheHooks.cpp | 2 +- .../src/apache/ApacheTracing.cpp | 2 +- .../src/apache/ApacheTracing.h | 2 +- .../src/apache/ExcludedModules.cpp | 2 +- .../src/apache/HookContainer.cpp | 2 +- .../src/apache/mod_apache_otel.cpp | 2 +- .../otel-webserver-module/src/core/AgentCore.cpp | 2 +- .../src/core/AgentLogger.cpp | 2 +- .../src/core/api/ApiUtils.cpp | 2 +- .../src/core/api/RequestProcessingEngine.cpp | 2 +- .../src/core/api/SpanNamer.cpp | 2 +- .../src/core/api/WSAgent.cpp | 2 +- .../src/core/api/opentelemetry_ngx_api.cpp | 2 +- .../src/core/sdkwrapper/ScopedSpan.cpp | 2 +- .../src/core/sdkwrapper/SdkHelperFactory.cpp | 2 +- .../src/core/sdkwrapper/SdkWrapper.cpp | 2 +- .../src/core/sdkwrapper/ServerSpan.cpp | 2 +- .../src/util/SpanNamingUtils.cpp | 2 +- .../test/unit/AgentCore_test.cpp | 2 +- .../test/unit/ApiUtils_test.cpp | 2 +- .../test/unit/RequestProcessingEngine_test.cpp | 2 +- .../test/unit/ScopedSpan_test.cpp | 2 +- .../test/unit/SdkUtils_test.cpp | 2 +- .../test/unit/SdkWrapper_test.cpp | 2 +- .../test/unit/ServerSpan_test.cpp | 2 +- .../test/unit/SpanNamer_test.cpp | 15 +++++++++++++++ .../test/unit/WSAgent_test.cpp | 2 +- .../test/unit/integration_test.cpp | 2 +- .../otel-webserver-module/test/unit/unit_test.cpp | 2 +- 57 files changed, 71 insertions(+), 56 deletions(-) diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h index 9e72af3b2..81e872e79 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h index 1ba75db79..1777f440a 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h b/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h index 80179b994..29d01fddc 100644 --- a/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h +++ b/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/apache/HookContainer.h b/instrumentation/otel-webserver-module/include/apache/HookContainer.h index 839f052db..3a757fda9 100644 --- a/instrumentation/otel-webserver-module/include/apache/HookContainer.h +++ b/instrumentation/otel-webserver-module/include/apache/HookContainer.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/AgentCore.h b/instrumentation/otel-webserver-module/include/core/AgentCore.h index c23487d63..68dfad2ae 100644 --- a/instrumentation/otel-webserver-module/include/core/AgentCore.h +++ b/instrumentation/otel-webserver-module/include/core/AgentCore.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/AgentLogger.h b/instrumentation/otel-webserver-module/include/core/AgentLogger.h index fc500dbac..77ff437ac 100755 --- a/instrumentation/otel-webserver-module/include/core/AgentLogger.h +++ b/instrumentation/otel-webserver-module/include/core/AgentLogger.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/RequestContext.h b/instrumentation/otel-webserver-module/include/core/RequestContext.h index 5df50e67f..00749744f 100644 --- a/instrumentation/otel-webserver-module/include/core/RequestContext.h +++ b/instrumentation/otel-webserver-module/include/core/RequestContext.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h b/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h index 42eb47e5c..db8b525be 100644 --- a/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h +++ b/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h b/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h index 76b660e12..2d42e13ef 100755 --- a/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h +++ b/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/Interface.h b/instrumentation/otel-webserver-module/include/core/api/Interface.h index fa01298f3..b704c9ef2 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Interface.h +++ b/instrumentation/otel-webserver-module/include/core/api/Interface.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index cc743b95b..615669ba1 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h index 4b83d0df8..b1b28a4d9 100644 --- a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h +++ b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h b/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h index 78f82558b..ba7e53ddb 100644 --- a/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h +++ b/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h index 8134854e0..7069c1647 100644 --- a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h +++ b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h index c9dc5eab5..abe2817ef 100644 --- a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h +++ b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index 7b2e29f83..a89f7b86e 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h index d0f992c18..21645173e 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h index 5069a1e22..3d58baeb9 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h index 4caf8fed7..4438cea8d 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h index 6f76331c8..3b95378c7 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h index 2d4e3006b..d2835280c 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h index bf75a055c..339693887 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h index 60654d9b1..7561d0950 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h index 8cabb0223..92bb186d2 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h index 37ff63c30..93196c2b0 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h index 9c2a95c3a..338cc3b8c 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/include/util/SpanNamingUtils.h b/instrumentation/otel-webserver-module/include/util/SpanNamingUtils.h index 50d2a9720..4bcb153b7 100755 --- a/instrumentation/otel-webserver-module/include/util/SpanNamingUtils.h +++ b/instrumentation/otel-webserver-module/include/util/SpanNamingUtils.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp index 62b2a30cf..0e7d2fbe2 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index c521958b0..c07c736d2 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp index a19ba70a4..5eb36b43b 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h index b92fc83b0..72717c54c 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h +++ b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/ExcludedModules.cpp b/instrumentation/otel-webserver-module/src/apache/ExcludedModules.cpp index ecff08f1b..f9bd8fc2f 100644 --- a/instrumentation/otel-webserver-module/src/apache/ExcludedModules.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ExcludedModules.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp b/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp index 0a984756e..d4c06465e 100644 --- a/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp +++ b/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp index 7dd8d28df..3a04bf6da 100644 --- a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp +++ b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/AgentCore.cpp b/instrumentation/otel-webserver-module/src/core/AgentCore.cpp index 76429cb81..5d5122796 100644 --- a/instrumentation/otel-webserver-module/src/core/AgentCore.cpp +++ b/instrumentation/otel-webserver-module/src/core/AgentCore.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/AgentLogger.cpp b/instrumentation/otel-webserver-module/src/core/AgentLogger.cpp index 591395477..0344a5324 100755 --- a/instrumentation/otel-webserver-module/src/core/AgentLogger.cpp +++ b/instrumentation/otel-webserver-module/src/core/AgentLogger.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp index 6e2ebeadf..6dbe1572b 100755 --- a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp index f8faa33cc..5ea643d8a 100644 --- a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp b/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp index 4ccf876b7..b328a588b 100644 --- a/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp index 0e8107904..20c5438ee 100644 --- a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index d3126800c..e9b449847 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp index d697dd09b..6d19c769e 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp index 056edbf7a..8a75ac8b3 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp index bf5670172..ebac105f6 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp index 240e7615c..63defff4d 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/util/SpanNamingUtils.cpp b/instrumentation/otel-webserver-module/src/util/SpanNamingUtils.cpp index 1eddd30be..8d5aa9cb4 100755 --- a/instrumentation/otel-webserver-module/src/util/SpanNamingUtils.cpp +++ b/instrumentation/otel-webserver-module/src/util/SpanNamingUtils.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp b/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp index 5da54033c..e303fda02 100644 --- a/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp b/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp index e5973df70..db8867808 100644 --- a/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp index 1651c3664..85dd5f783 100644 --- a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp b/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp index a7ca78bc7..955913b61 100644 --- a/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp b/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp index 48f852936..31f87c719 100644 --- a/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp b/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp index 17a2b02e6..9828e929f 100644 --- a/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp b/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp index f5d5ecf1d..d910e9182 100644 --- a/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp b/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp index b8e7aa64a..6d83bef3e 100644 --- a/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp @@ -1,3 +1,18 @@ +/* +* Copyright 2022, OpenTelemetry Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ #include "gtest/gtest.h" #include "api/SpanNamer.h" #include "SpanNamingUtils.h" diff --git a/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp b/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp index 18d9fb2fa..8fb9aaeb1 100644 --- a/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/integration_test.cpp b/instrumentation/otel-webserver-module/test/unit/integration_test.cpp index 96da0eb5b..88ef49232 100644 --- a/instrumentation/otel-webserver-module/test/unit/integration_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/integration_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/unit_test.cpp b/instrumentation/otel-webserver-module/test/unit/unit_test.cpp index 0f0282399..d76eb9191 100644 --- a/instrumentation/otel-webserver-module/test/unit/unit_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/unit_test.cpp @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From e07909bb15d3f7357136ef45df4d750fa1ac0037 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:29:29 +0530 Subject: [PATCH 32/77] Adding Missing Attributes (#234) * Adding Servername * Add Scheme * Adding flavor and target * hostname * Adding comment --- .../include/core/api/opentelemetry_ngx_api.h | 5 +++ .../src/core/api/opentelemetry_ngx_api.cpp | 6 ++++ .../src/nginx/ngx_http_opentelemetry_module.c | 35 +++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index a89f7b86e..afcbfa91c 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -36,10 +36,15 @@ typedef struct{ /* Structure for the request payload */ typedef struct { const char* uri; + const char* server_name; + const char* scheme; + const char* flavor; + const char* hostname; const char* protocol; const char* http_get_param; const char* http_post_param; const char* request_method; + const char* client_ip; http_headers* propagation_headers; http_headers* request_headers; diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index e9b449847..388060aa0 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -31,10 +31,16 @@ void populatePayload(request_payload* req_payload, void* load) { appd::core::RequestPayload* payload = (appd::core::RequestPayload*)load; payload->set_uri(req_payload->uri); + payload->set_scheme(req_payload->scheme); + payload->set_flavor(req_payload->flavor); + payload->set_target(req_payload->uri); + payload->set_host(req_payload->hostname); + payload->set_server_name(req_payload->server_name); payload->set_request_protocol(req_payload->protocol); payload->set_http_post_parameter(req_payload->http_post_param); payload->set_http_get_parameter(req_payload->http_get_param); payload->set_http_request_method(req_payload->request_method); + payload->set_client_ip(req_payload->client_ip); for(int i=0; ipropagation_count; i++){ payload->set_http_headers(req_payload->propagation_headers[i].name, req_payload->propagation_headers[i].value); diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 8aee79189..79d42fc91 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -24,6 +24,7 @@ ngx_http_opentelemetry_worker_conf_t *worker_conf; static contextNode contexts[5]; static unsigned int c_count = 0; static unsigned int isGlobalContextSet = 0; +static ngx_str_t hostname; /* List of modules being monitored @@ -613,6 +614,10 @@ static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) // ngx_http_next_body_filter = ngx_http_top_body_filter; // ngx_http_top_body_filter = ngx_http_opentelemetry_body_filter; + hostname = cf->cycle->hostname; + /* hostname is extracted from the nginx cycle. The attribute hostname is needed + for OTEL spec and the only place it is available is cf->cycle + */ ngx_writeError(cf->cycle->log, __func__, "Opentelemetry Modlue init completed !"); return NGX_OK; @@ -1541,9 +1546,37 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* temp_uri[(r->uri).len]='\0'; req_payload->uri = temp_uri; + ngx_http_core_srv_conf_t* cscf = (ngx_http_core_srv_conf_t*)ngx_http_get_module_srv_conf(r, ngx_http_core_module); + req_payload->server_name = (const char*)(cscf->server_name).data; + + #if (NGX_HTTP_SSL) + + if(r->connection->ssl) + { + req_payload->scheme = "https"; + } + else + { + req_payload->scheme = "http"; + } + + #else + + req_payload->scheme = "http"; + + #endif + req_payload->protocol = (const char*)(r->http_protocol).data; req_payload->request_method = (const char*)(r->method_name).data; + // flavor has to be scraped from protocol in future + req_payload->flavor = (const char*)(r->http_protocol).data; + + char *temp_hostname = ngx_pcalloc(r->pool, (strlen(hostname.data))+1); + strcpy(temp_hostname,(const char*)hostname.data); + temp_hostname[hostname.len]='\0'; + req_payload->hostname = temp_hostname; + req_payload->http_post_param = ngx_pcalloc(r->pool, sizeof(u_char*)); req_payload->http_get_param = ngx_pcalloc(r->pool, sizeof(u_char*)); @@ -1563,6 +1596,8 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* } } + req_payload->client_ip = (const char*)(r->connection->addr_text).data; + ngx_http_opentelemetry_loc_conf_t *conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); part = &r->headers_in.headers.part; From 7432ef2e8eaee29e9b1551bf144541c0c9df26c7 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Thu, 17 Nov 2022 10:39:27 +0530 Subject: [PATCH 33/77] Adding http.status_code as span attributes for both Apache/Nginx (#235) * Setting proper value of http.status_code as span attributes * Corrected type * Incorporated Review Comments --- .../include/core/api/Payload.h | 6 ++---- .../include/core/api/opentelemetry_ngx_api.h | 2 ++ .../include/core/sdkwrapper/SdkConstants.h | 2 ++ .../src/apache/ApacheHooks.cpp | 12 +++++++----- .../src/core/api/RequestProcessingEngine.cpp | 3 ++- .../src/core/api/opentelemetry_ngx_api.cpp | 1 + .../src/nginx/ngx_http_opentelemetry_module.c | 8 ++++---- .../src/nginx/ngx_http_opentelemetry_module.h | 1 + .../test/unit/RequestProcessingEngine_test.cpp | 16 +++++++++++++--- 9 files changed, 34 insertions(+), 17 deletions(-) diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index 615669ba1..fc06a4736 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -18,11 +18,11 @@ #define __PAYLOAD_H #include +#include "sdkwrapper/SdkConstants.h" namespace appd { namespace core { - //----------------------------------------------------------------------------------------- // RequestPayload // Used for following purposes: @@ -47,7 +47,6 @@ class RequestPayload std::string flavor; std::string client_ip; long port = 80; - long status_code = 200; public: void set_http_headers(const std::string& key, const std::string& value) @@ -70,7 +69,6 @@ class RequestPayload 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; } @@ -86,7 +84,6 @@ class RequestPayload 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; } std::unordered_map& get_request_headers() { return request_headers; } @@ -95,6 +92,7 @@ class RequestPayload struct ResponsePayload { std::unordered_map response_headers; + unsigned int status_code{sdkwrapper::kStatusCodeInit}; }; struct InteractionPayload diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index afcbfa91c..00010b837 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -55,6 +55,8 @@ typedef struct { typedef struct { http_headers* response_headers; int response_headers_count; + + unsigned int status_code; }response_payload; typedef struct{ diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h index d2835280c..3f236e8cf 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h @@ -46,6 +46,8 @@ constexpr int HTTP_ERROR_5XX = 500; constexpr int HTTP_PROTO_1000 = 1000; constexpr int HTTP_PROTO_1001 = 1001; +constexpr unsigned int kStatusCodeInit = 0; + } // sdkwrapper } // core } // appd diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index c07c736d2..da69c69bf 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -522,9 +522,6 @@ 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); @@ -675,16 +672,21 @@ int ApacheHooks::appd_hook_log_transaction_end(request_rec* r) apr_table_unset(r->notes, APPD_REQ_HANDLE_KEY); APPD_SDK_STATUS_CODE res; + std::unique_ptr responsePayload + (new appd::core::ResponsePayload); + responsePayload->status_code = r->status; if (appd_requestHasErrors(r)) { std::ostringstream oss; oss << r->status; - res = wsAgent.endRequest(reqHandle, oss.str().c_str()); + res = wsAgent.endRequest + (reqHandle, oss.str().c_str(), responsePayload.get()); } else { - res = wsAgent.endRequest(reqHandle, NULL); + res = wsAgent.endRequest( + reqHandle, NULL, responsePayload.get()); } if (APPD_ISSUCCESS(res)) diff --git a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp index 5ea643d8a..6b1169147 100644 --- a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp @@ -74,7 +74,6 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startRequest( 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& request_headers = payload->get_request_headers(); @@ -157,6 +156,8 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::endRequest( std::string(itr->first); rootSpan->AddAttribute(key, itr->second); } + + rootSpan->AddAttribute(kAttrHTTPStatusCode, payload->status_code); } LOG4CXX_TRACE(mLogger, "Ending root span with id: " << rootSpan.get()); diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index 388060aa0..ebafeacbf 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -125,6 +125,7 @@ APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* = payload->response_headers[i].value; } } + responsePayload->status_code = payload->status_code; } res = wsAgent.endRequest(req_handle_key, errMsg, responsePayload.get()); diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 79d42fc91..3452adefd 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -1101,18 +1101,18 @@ static void stopMonitoringRequest(ngx_http_request_t* r, } APPD_SDK_STATUS_CODE res; - unsigned int errCode=0; char* msg = NULL; if (otel_requestHasErrors(r)) { - errCode=(unsigned int)otel_getErrorCode(r); - msg = (char*)malloc(6); - sprintf(msg, "%d", errCode); + res_payload->status_code = (unsigned int)otel_getErrorCode(r); + msg = (char*)malloc(STATUS_CODE_BYTE_COUNT * sizeof(char)); + sprintf(msg, "%d", res_payload->status_code); res = endRequest(otel_req_handle_key, msg, res_payload); } else { + res_payload->status_code = r->headers_out.status; res = endRequest(otel_req_handle_key, msg, res_payload); } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h index 9149649c3..a3b749299 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -22,6 +22,7 @@ #include "../../include/core/api/opentelemetry_ngx_api.h" #define LOWEST_HTTP_ERROR_CODE 400 +#define STATUS_CODE_BYTE_COUNT 6 /* The following enum has one-to-one mapping with otel_monitored_modules[] defined in .c file. diff --git a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp index 85dd5f783..4fb0e48eb 100644 --- a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp @@ -113,6 +113,11 @@ MATCHER_P(HasLongIntValue, value, "") { return opentelemetry::nostd::get(arg) == value; } +MATCHER_P(HasUnsignedIntValue, value, "") { + + return opentelemetry::nostd::get(arg) == value; +} + MATCHER_P(HasBoolValue, value, "") { return opentelemetry::nostd::get(arg) == value; } @@ -131,7 +136,6 @@ TEST(TestRequestProcessingEngine, StartRequest) 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"); @@ -146,7 +150,6 @@ TEST(TestRequestProcessingEngine, StartRequest) 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"; @@ -229,12 +232,19 @@ TEST(TestRequestProcessingEngine, EndRequest) EXPECT_CALL(*getMockSpan(interactionSpan1), End()). Times(1); + unsigned int status_code = 403; EXPECT_CALL(*getMockSpan(rootSpan), SetStatus(appd::core::sdkwrapper::StatusCode::Error, "HTTP ERROR CODE:403")).Times(1); + EXPECT_CALL(*getMockSpan(rootSpan), + AddAttribute(kAttrHTTPStatusCode, + HasUnsignedIntValue(status_code))).Times(1); EXPECT_CALL(*getMockSpan(rootSpan), End()). Times(1); - auto res = engine.endRequest(rContext, "403"); + std::unique_ptr responsePayload + (new appd::core::ResponsePayload); + responsePayload->status_code = status_code; + auto res = engine.endRequest(rContext, "403", responsePayload.get()); EXPECT_EQ(res, APPD_SUCCESS); } From 19f74b9ebb2af9e6e415ebf1e9264e75546fc4d6 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Thu, 17 Nov 2022 13:00:27 +0530 Subject: [PATCH 34/77] Updated readme with instructions to capture request and response headers in Span Attributes. (#236) * Added Readme for Nginx Headers * Added Readme for Nginx Headers * Added Readme for Nginx Headers * Added Readme for Nginx Headers --- instrumentation/otel-webserver-module/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index cf300c844..9b59ccfd8 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -172,7 +172,8 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get |*NginxModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| |*NginxModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation| |*NginxModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| - +|*NginxModuleRequestHeaders* | | OPTIONAL: Specify the request headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleRequestHeaders Accept-Charset,Accept-Encoding,User-Agent;```| +|*NginxModuleResponseHeaders* | | OPTIONAL: Specify the response headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleResponseHeaders Content-Length,Content-Type;```| ### Build and Installation #### Prerequisites From dba13fef65749f0fc703076a05896c7f28c44976 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 21 Nov 2022 17:41:46 -0800 Subject: [PATCH 35/77] ETW Metrics Exporter for Windows (#228) --- exporters/geneva/CMakeLists.txt | 19 +++-- .../portfile.cmake | 24 ++++++ .../vcpkg.json | 24 ++++++ exporters/geneva/example/example_metrics.cc | 17 ++-- exporters/geneva/example/foo_library.cc | 3 - exporters/geneva/example/foo_library.h | 2 - .../geneva/metrics/connection_string_parser.h | 2 +- .../exporters/geneva/metrics/data_transport.h | 13 ++- .../geneva/metrics/etw_data_transport.h | 39 +++++++++ .../exporters/geneva/metrics/exporter.h | 6 -- .../unix_domain_socket_data_transport.h | 3 +- exporters/geneva/src/etw_data_transport.cc | 85 +++++++++++++++++++ exporters/geneva/src/exporter.cc | 42 +++++---- .../src/unix_domain_socket_data_transport.cc | 3 +- 14 files changed, 237 insertions(+), 45 deletions(-) create mode 100644 exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/portfile.cmake create mode 100644 exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/vcpkg.json create mode 100644 exporters/geneva/include/opentelemetry/exporters/geneva/metrics/etw_data_transport.h create mode 100644 exporters/geneva/src/etw_data_transport.cc diff --git a/exporters/geneva/CMakeLists.txt b/exporters/geneva/CMakeLists.txt index db06e03af..57f3eba7c 100644 --- a/exporters/geneva/CMakeLists.txt +++ b/exporters/geneva/CMakeLists.txt @@ -4,24 +4,33 @@ cmake_minimum_required(VERSION 3.12) # (using add_subdirectory) or if it is the main project # set(MAIN_PROJECT OFF) - set(MAIN_PROJECT OFF) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(opentelemetry-geneva-metrics) set(MAIN_PROJECT ON) endif() +if(NOT WIN32) + find_package(CURL REQUIRED) +endif() add_definitions(-DHAVE_CONSOLE_LOG) if(MAIN_PROJECT) find_package(opentelemetry-cpp REQUIRED) endif() -find_package(CURL REQUIRED) - include_directories(include) + # create geneva metrics exporter -add_library(opentelemetry_exporter_geneva_metrics - src/exporter.cc src/unix_domain_socket_data_transport.cc) +if(WIN32) + add_library( + opentelemetry_exporter_geneva_metrics + src/exporter.cc src/etw_data_transport.cc + src/unix_domain_socket_data_transport.cc) +else() + add_library(opentelemetry_exporter_geneva_metrics + src/exporter.cc src/unix_domain_socket_data_transport.cc) +endif() + target_include_directories(opentelemetry_exporter_geneva_metrics PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) target_link_libraries(opentelemetry_exporter_geneva_metrics diff --git a/exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/portfile.cmake b/exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/portfile.cmake new file mode 100644 index 000000000..c5c215846 --- /dev/null +++ b/exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/portfile.cmake @@ -0,0 +1,24 @@ +include(vcpkg_common_functions) + +if(VCPKG_TARGET_IS_WINDOWS) + vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +endif() + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO lalitb/opentelemetry-cpp-contrib + HEAD_REF geneva-windows +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}/exporters/geneva/" + OPTIONS + -DBUILD_TESTING=OFF + -DBUILD_EXAMPLE=OFF +) + +vcpkg_cmake_install() +vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/${PORT}) +vcpkg_copy_pdbs() +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share") diff --git a/exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/vcpkg.json b/exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/vcpkg.json new file mode 100644 index 000000000..6c80ffa8e --- /dev/null +++ b/exporters/geneva/build_tools/ports/opentelemetry-etw-metrics-exporter/vcpkg.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json", + "name": "opentelemetry-etw-metrics-exporter", + "version-semver": "0.0.1", + "description": [ + "OpenTelemetry ETW Exporter uses OpenTelemetry API/SDK to export the metrics data to ETW." + ], + "homepage": "https://github.com/open-telemetry/opentelemetry-cpp-contrib", + "license": "Apache-2.0", + "dependencies": [ + { + "name": "opentelemetry-cpp", + "host": true + }, + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] + } \ No newline at end of file diff --git a/exporters/geneva/example/example_metrics.cc b/exporters/geneva/example/example_metrics.cc index 350d8d36f..bf674bd64 100644 --- a/exporters/geneva/example/example_metrics.cc +++ b/exporters/geneva/example/example_metrics.cc @@ -1,7 +1,6 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifndef ENABLE_METRICS_PREVIEW #include "opentelemetry/exporters/geneva/metrics/exporter.h" #include "opentelemetry/metrics/provider.h" #include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" @@ -26,9 +25,13 @@ const std::string kUnixDomainPath = "/tmp/ifx_unix_socket"; const std::string kNamespaceName = "test_ns"; void initMetrics(const std::string &name, const std::string &account_name) { - std::string conn_string = "Endpoint=unix://" + kUnixDomainPath + - ";Account=" + account_name + - ";Namespace=" + kNamespaceName; + +#ifndef _WIN32 + conn_string = "Endpoint=unix://" + kUnixDomainPath + ";" + conn_string; +#else + std::string conn_string = + "Account=" + account_name + ";Namespace=" + kNamespaceName; +#endif geneva_exporter::ExporterOptions options{conn_string}; std::unique_ptr exporter{ new geneva_exporter::Exporter(options)}; @@ -84,8 +87,7 @@ void initMetrics(const std::string &name, const std::string &account_name) { std::shared_ptr aggregation_config{ new opentelemetry::sdk::metrics::HistogramAggregationConfig()}; - static_cast< - opentelemetry::sdk::metrics::HistogramAggregationConfig*>( + static_cast( aggregation_config.get()) ->boundaries_ = std::list{0.0, 50.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 10000.0}; @@ -128,6 +130,3 @@ int main(int argc, char **argv) { histogram_example.join(); } } -#else -int main() {} -#endif \ No newline at end of file diff --git a/exporters/geneva/example/foo_library.cc b/exporters/geneva/example/foo_library.cc index 019bfe39f..2ece3d87d 100644 --- a/exporters/geneva/example/foo_library.cc +++ b/exporters/geneva/example/foo_library.cc @@ -1,7 +1,6 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifndef ENABLE_METRICS_PREVIEW #include "foo_library.h" #include "opentelemetry/context/context.h" #include "opentelemetry/metrics/provider.h" @@ -92,5 +91,3 @@ void FooLibrary::histogram_example(const std::string &name) { std::this_thread::sleep_for(std::chrono::milliseconds(250)); } } - -#endif \ No newline at end of file diff --git a/exporters/geneva/example/foo_library.h b/exporters/geneva/example/foo_library.h index cbb430bec..bc625f13c 100644 --- a/exporters/geneva/example/foo_library.h +++ b/exporters/geneva/example/foo_library.h @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once -#ifndef ENABLE_METRICS_PREVIEW #include class FooLibrary { @@ -11,4 +10,3 @@ class FooLibrary { static void histogram_example(const std::string &name); static void observable_counter_example(const std::string &name); }; -#endif \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h index 5f53ff7c8..39fff58ae 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h @@ -73,7 +73,7 @@ class ConnectionStringParser { } } } -#if defined(_MSC_VER) +#ifdef _WIN32 if (account_.size() && namespace_.size() && !is_endpoint_found) { transport_protocol_ = TransportProtocol::kETW; } diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h index 66bfe5717..7ff8be170 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h @@ -11,13 +11,22 @@ OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { namespace geneva { namespace metrics { -using ByteVector = std::vector; + +// These enums are defined in +// file: test/decoder/ifx_metrics_bin.ksy (enum metric_event_type) +enum class MetricsEventType : uint16_t { + ULongMetric = 50, + DoubleMetric = 55, + ExternallyAggregatedULongDistributionMetric = 56 +}; class DataTransport { public: virtual bool Connect() noexcept = 0; - virtual bool Send(const char *data, uint16_t length) noexcept = 0; + virtual bool Send(MetricsEventType event_type, const char *data, + uint16_t length) noexcept = 0; virtual bool Disconnect() noexcept = 0; + virtual ~DataTransport() = 0; }; } // namespace metrics } // namespace geneva diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/etw_data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/etw_data_transport.h new file mode 100644 index 000000000..41c54cd48 --- /dev/null +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/etw_data_transport.h @@ -0,0 +1,39 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/exporters/geneva/metrics/connection_string_parser.h" +#include "opentelemetry/exporters/geneva/metrics/data_transport.h" +#include "opentelemetry/version.h" + +#include +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { +static const REGHANDLE INVALID_HANDLE = _UI64_MAX; +static const GUID kMDMProviderGUID = { + 0xedc24920, 0xe004, 0x40f6, 0xa8, 0xe1, 0x0e, 0x6e, 0x48, 0xf3, 0x9d, 0x84}; + +class ETWDataTransport : public DataTransport { +public: + ETWDataTransport(const size_t offset_to_skip_); + bool Connect() noexcept override; + bool Send(MetricsEventType event_type, const char *data, + uint16_t length) noexcept override; + bool Disconnect() noexcept override; + ~ETWDataTransport(); + +private: + REGHANDLE provider_handle_; + bool connected_{false}; + const size_t offset_to_skip_; +}; +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h index efeeb3b74..2625d482d 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -33,12 +33,6 @@ constexpr uint64_t kSecondsToUnixTime = // 1601-01-01T00:00:00Z and UNIX/Linux epoch // (1970-01-01T00:00:00Z) -enum class MetricsEventType : uint16_t { - ULongMetric = 50, - DoubleMetric = 55, - ExternallyAggregatedULongDistributionMetric = 56 -}; - /** * The Geneva metrics exporter exports metrics data to Geneva */ diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h index b36faf56d..798988376 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h @@ -18,7 +18,8 @@ class UnixDomainSocketDataTransport : public DataTransport { public: UnixDomainSocketDataTransport(const std::string &connection_string); bool Connect() noexcept override; - bool Send(const char *data, uint16_t length) noexcept override; + bool Send(MetricsEventType event_type, const char *data, + uint16_t length) noexcept override; bool Disconnect() noexcept override; private: diff --git a/exporters/geneva/src/etw_data_transport.cc b/exporters/geneva/src/etw_data_transport.cc new file mode 100644 index 000000000..400f503ae --- /dev/null +++ b/exporters/geneva/src/etw_data_transport.cc @@ -0,0 +1,85 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/geneva/metrics/etw_data_transport.h" +#include "opentelemetry/exporters/geneva/metrics/macros.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter { +namespace geneva { +namespace metrics { +#define GUID_FORMAT \ + "%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX" +#define GUID_ARG(guid) \ + (guid).Data1, (guid).Data2, (guid).Data3, (guid).Data4[0], (guid).Data4[1], \ + (guid).Data4[2], (guid).Data4[3], (guid).Data4[4], (guid).Data4[5], \ + (guid).Data4[6], (guid).Data4[7] + +ETWDataTransport::ETWDataTransport(const size_t offset_to_skip) + : offset_to_skip_{offset_to_skip} { + auto status = + ::EventRegister(&kMDMProviderGUID, NULL, NULL, &provider_handle_); + if (status != ERROR_SUCCESS) { + LOG_ERROR("ETWDataTransport:: Failed to initialize the ETW provider. " + "Metrics will not be published, Provider ID: {" GUID_FORMAT "}", + GUID_ARG(kMDMProviderGUID)); + provider_handle_ = INVALID_HANDLE; + } +} + +bool ETWDataTransport::Connect() noexcept { + // connection is already established in constructor. Check if it is still + // valid. + if (provider_handle_ == INVALID_HANDLE) { + LOG_ERROR("ETWDataTransport:: Failed to initialize the ETW provider. " + "Metrics will not be published"); + return false; + } + return true; +} + +bool ETWDataTransport::Send(MetricsEventType event_type, const char *data, + uint16_t length) noexcept { + if (provider_handle_ == INVALID_HANDLE) { + LOG_ERROR("ETWDataTransport:: ETW Provider Handle is not valid. Metrics is " + "dropped"); + return false; + } + const unsigned int descriptorSize = 1; + EVENT_DATA_DESCRIPTOR dataDescriptor[descriptorSize]; + ::ZeroMemory(&dataDescriptor, sizeof(dataDescriptor)); + // skip the event_id and the payload length (as expected by the ETW listener) + ::EventDataDescCreate(&dataDescriptor[0], data + offset_to_skip_, + length - offset_to_skip_); + + EVENT_DESCRIPTOR evtDescriptor; + ::ZeroMemory(&evtDescriptor, sizeof(EVENT_DESCRIPTOR)); + evtDescriptor.Version = 1; + evtDescriptor.Version = 0; + evtDescriptor.Id = static_cast(event_type); + auto result = ::EventWrite(provider_handle_, &evtDescriptor, descriptorSize, + dataDescriptor); + if (result != ERROR_SUCCESS) { + LOG_ERROR("ETWDataTransport:: Failed to publish metric to ETW. Error: %d", + result); + return false; + } + return true; +} + +bool ETWDataTransport::Disconnect() noexcept { + // provider is deregistered in destructor. + return true; +} + +ETWDataTransport::~ETWDataTransport() { + if (provider_handle_ != INVALID_HANDLE) { + ::EventUnregister(provider_handle_); + provider_handle_ = INVALID_HANDLE; + } +} + +} // namespace metrics +} // namespace geneva +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc index e67a63098..750ea3375 100644 --- a/exporters/geneva/src/exporter.cc +++ b/exporters/geneva/src/exporter.cc @@ -4,6 +4,9 @@ #include "opentelemetry/exporters/geneva/metrics/exporter.h" #include "opentelemetry/exporters/geneva/metrics/macros.h" #include "opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h" +#ifdef _WIN32 +#include "opentelemetry/exporters/geneva/metrics/etw_data_transport.h" +#endif #include "opentelemetry/metrics/meter_provider.h" #include "opentelemetry/sdk_config.h" @@ -25,6 +28,13 @@ Exporter::Exporter(const ExporterOptions &options) std::unique_ptr(new UnixDomainSocketDataTransport( connection_string_parser_.url_->path_)); } +#ifdef _WIN32 + else if (connection_string_parser_.transport_protocol_ == + TransportProtocol::kETW) { + data_transport_ = std::unique_ptr( + new ETWDataTransport(kBinaryHeaderSize)); + } +#endif } // Connect transport at initialization auto status = data_transport_->Connect(); @@ -52,7 +62,6 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( const std::lock_guard locked(lock_); shutdown = is_shutdown_; } - if (shutdown) { OTEL_INTERNAL_LOG_ERROR("[Genava Exporter] Exporting " << data.scope_metric_data_.size() @@ -81,7 +90,7 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( sdk::metrics::AggregationType::kSum, event_type, value.value_, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); - data_transport_->Send(buffer_non_histogram_, + data_transport_->Send(event_type, buffer_non_histogram_, body_length + kBinaryHeaderSize); } else if (nostd::holds_alternative( @@ -97,7 +106,7 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( value.value_, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); - data_transport_->Send(buffer_non_histogram_, + data_transport_->Send(event_type, buffer_non_histogram_, body_length + kBinaryHeaderSize); } else if (nostd::holds_alternative( point_data_with_attributes.point_data)) { @@ -121,7 +130,7 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( .counts_, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); - data_transport_->Send(buffer_histogram_, + data_transport_->Send(event_type, buffer_histogram_, body_length + kBinaryHeaderSize); } } @@ -173,12 +182,14 @@ size_t Exporter::InitiaizeBufferForHistogramData() { size_t Exporter::SerializeNonHistogramMetrics( sdk::metrics::AggregationType agg_type, MetricsEventType event_type, const sdk::metrics::ValueType &value, common::SystemTimestamp ts, - const std::string& metric_name, const sdk::metrics::PointAttributes &attributes) { + const std::string &metric_name, + const sdk::metrics::PointAttributes &attributes) { auto bufferIndex = buffer_index_non_histogram_; SerializeString(buffer_non_histogram_, bufferIndex, metric_name); for (const auto &kv : attributes) { if (kv.first.size() > kMaxDimensionNameSize) { - LOG_WARN("Dimension name limit overflow: %s Limit %d", kv.first.c_str(), kMaxDimensionNameSize); + LOG_WARN("Dimension name limit overflow: %s Limit %d", kv.first.c_str(), + kMaxDimensionNameSize); continue; } SerializeString(buffer_non_histogram_, bufferIndex, kv.first); @@ -205,8 +216,8 @@ size_t Exporter::SerializeNonHistogramMetrics( static_cast(body_length)); // count of dimensions. - SerializeInt(buffer_non_histogram_, bufferIndex, - static_cast(attributes.size())); + SerializeInt(buffer_non_histogram_, bufferIndex, + static_cast(attributes.size())); // reserverd word (2 bytes) SerializeInt(buffer_non_histogram_, bufferIndex, 0); @@ -223,7 +234,7 @@ size_t Exporter::SerializeNonHistogramMetrics( SerializeInt(buffer_non_histogram_, bufferIndex, windows_ticks); if (event_type == MetricsEventType::ULongMetric) { SerializeInt(buffer_non_histogram_, bufferIndex, - static_cast(nostd::get(value))); + static_cast(nostd::get(value))); } else { SerializeInt( buffer_non_histogram_, bufferIndex, @@ -247,7 +258,8 @@ size_t Exporter::SerializeHistogramMetrics( // dimentions - name for (const auto &kv : attributes) { if (kv.first.size() > kMaxDimensionNameSize) { - LOG_WARN("Dimension name limit overflow: %s Limit: %d", kv.first.c_str(), kMaxDimensionNameSize); + LOG_WARN("Dimension name limit overflow: %s Limit: %d", kv.first.c_str(), + kMaxDimensionNameSize); continue; } SerializeString(buffer_histogram_, bufferIndex, kv.first); @@ -309,8 +321,8 @@ size_t Exporter::SerializeHistogramMetrics( static_cast(body_length)); // count of dimensions. - SerializeInt(buffer_histogram_, bufferIndex, - static_cast(attributes.size())); + SerializeInt(buffer_histogram_, bufferIndex, + static_cast(attributes.size())); // reserverd word (2 bytes) SerializeInt(buffer_histogram_, bufferIndex, 0); @@ -331,13 +343,13 @@ size_t Exporter::SerializeHistogramMetrics( MetricsEventType::ExternallyAggregatedULongDistributionMetric) { // sum SerializeInt(buffer_histogram_, bufferIndex, - static_cast(nostd::get(sum))); + static_cast(nostd::get(sum))); // min SerializeInt(buffer_histogram_, bufferIndex, - static_cast(nostd::get(min))); + static_cast(nostd::get(min))); // max SerializeInt(buffer_histogram_, bufferIndex, - static_cast(nostd::get(max))); + static_cast(nostd::get(max))); } else { // sum SerializeInt( diff --git a/exporters/geneva/src/unix_domain_socket_data_transport.cc b/exporters/geneva/src/unix_domain_socket_data_transport.cc index 120f85e61..364ff0afb 100644 --- a/exporters/geneva/src/unix_domain_socket_data_transport.cc +++ b/exporters/geneva/src/unix_domain_socket_data_transport.cc @@ -26,7 +26,8 @@ bool UnixDomainSocketDataTransport::Connect() noexcept { return true; } -bool UnixDomainSocketDataTransport::Send(char const *data, +bool UnixDomainSocketDataTransport::Send(MetricsEventType event_type, + char const *data, uint16_t length) noexcept { int error_code = 0; if (connected_) { From 26324a9e63d83ea9e53db1709bace9cbdeb51092 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 1 Dec 2022 19:09:24 -0800 Subject: [PATCH 36/77] Add Support for UpDownCounter, ObservableUpDownCounter, ObservableGauge, Histogram (#241) --- exporters/geneva/example/example_metrics.cc | 6 +- .../exporters/geneva/metrics/data_transport.h | 17 +++- .../exporters/geneva/metrics/exporter.h | 2 + .../unix_domain_socket_data_transport.h | 1 + exporters/geneva/src/exporter.cc | 81 +++++++++------ .../geneva/test/common/generate_metrics.h | 99 ++++++++++++++++++- .../geneva/test/decoder/ifx_metrics_bin.cpp | 5 + .../geneva/test/metrics_exporter_test.cc | 58 +++++++++-- 8 files changed, 218 insertions(+), 51 deletions(-) diff --git a/exporters/geneva/example/example_metrics.cc b/exporters/geneva/example/example_metrics.cc index bf674bd64..d88f84621 100644 --- a/exporters/geneva/example/example_metrics.cc +++ b/exporters/geneva/example/example_metrics.cc @@ -26,12 +26,12 @@ const std::string kNamespaceName = "test_ns"; void initMetrics(const std::string &name, const std::string &account_name) { -#ifndef _WIN32 - conn_string = "Endpoint=unix://" + kUnixDomainPath + ";" + conn_string; -#else std::string conn_string = "Account=" + account_name + ";Namespace=" + kNamespaceName; +#ifndef _WIN32 + conn_string = "Endpoint=unix://" + kUnixDomainPath + ";" + conn_string; #endif + geneva_exporter::ExporterOptions options{conn_string}; std::unique_ptr exporter{ new geneva_exporter::Exporter(options)}; diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h index 7ff8be170..aedc53b02 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/data_transport.h @@ -12,12 +12,19 @@ namespace exporter { namespace geneva { namespace metrics { -// These enums are defined in +// These enums are defined in // file: test/decoder/ifx_metrics_bin.ksy (enum metric_event_type) enum class MetricsEventType : uint16_t { - ULongMetric = 50, + Uint64Metric = 50, + DoubleScaledToLongMetric = 51, + BatchMetric = 52, + ExternallyAggregatedUlongMetric = 53, + ExternallyAggregatedDoubleMetric = 54, DoubleMetric = 55, - ExternallyAggregatedULongDistributionMetric = 56 + ExternallyAggregatedUlongDistributionMetric = 56, + ExternallyAggregatedDoubleDistributionMetric = 57, + ExternallyAggregatedDoubleScaledToLongDistributionMetric = 58, + Undefined = 100 }; class DataTransport { @@ -26,9 +33,9 @@ class DataTransport { virtual bool Send(MetricsEventType event_type, const char *data, uint16_t length) noexcept = 0; virtual bool Disconnect() noexcept = 0; - virtual ~DataTransport() = 0; + virtual ~DataTransport() = default; }; } // namespace metrics } // namespace geneva } // namespace exporter -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h index 2625d482d..e780c5acd 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -33,6 +33,8 @@ constexpr uint64_t kSecondsToUnixTime = // 1601-01-01T00:00:00Z and UNIX/Linux epoch // (1970-01-01T00:00:00Z) +using ValueType = nostd::variant; + /** * The Geneva metrics exporter exports metrics data to Geneva */ diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h index 798988376..f9ea26dc1 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/unix_domain_socket_data_transport.h @@ -21,6 +21,7 @@ class UnixDomainSocketDataTransport : public DataTransport { bool Send(MetricsEventType event_type, const char *data, uint16_t length) noexcept override; bool Disconnect() noexcept override; + ~UnixDomainSocketDataTransport() = default; private: // Socket connection is re-established for every batch of events diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc index 750ea3375..32a66c8d3 100644 --- a/exporters/geneva/src/exporter.cc +++ b/exporters/geneva/src/exporter.cc @@ -81,13 +81,29 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( point_data_with_attributes.point_data)) { auto value = nostd::get( point_data_with_attributes.point_data); - MetricsEventType event_type = MetricsEventType::ULongMetric; + ValueType new_value = value.value_; + + MetricsEventType event_type; + if (nostd::holds_alternative(value.value_)) { event_type = MetricsEventType::DoubleMetric; + } else { + if (!value.is_monotonic_) { + // NOTE - Potential for minor precision loss implicitly going from + // int64_t to double - + // - A 64-bit integer can hold more significant decimal digits + // than a standard + // IEEE (64-bit) double precision floating-point + // representation + new_value = static_cast(nostd::get(new_value)); + event_type = MetricsEventType::DoubleMetric; + + } else { + event_type = MetricsEventType::Uint64Metric; + } } - body_length = SerializeNonHistogramMetrics( - sdk::metrics::AggregationType::kSum, event_type, value.value_, + sdk::metrics::AggregationType::kSum, event_type, new_value, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); data_transport_->Send(event_type, buffer_non_histogram_, @@ -95,16 +111,21 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( } else if (nostd::holds_alternative( point_data_with_attributes.point_data)) { - auto value = nostd::get( + auto value = nostd::get( point_data_with_attributes.point_data); - MetricsEventType event_type = MetricsEventType::ULongMetric; - if (nostd::holds_alternative(value.value_)) { - event_type = MetricsEventType::DoubleMetric; + ValueType new_value = value.value_; + if (nostd::holds_alternative(value.value_)) { + // NOTE - Potential for minor precision loss implicitly going from + // int64_t to double - + // - A 64-bit integer can hold more significant decimal digits + // than a standard + // IEEE (64-bit) double precision floating-point representation + new_value = static_cast(nostd::get(new_value)); } + MetricsEventType event_type = MetricsEventType::DoubleMetric; body_length = SerializeNonHistogramMetrics( - sdk::metrics::AggregationType::kLastValue, event_type, - value.value_, metric_data.end_ts, - metric_data.instrument_descriptor.name_, + sdk::metrics::AggregationType::kLastValue, event_type, new_value, + metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); data_transport_->Send(event_type, buffer_non_histogram_, body_length + kBinaryHeaderSize); @@ -112,16 +133,21 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( point_data_with_attributes.point_data)) { auto value = nostd::get( point_data_with_attributes.point_data); - MetricsEventType event_type = - MetricsEventType::ExternallyAggregatedULongDistributionMetric; + ValueType new_sum = value.sum_; + ValueType new_min = value.min_; + ValueType new_max = value.max_; + if (nostd::holds_alternative(value.sum_)) { - LOG_ERROR("Geneva Exporter::Export- Double value is not supported " - "for Histogram"); - continue; + // TODO: Double is not supported by Geneva, convert it to int64_t + new_sum = static_cast(nostd::get(new_sum)); + new_min = static_cast(nostd::get(new_min)); + new_max = static_cast(nostd::get(new_max)); } + MetricsEventType event_type = + MetricsEventType::ExternallyAggregatedUlongDistributionMetric; body_length = SerializeHistogramMetrics( sdk::metrics::AggregationType::kHistogram, event_type, - value.count_, value.sum_, value.min_, value.max_, + value.count_, new_sum, new_min, new_max, nostd::get( point_data_with_attributes.point_data) .boundaries_, @@ -232,13 +258,15 @@ size_t Exporter::SerializeNonHistogramMetrics( .count()); SerializeInt(buffer_non_histogram_, bufferIndex, windows_ticks); - if (event_type == MetricsEventType::ULongMetric) { + if (event_type == MetricsEventType::Uint64Metric) { SerializeInt(buffer_non_histogram_, bufferIndex, static_cast(nostd::get(value))); - } else { + } else if (event_type == MetricsEventType::DoubleMetric) { SerializeInt( buffer_non_histogram_, bufferIndex, *(reinterpret_cast(&(nostd::get(value))))); + } else { + // Won't reach here. } return body_length; } @@ -290,7 +318,7 @@ size_t Exporter::SerializeHistogramMetrics( size_t index = 0; uint16_t bucket_count = 0; if (event_type == - MetricsEventType::ExternallyAggregatedULongDistributionMetric) { + MetricsEventType::ExternallyAggregatedUlongDistributionMetric) { for (auto boundary : boundaries) { if (counts[index] > 0) { SerializeInt(buffer_histogram_, bufferIndex, @@ -340,7 +368,7 @@ size_t Exporter::SerializeHistogramMetrics( // sum, min, max if (event_type == - MetricsEventType::ExternallyAggregatedULongDistributionMetric) { + MetricsEventType::ExternallyAggregatedUlongDistributionMetric) { // sum SerializeInt(buffer_histogram_, bufferIndex, static_cast(nostd::get(sum))); @@ -351,18 +379,7 @@ size_t Exporter::SerializeHistogramMetrics( SerializeInt(buffer_histogram_, bufferIndex, static_cast(nostd::get(max))); } else { - // sum - SerializeInt( - buffer_histogram_, bufferIndex, - *(reinterpret_cast(&(nostd::get(sum))))); - // min - SerializeInt( - buffer_histogram_, bufferIndex, - *(reinterpret_cast(&(nostd::get(min))))); - // max - SerializeInt( - buffer_histogram_, bufferIndex, - *(reinterpret_cast(&(nostd::get(max))))); + // won't reach here. } return body_length; } diff --git a/exporters/geneva/test/common/generate_metrics.h b/exporters/geneva/test/common/generate_metrics.h index 1f1214b4c..ac5e1604f 100644 --- a/exporters/geneva/test/common/generate_metrics.h +++ b/exporters/geneva/test/common/generate_metrics.h @@ -29,11 +29,12 @@ const uint16_t kCounterDoubleEventId = 55; static inline opentelemetry::sdk::metrics::ResourceMetrics GenerateSumDataDoubleMetrics() { - opentelemetry::sdk::metrics::SumPointData sum_point_data1{}; sum_point_data1.value_ = kCounterDoubleValue1; + sum_point_data1.is_monotonic_ = true; opentelemetry::sdk::metrics::SumPointData sum_point_data2{}; sum_point_data2.value_ = kCounterDoubleValue2; + sum_point_data2.is_monotonic_ = true; opentelemetry::sdk::metrics::ResourceMetrics data; auto resource = opentelemetry::sdk::resource::Resource::Create( opentelemetry::sdk::resource::ResourceAttributes{}); @@ -81,9 +82,9 @@ const uint16_t kCounterLongEventId = 50; static inline opentelemetry::sdk::metrics::ResourceMetrics GenerateSumDataLongMetrics() { - opentelemetry::sdk::metrics::SumPointData sum_point_data{}; sum_point_data.value_ = kCounterLongValue; + sum_point_data.is_monotonic_ = true; opentelemetry::sdk::metrics::ResourceMetrics data; auto resource = opentelemetry::sdk::resource::Resource::Create( opentelemetry::sdk::resource::ResourceAttributes{}); @@ -111,6 +112,100 @@ GenerateSumDataLongMetrics() { return data; } +// Counter Instrument of long type +const std::string kUpDownCounterLongInstrumentName = + "test_instrument_up_down_couter_long_name"; +const std::string kUpDownCounterLongInstrumentDesc = + "test_instrument_up_down_counter_long_desc"; +const std::string kUpDownCounterLongInstrumentUnit = + "test_instrument_up_down_conter_long_unit"; +const long kUpDownCounterLongValue = -10; +const std::string kUpDownCounterLongAttributeKey1 = "up_down_counter_long_key1"; +const std::string kUpDownCounterLongAttributeValue1 = + "up_down_counter_long_value1"; +const uint16_t kUpDownCounterLongCountDimensions = 1; + +static inline opentelemetry::sdk::metrics::ResourceMetrics +GenerateSumDataLongMetricsNonMonotonic() { + opentelemetry::sdk::metrics::SumPointData sum_point_data{}; + sum_point_data.value_ = kUpDownCounterLongValue; + sum_point_data.is_monotonic_ = false; + opentelemetry::sdk::metrics::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::MetricData metric_data{ + opentelemetry::sdk::metrics::InstrumentDescriptor{ + kUpDownCounterLongInstrumentName, kUpDownCounterLongInstrumentDesc, + kUpDownCounterLongInstrumentUnit, + opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter, + opentelemetry::sdk::metrics::InstrumentValueType::kLong}, + opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + std::vector{ + {opentelemetry::sdk::metrics::PointAttributes{ + {kUpDownCounterLongAttributeKey1, + kUpDownCounterLongAttributeValue1}}, + sum_point_data}}}; + data.scope_metric_data_ = + std::vector{ + {scope.get(), + std::vector{metric_data}}}; + return data; +} + +// Counter Instrument of double type +const std::string kUpDownCounterDoubleInstrumentName = + "test_instrument_up_down_couter_double_name"; +const std::string kUpDownCounterDoubleInstrumentDesc = + "test_instrument_up_down_counter_double_desc"; +const std::string kUpDownCounterDoubleInstrumentUnit = + "test_instrument_up_down_conter_double_unit"; +const double kUpDownCounterDoubleValue = -10.2; +const std::string kUpDownCounterDoubleAttributeKey1 = + "up_down_counter_double_key1"; +const std::string kUpDownCounterDoubleAttributeValue1 = + "up_down_counter_double_value1"; +const uint16_t kUpDownCounterDoubleCountDimensions = 1; + +static inline opentelemetry::sdk::metrics::ResourceMetrics +GenerateSumDataDoubleMetricsNonMonotonic() { + opentelemetry::sdk::metrics::SumPointData sum_point_data1{}; + sum_point_data1.value_ = kUpDownCounterDoubleValue; + sum_point_data1.is_monotonic_ = false; + opentelemetry::sdk::metrics::ResourceMetrics data; + auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + data.resource_ = &resource; + auto scope = + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::MetricData metric_data{ + opentelemetry::sdk::metrics::InstrumentDescriptor{ + kUpDownCounterDoubleInstrumentName, + kUpDownCounterDoubleInstrumentDesc, + kUpDownCounterDoubleInstrumentUnit, + opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter, + opentelemetry::sdk::metrics::InstrumentValueType::kDouble}, + opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, + std::vector{ + {opentelemetry::sdk::metrics::PointAttributes{ + {kUpDownCounterDoubleAttributeKey1, + kUpDownCounterDoubleAttributeValue1}}, + sum_point_data1}}}; + data.scope_metric_data_ = + std::vector{ + {scope.get(), + std::vector{metric_data}}}; + return data; +} + // Histogram Instrument of type long const std::string kHistogramLongInstrumentName = "test_instrument_histogram_long_name"; diff --git a/exporters/geneva/test/decoder/ifx_metrics_bin.cpp b/exporters/geneva/test/decoder/ifx_metrics_bin.cpp index 7ed70c4d2..bd6091e8f 100644 --- a/exporters/geneva/test/decoder/ifx_metrics_bin.cpp +++ b/exporters/geneva/test/decoder/ifx_metrics_bin.cpp @@ -2,7 +2,10 @@ #include "ifx_metrics_bin.h" +#include ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { + std::cout << "\nLALIT:ifx_metrics_bin::CONST.."; + m__parent = p__parent; m__root = this; m_body = 0; @@ -17,7 +20,9 @@ ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p_ } void ifx_metrics_bin_t::_read() { + std::cout << "\nLALIT:ifx_metrics_bin::READ.."; m_event_id = m__io->read_u2le(); + std::cout << "\nLALIT:ifx_metrics_bin Event ID:" << m_event_id << "\n"; m_len_body = m__io->read_u2le(); m__raw_body = m__io->read_bytes(len_body()); m__io__raw_body = new kaitai::kstream(m__raw_body); diff --git a/exporters/geneva/test/metrics_exporter_test.cc b/exporters/geneva/test/metrics_exporter_test.cc index 2381b183e..c1dd94986 100644 --- a/exporters/geneva/test/metrics_exporter_test.cc +++ b/exporters/geneva/test/metrics_exporter_test.cc @@ -36,6 +36,8 @@ struct TestServer { std::atomic count{0}; size_t count_counter_double = 0; size_t count_counter_long = 0; + size_t count_up_down_counter_long = 0; + size_t count_up_down_counter_double = 0; size_t count_histogram_long = 0; TestServer(SocketServer &server) : server(server) { @@ -45,6 +47,7 @@ struct TestServer { kaitai::kstream ks(&ss); try { ifx_metrics_bin_t event_bin = ifx_metrics_bin_t(&ks); + if (event_bin.event_id() == kCounterDoubleEventId) { EXPECT_EQ(event_bin.event_id(), kCounterDoubleEventId); auto event_body = event_bin.body(); @@ -57,6 +60,9 @@ struct TestServer { kCounterDoubleAttributeValue1); EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), kCounterDoubleAttributeKey1); + EXPECT_EQ(event_body->metric_name()->value(), + kCounterDoubleInstrumentName); + count_counter_double++; } if (static_cast( event_body->value_section()) @@ -71,12 +77,34 @@ struct TestServer { kCounterDoubleAttributeValue3); EXPECT_EQ(event_body->dimensions_names()->at(1)->value(), kCounterDoubleAttributeKey3); + EXPECT_EQ(event_body->metric_name()->value(), + kCounterDoubleInstrumentName); + count_counter_double++; + } + if (static_cast( + event_body->value_section()) + ->value() == kUpDownCounterLongValue) { + EXPECT_EQ(event_body->num_dimensions(), + kUpDownCounterLongCountDimensions); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kUpDownCounterLongAttributeValue1); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kUpDownCounterLongAttributeKey1); + count_up_down_counter_long++; + } + if (static_cast( + event_body->value_section()) + ->value() == kUpDownCounterDoubleValue) { + EXPECT_EQ(event_body->num_dimensions(), + kUpDownCounterDoubleCountDimensions); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kUpDownCounterDoubleAttributeValue1); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kUpDownCounterDoubleAttributeKey1); + count_up_down_counter_double++; } EXPECT_EQ(event_body->metric_account()->value(), kAccountName); EXPECT_EQ(event_body->metric_namespace()->value(), kNamespaceName); - EXPECT_EQ(event_body->metric_name()->value(), - kCounterDoubleInstrumentName); - count_counter_double++; } else if (event_bin.event_id() == kCounterLongEventId) { EXPECT_EQ(event_bin.event_id(), kCounterLongEventId); auto event_body = event_bin.body(); @@ -147,7 +175,6 @@ struct TestServer { } index_all_buckets++; } - count_histogram_long++; } @@ -197,20 +224,33 @@ TEST(GenevaMetricsExporter, BasicTests) { // export sum aggregation - double auto metric_data = GenerateSumDataDoubleMetrics(); exporter.Export(metric_data); - yield_for(std::chrono::milliseconds(500)); + yield_for(std::chrono::milliseconds(1000)); // export sum aggregation - long metric_data = GenerateSumDataLongMetrics(); exporter.Export(metric_data); - yield_for(std::chrono::milliseconds(500)); + yield_for(std::chrono::milliseconds(1000)); + + // export sum aggregation - long - non monotonic + metric_data = GenerateSumDataLongMetricsNonMonotonic(); + exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(1000)); + + // export sum aggregation - double - non monotonic + metric_data = GenerateSumDataDoubleMetricsNonMonotonic(); + exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(1000)); // export histogram aggregation - long metric_data = GenerateHistogramDataLongMetrics(); exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(1000)); + + EXPECT_EQ(testServer.count_counter_double, 1); + EXPECT_EQ(testServer.count_counter_long, 1); + EXPECT_EQ(testServer.count_up_down_counter_long, 1); + EXPECT_EQ(testServer.count_up_down_counter_double, 1); - yield_for(std::chrono::milliseconds(5000)); - // EXPECT_EQ(testServer.count_counter_double, 2); - // EXPECT_EQ(testServer.count_counter_long, 1); EXPECT_EQ(testServer.count_histogram_long, 1); testServer.Stop(); From 7d108cd0ed268b310cba4766a0465f38adedded3 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Mon, 5 Dec 2022 13:46:00 +0530 Subject: [PATCH 37/77] Nomenclature changes from Appd/Appdynamics to Otel/OpenTelemetry for header and cpp files (#243) * Initial chnages * More changes * More Changes * More changes * More changes * Removed unwanted file --- .../include/apache/ApacheConfig.h | 94 +- .../include/apache/ApacheHooks.h | 260 ++--- .../include/apache/ExcludedModules.h | 4 +- .../include/apache/HookContainer.h | 146 +-- .../include/core/AgentCore.h | 26 +- .../include/core/RequestContext.h | 4 +- .../include/core/api/ApiUtils.h | 28 +- .../include/core/api/AppdynamicsSdk.h | 128 +-- .../include/core/api/Interface.h | 34 +- .../include/core/api/Payload.h | 6 +- .../core/api/RequestProcessingEngine.h | 40 +- .../include/core/api/SpanNamer.h | 4 +- .../include/core/api/TenantConfig.h | 6 +- .../include/core/api/WSAgent.h | 40 +- .../include/core/api/opentelemetry_ngx_api.h | 10 +- .../include/core/sdkwrapper/IScopedSpan.h | 4 +- .../core/sdkwrapper/ISdkHelperFactory.h | 4 +- .../include/core/sdkwrapper/ISdkWrapper.h | 4 +- .../include/core/sdkwrapper/ScopedSpan.h | 4 +- .../include/core/sdkwrapper/SdkConstants.h | 4 +- .../include/core/sdkwrapper/SdkEnums.h | 4 +- .../core/sdkwrapper/SdkHelperFactory.h | 4 +- .../include/core/sdkwrapper/SdkUtils.h | 4 +- .../include/core/sdkwrapper/SdkWrapper.h | 4 +- .../include/core/sdkwrapper/ServerSpan.h | 4 +- .../src/apache/ApacheConfig.cpp | 250 ++--- .../src/apache/ApacheHooks.cpp | 972 +++++++++--------- .../src/apache/ApacheTracing.h | 4 +- .../src/apache/HookContainer.cpp | 8 +- .../src/apache/mod_apache_otel.cpp | 74 +- .../src/core/AgentCore.cpp | 4 +- .../src/core/api/ApiUtils.cpp | 168 +-- .../src/core/api/RequestProcessingEngine.cpp | 62 +- .../src/core/api/SpanNamer.cpp | 2 +- .../src/core/api/WSAgent.cpp | 88 +- .../src/core/api/opentelemetry_ngx_api.cpp | 38 +- .../src/core/sdkwrapper/ScopedSpan.cpp | 4 +- .../src/core/sdkwrapper/SdkHelperFactory.cpp | 4 +- .../src/core/sdkwrapper/SdkWrapper.cpp | 4 +- .../src/core/sdkwrapper/ServerSpan.cpp | 4 +- .../src/nginx/ngx_http_opentelemetry_log.c | 2 +- .../src/nginx/ngx_http_opentelemetry_log.h | 2 +- .../src/nginx/ngx_http_opentelemetry_module.c | 114 +- .../src/nginx/ngx_http_opentelemetry_module.h | 14 +- .../test/unit/AgentCore_test.cpp | 84 +- .../test/unit/ApiUtils_test.cpp | 224 ++-- .../unit/RequestProcessingEngine_test.cpp | 130 +-- .../test/unit/ScopedSpan_test.cpp | 2 +- .../test/unit/SdkUtils_test.cpp | 6 +- .../test/unit/SdkWrapper_test.cpp | 24 +- .../test/unit/ServerSpan_test.cpp | 18 +- .../test/unit/SpanNamer_test.cpp | 8 +- .../test/unit/WSAgent_test.cpp | 230 ++--- .../test/unit/integration_test.cpp | 20 +- .../test/unit/mocks/mock_OpenTelemetry.h | 2 +- .../unit/mocks/mock_RequestProcessingEngine.h | 38 +- .../test/unit/mocks/mock_SdkHelperFactory.h | 8 +- .../test/unit/mocks/mock_core.h | 64 +- .../test/unit/mocks/mock_dummy.h | 2 +- .../test/unit/mocks/mock_sdkwrapper.h | 28 +- 60 files changed, 1788 insertions(+), 1788 deletions(-) diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h index 81e872e79..912cd1d6c 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef APPD_APACHECONFIG_H -#define APPD_APACHECONFIG_H +#ifndef APACHECONFIG_H +#define APACHECONFIG_H #define SIZE 5 //Fixed SIZE (intermediate value chosen as 5) for masking private data if any before logging into Apache logs #include @@ -24,14 +24,14 @@ #include "httpd.h" // request_rec #include "http_config.h" // cmd_parms -class appd_cfg +class otel_cfg { public: void init(); bool validate(const request_rec *r); - int getAppdEnabled() { return appdEnabled; } - int getAppdEnabledInitialized() { return appdEnabled_initialized; } + int getOtelEnabled() { return otelEnabled; } + int getOtelEnabledInitialized() { return otelEnabled_initialized; } const char* getOtelExporterType() { return otelExporterType; } int getOtelExporterTypeInitialized() { return otelExporterType_initialized; } @@ -114,13 +114,13 @@ class appd_cfg private: // Agent to Controller Connection Configuration - int appdEnabled; // OPTIONAL: 0 for false, 1 for true (defaults to true) - int appdEnabled_initialized; + int otelEnabled; // OPTIONAL: 0 for false, 1 for true (defaults to true) + int otelEnabled_initialized; const char *otelExporterType; // OPTIONAL: Type of exporter to be configured in TracerProvider of OTel SDK embedded into Agent int otelExporterType_initialized; - const char *otelExporterEndpoint; // REQUIRED: AppDynamics endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces + const char *otelExporterEndpoint; // REQUIRED: Collector endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces int otelExporterEndpoint_initialized; int otelSslEnabled; // OPTIONAL: Decision whether connection to the Exporter endpoint is secured @@ -135,10 +135,10 @@ class appd_cfg const char *otelSamplerType; // OPTIONAL: Type of Otel Sampler int otelSamplerType_initialized; - const char *serviceNamespace; // REQUIRED: A namespace for the AppdServiceName; equivalent to your AppDynamics application name + const char *serviceNamespace; // REQUIRED: A namespace for the ServiceName; int serviceNamespace_initialized; - const char *serviceName; // REQUIRED: Logical name of the service; equivalent to your AppDynamics tier name + const char *serviceName; // REQUIRED: Logical name of the service; int serviceName_initialized; const char *serviceInstanceId; // REQUIRED: The string ID of the service instance. Distinguish between instances of a service @@ -221,69 +221,69 @@ class ApacheConfigHandlers public: static std::unordered_map > m_webServerContexts; - static const char* appd_set_enabled(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelExporterType(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelExporterEndpoint(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelSslCertificatePath(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelProcessorType(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelSamplerType(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_serviceNamespace(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_serviceName(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_serviceInstanceId(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelMaxQueueSize(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelScheduledDelay(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelExportTimeout(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_otelMaxExportBatchSize(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_resolveBackends(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_traceAsError(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_reportAllInstrumentedModules(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_maskCookie(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_cookiePattern(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_maskSmUser(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_delimiter(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_segment(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_matchFilter(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_matchPattern(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_segmentType(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_set_segmentParameter(cmd_parms *cmd, void *conf, const char *arg); - static const char* appd_add_webserver_context( + static const char* otel_set_enabled(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelExporterType(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelExporterEndpoint(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelSslCertificatePath(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelProcessorType(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelSamplerType(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_serviceNamespace(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_serviceName(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_serviceInstanceId(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelMaxQueueSize(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelScheduledDelay(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelExportTimeout(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelMaxExportBatchSize(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_resolveBackends(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_traceAsError(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_reportAllInstrumentedModules(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_maskCookie(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_cookiePattern(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_maskSmUser(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_delimiter(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_segment(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_matchFilter(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_matchPattern(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_segmentType(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_segmentParameter(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_add_webserver_context( cmd_parms* cmd, void* conf, const char* serviceNamespace, const char* serviceName, const char* serviceInstanceId); - static void* appd_create_dir_config(apr_pool_t *p, char *dirspec); - static void* appd_merge_dir_config(apr_pool_t *p, void *parent_conf, void *newloc_conf); + static void* otel_create_dir_config(apr_pool_t *p, char *dirspec); + static void* otel_merge_dir_config(apr_pool_t *p, void *parent_conf, void *newloc_conf); - static appd_cfg* getConfig(const request_rec* r); - static appd_cfg* getProcessConfig(const request_rec* r); + static otel_cfg* getConfig(const request_rec* r); + static otel_cfg* getProcessConfig(const request_rec* r); - static std::string computeContextName(const appd_cfg* cfg); + static std::string computeContextName(const otel_cfg* cfg); static std::string hashPassword(const char* arg); - static void traceConfig(const request_rec* r, const appd_cfg* cfg); + static void traceConfig(const request_rec* r, const otel_cfg* cfg); private: - static appd_cfg* our_dconfig(const request_rec *r); + static otel_cfg* our_dconfig(const request_rec *r); static const char* helperChar( cmd_parms* cmd, - appd_cfg* cfg, + otel_cfg* cfg, const char* arg, const char*& var, int& inherit, const char* varName); static const char* helperInt( cmd_parms* cmd, - appd_cfg* cfg, + otel_cfg* cfg, const char* arg, int& var, int& inherit, const char* varName); - static void insertWebserverContext(cmd_parms* cmd, const appd_cfg* cfg); + static void insertWebserverContext(cmd_parms* cmd, const otel_cfg* cfg); }; #endif diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h index 1777f440a..eedc6a212 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h @@ -15,8 +15,8 @@ */ // This file includes are apache module hook functions -#ifndef APPD_APACHEHOOKS_H -#define APPD_APACHEHOOKS_H +#ifndef APACHEHOOKS_H +#define APACHEHOOKS_H #include #include @@ -28,10 +28,10 @@ class ApacheHooks public: static std::string m_aggregatorCommDir; static bool m_reportAllStages; - static const char* APPD_CONFIG_KEY; - static const char* APPD_CORRELATION_HEADER_KEY; - static const char* APPD_INTERACTION_HANDLE_KEY; - static const char* APPD_REQ_HANDLE_KEY; + static const char* OTEL_CONFIG_KEY; + static const char* OTEL_CORRELATION_HEADER_KEY; + static const char* OTEL_INTERACTION_HANDLE_KEY; + static const char* OTEL_REQ_HANDLE_KEY; static const int LOWEST_HTTP_ERROR_CODE = 400; static const std::initializer_list httpHeaders; static void registerHooks(apr_pool_t *p); @@ -39,12 +39,12 @@ class ApacheHooks friend class ApacheHooksForStage; private: - static void appd_child_init(apr_pool_t *p, server_rec *s); - static apr_status_t appd_child_exit(void* data); + static void otel_child_init(apr_pool_t *p, server_rec *s); + static apr_status_t otel_child_exit(void* data); - static bool initialize_appdynamics(const request_rec *r); - static int appd_hook_header_parser_begin(request_rec *r); - static int appd_hook_log_transaction_end(request_rec *r); + static bool initialize_opentelemetry(const request_rec *r); + static int otel_hook_header_parser_begin(request_rec *r); + static int otel_hook_log_transaction_end(request_rec *r); // Callback to start an Interaction @@ -54,25 +54,25 @@ class ApacheHooks // we ignore that backend call in the SDK. // // ASSUMPTION: if a module returns DECLINED, it does not go out to another tier. - static APPD_SDK_STATUS_CODE appd_startInteraction( + static OTEL_SDK_STATUS_CODE otel_startInteraction( request_rec *r, - HookContainer::appd_endpoint_indexes, + HookContainer::otel_endpoint_indexes, bool isAlwaysRunStage = false, bool ignoreBackend = false); // Callback to stop an Interaction - static void appd_stopInteraction(request_rec *r, bool isAlwaysRunStage = false, bool ignoreBackend = false); + static void otel_stopInteraction(request_rec *r, bool isAlwaysRunStage = false, bool ignoreBackend = false); - static void appd_payload_decorator(request_rec* r, std::unordered_map propagationHeaders); - static bool appd_requestHasErrors(request_rec* r); - static apr_status_t appd_output_filter(ap_filter_t* f, apr_bucket_brigade* pbb); + static void otel_payload_decorator(request_rec* r, std::unordered_map propagationHeaders); + static bool otel_requestHasErrors(request_rec* r); + static apr_status_t otel_output_filter(ap_filter_t* f, apr_bucket_brigade* pbb); // These hooks are for stopping interaction after a module callback in hook stages - static int appd_hook_interaction_end(request_rec *r); - static int appd_hook_interaction_end_handler(request_rec *r); // ignore backends in handler stage - static int appd_hook_interaction_end_quick_handler(request_rec *r, int i); - static void appd_hook_interaction_end_insert_filter(request_rec *r); - static int appd_hook_interaction_end_log_transaction(request_rec *r); + static int otel_hook_interaction_end(request_rec *r); + static int otel_hook_interaction_end_handler(request_rec *r); // ignore backends in handler stage + static int otel_hook_interaction_end_quick_handler(request_rec *r, int i); + static void otel_hook_interaction_end_insert_filter(request_rec *r); + static int otel_hook_interaction_end_log_transaction(request_rec *r); }; class ApacheHooksForStage @@ -81,27 +81,27 @@ class ApacheHooksForStage // For reference: Stages and their hook function prototypes, we can hook into the modules // for the following stages // - // int appd_hook_create_request(request_rec *r); - // void appd_hook_pre_read_request(request_rec *r, conn_rec* c); - // int appd_hook_post_read_request(request_rec *r); - // int appd_hook_header_parser(request_rec *r); - // const char* appd_hook_http_scheme(const request_rec *r); - // apr_port_t appd_hook_default_port(const request_rec *r); - // int appd_hook_quick_handler(request_rec *r, int i); - // int appd_hook_translate_name(request_rec *r); - // int appd_hook_map_to_storage(request_rec *r); - // int appd_hook_access_checker_ex(request_rec *r); - // int appd_hook_access_checker(request_rec *r); - // int appd_hook_check_user_id(request_rec *r); - // int appd_hook_note_auth_failure(request_rec *r, const char* c); - // int appd_hook_auth_checker(request_rec *r); - // int appd_hook_type_checker(request_rec *r); - // int appd_hook_fixups(request_rec *r); - // void appd_hook_insert_filter(request_rec *r); - // int appd_hook_handler(request_rec *r); - // int appd_hook_log_transaction(request_rec *r); - // void appd_hook_insert_error_filter(request_rec *r); - // int appd_hook_generate_log_id(const conn_rec *c, const request_rec *r, const char**); + // int otel_hook_create_request(request_rec *r); + // void otel_hook_pre_read_request(request_rec *r, conn_rec* c); + // int otel_hook_post_read_request(request_rec *r); + // int otel_hook_header_parser(request_rec *r); + // const char* otel_hook_http_scheme(const request_rec *r); + // apr_port_t otel_hook_default_port(const request_rec *r); + // int otel_hook_quick_handler(request_rec *r, int i); + // int otel_hook_translate_name(request_rec *r); + // int otel_hook_map_to_storage(request_rec *r); + // int otel_hook_access_checker_ex(request_rec *r); + // int otel_hook_access_checker(request_rec *r); + // int otel_hook_check_user_id(request_rec *r); + // int otel_hook_note_auth_failure(request_rec *r, const char* c); + // int otel_hook_auth_checker(request_rec *r); + // int otel_hook_type_checker(request_rec *r); + // int otel_hook_fixups(request_rec *r); + // void otel_hook_insert_filter(request_rec *r); + // int otel_hook_handler(request_rec *r); + // int otel_hook_log_transaction(request_rec *r); + // void otel_hook_insert_error_filter(request_rec *r); + // int otel_hook_generate_log_id(const conn_rec *c, const request_rec *r, const char**); /* function prototypes for the apache module hook callbacks according to different stages @@ -120,92 +120,92 @@ class ApacheHooksForStage TODO: Decide among the following stages at what all we need the modules to be instrumented, and define the hooks handlers for the same to start an interaction before module callback. */ - static int appd_hook_header_parser1(request_rec* r); - static int appd_hook_header_parser2(request_rec* r); - static int appd_hook_header_parser3(request_rec* r); - static int appd_hook_header_parser4(request_rec* r); - static int appd_hook_header_parser5(request_rec* r); - static int appd_hook_quick_handler1(request_rec* r, int i); - static int appd_hook_quick_handler2(request_rec* r, int i); - static int appd_hook_quick_handler3(request_rec* r, int i); - static int appd_hook_quick_handler4(request_rec* r, int i); - static int appd_hook_quick_handler5(request_rec* r, int i); - static int appd_hook_access_checker1(request_rec* r); - static int appd_hook_access_checker2(request_rec* r); - static int appd_hook_access_checker3(request_rec* r); - static int appd_hook_access_checker4(request_rec* r); - static int appd_hook_access_checker5(request_rec* r); - static int appd_hook_check_user_id1(request_rec* r); - static int appd_hook_check_user_id2(request_rec* r); - static int appd_hook_check_user_id3(request_rec* r); - static int appd_hook_check_user_id4(request_rec* r); - static int appd_hook_check_user_id5(request_rec* r); - static int appd_hook_auth_checker1(request_rec* r); - static int appd_hook_auth_checker2(request_rec* r); - static int appd_hook_auth_checker3(request_rec* r); - static int appd_hook_auth_checker4(request_rec* r); - static int appd_hook_auth_checker5(request_rec* r); - static int appd_hook_type_checker1(request_rec* r); - static int appd_hook_type_checker2(request_rec* r); - static int appd_hook_type_checker3(request_rec* r); - static int appd_hook_type_checker4(request_rec* r); - static int appd_hook_type_checker5(request_rec* r); - static int appd_hook_fixups1(request_rec* r); - static int appd_hook_fixups2(request_rec* r); - static int appd_hook_fixups3(request_rec* r); - static int appd_hook_fixups4(request_rec* r); - static int appd_hook_fixups5(request_rec* r); - static void appd_hook_insert_filter1(request_rec* r); - static void appd_hook_insert_filter2(request_rec* r); - static void appd_hook_insert_filter3(request_rec* r); - static void appd_hook_insert_filter4(request_rec* r); - static void appd_hook_insert_filter5(request_rec* r); - static int appd_hook_handler1(request_rec* r); - static int appd_hook_handler2(request_rec* r); - static int appd_hook_handler3(request_rec* r); - static int appd_hook_handler4(request_rec* r); - static int appd_hook_handler5(request_rec* r); - static int appd_hook_handler6(request_rec* r); - static int appd_hook_handler7(request_rec* r); - static int appd_hook_handler8(request_rec* r); - static int appd_hook_handler9(request_rec* r); - static int appd_hook_handler10(request_rec* r); - static int appd_hook_handler11(request_rec* r); - static int appd_hook_handler12(request_rec* r); - static int appd_hook_handler13(request_rec* r); - static int appd_hook_handler14(request_rec* r); - static int appd_hook_handler15(request_rec* r); - static int appd_hook_handler16(request_rec* r); - static int appd_hook_handler17(request_rec* r); - static int appd_hook_handler18(request_rec* r); - static int appd_hook_handler19(request_rec* r); - static int appd_hook_handler20(request_rec* r); - static int appd_hook_log_transaction1(request_rec* r); - static int appd_hook_log_transaction2(request_rec* r); - static int appd_hook_log_transaction3(request_rec* r); - static int appd_hook_log_transaction4(request_rec* r); - static int appd_hook_log_transaction5(request_rec* r); - - static const std::vector appd_header_parser_hooks; - static const std::vector appd_header_parser_indexes; - static const std::vector appd_quick_handler_hooks; - static const std::vector appd_quick_handler_indexes; - static const std::vector appd_access_checker_hooks; - static const std::vector appd_access_checker_indexes; - static const std::vector appd_check_user_id_hooks; - static const std::vector appd_check_user_id_indexes; - static const std::vector appd_auth_checker_hooks; - static const std::vector appd_auth_checker_indexes; - static const std::vector appd_type_checker_hooks; - static const std::vector appd_type_checker_indexes; - static const std::vector appd_fixups_hooks; - static const std::vector appd_fixups_indexes; - static const std::vector appd_insert_filter_hooks; - static const std::vector appd_insert_filter_indexes; - static const std::vector appd_handler_hooks; - static const std::vector appd_handler_indexes; - static const std::vector appd_log_transaction_hooks; - static const std::vector appd_log_transaction_indexes; + static int otel_hook_header_parser1(request_rec* r); + static int otel_hook_header_parser2(request_rec* r); + static int otel_hook_header_parser3(request_rec* r); + static int otel_hook_header_parser4(request_rec* r); + static int otel_hook_header_parser5(request_rec* r); + static int otel_hook_quick_handler1(request_rec* r, int i); + static int otel_hook_quick_handler2(request_rec* r, int i); + static int otel_hook_quick_handler3(request_rec* r, int i); + static int otel_hook_quick_handler4(request_rec* r, int i); + static int otel_hook_quick_handler5(request_rec* r, int i); + static int otel_hook_access_checker1(request_rec* r); + static int otel_hook_access_checker2(request_rec* r); + static int otel_hook_access_checker3(request_rec* r); + static int otel_hook_access_checker4(request_rec* r); + static int otel_hook_access_checker5(request_rec* r); + static int otel_hook_check_user_id1(request_rec* r); + static int otel_hook_check_user_id2(request_rec* r); + static int otel_hook_check_user_id3(request_rec* r); + static int otel_hook_check_user_id4(request_rec* r); + static int otel_hook_check_user_id5(request_rec* r); + static int otel_hook_auth_checker1(request_rec* r); + static int otel_hook_auth_checker2(request_rec* r); + static int otel_hook_auth_checker3(request_rec* r); + static int otel_hook_auth_checker4(request_rec* r); + static int otel_hook_auth_checker5(request_rec* r); + static int otel_hook_type_checker1(request_rec* r); + static int otel_hook_type_checker2(request_rec* r); + static int otel_hook_type_checker3(request_rec* r); + static int otel_hook_type_checker4(request_rec* r); + static int otel_hook_type_checker5(request_rec* r); + static int otel_hook_fixups1(request_rec* r); + static int otel_hook_fixups2(request_rec* r); + static int otel_hook_fixups3(request_rec* r); + static int otel_hook_fixups4(request_rec* r); + static int otel_hook_fixups5(request_rec* r); + static void otel_hook_insert_filter1(request_rec* r); + static void otel_hook_insert_filter2(request_rec* r); + static void otel_hook_insert_filter3(request_rec* r); + static void otel_hook_insert_filter4(request_rec* r); + static void otel_hook_insert_filter5(request_rec* r); + static int otel_hook_handler1(request_rec* r); + static int otel_hook_handler2(request_rec* r); + static int otel_hook_handler3(request_rec* r); + static int otel_hook_handler4(request_rec* r); + static int otel_hook_handler5(request_rec* r); + static int otel_hook_handler6(request_rec* r); + static int otel_hook_handler7(request_rec* r); + static int otel_hook_handler8(request_rec* r); + static int otel_hook_handler9(request_rec* r); + static int otel_hook_handler10(request_rec* r); + static int otel_hook_handler11(request_rec* r); + static int otel_hook_handler12(request_rec* r); + static int otel_hook_handler13(request_rec* r); + static int otel_hook_handler14(request_rec* r); + static int otel_hook_handler15(request_rec* r); + static int otel_hook_handler16(request_rec* r); + static int otel_hook_handler17(request_rec* r); + static int otel_hook_handler18(request_rec* r); + static int otel_hook_handler19(request_rec* r); + static int otel_hook_handler20(request_rec* r); + static int otel_hook_log_transaction1(request_rec* r); + static int otel_hook_log_transaction2(request_rec* r); + static int otel_hook_log_transaction3(request_rec* r); + static int otel_hook_log_transaction4(request_rec* r); + static int otel_hook_log_transaction5(request_rec* r); + + static const std::vector otel_header_parser_hooks; + static const std::vector otel_header_parser_indexes; + static const std::vector otel_quick_handler_hooks; + static const std::vector otel_quick_handler_indexes; + static const std::vector otel_access_checker_hooks; + static const std::vector otel_access_checker_indexes; + static const std::vector otel_check_user_id_hooks; + static const std::vector otel_check_user_id_indexes; + static const std::vector otel_auth_checker_hooks; + static const std::vector otel_auth_checker_indexes; + static const std::vector otel_type_checker_hooks; + static const std::vector otel_type_checker_indexes; + static const std::vector otel_fixups_hooks; + static const std::vector otel_fixups_indexes; + static const std::vector otel_insert_filter_hooks; + static const std::vector otel_insert_filter_indexes; + static const std::vector otel_handler_hooks; + static const std::vector otel_handler_indexes; + static const std::vector otel_log_transaction_hooks; + static const std::vector otel_log_transaction_indexes; template static void insertHooksForStage( @@ -213,7 +213,7 @@ class ApacheHooksForStage hook_get_t getModules, T setHook, const std::vector &beginHandlers, - const std::vector &indexes, + const std::vector &indexes, S endHandler, const std::string& stage); }; diff --git a/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h b/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h index 29d01fddc..d01a0866f 100644 --- a/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h +++ b/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef APPD_EXCLUDEDMODULES_H -#define APPD_EXCLUDEDMODULES_H +#ifndef EXCLUDEDMODULES_H +#define EXCLUDEDMODULES_H #include #include diff --git a/instrumentation/otel-webserver-module/include/apache/HookContainer.h b/instrumentation/otel-webserver-module/include/apache/HookContainer.h index 3a757fda9..a15b782bd 100644 --- a/instrumentation/otel-webserver-module/include/apache/HookContainer.h +++ b/instrumentation/otel-webserver-module/include/apache/HookContainer.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef APPD_HOOKSCONTAINER_H -#define APPD_HOOKSCONTAINER_H +#ifndef HOOKSCONTAINER_H +#define HOOKSCONTAINER_H #include #include @@ -39,82 +39,82 @@ class HookContainer public: // The following are indentifiers into the hookContainer storage. This is needed to // store and retrieve the endpoint module name. - enum appd_endpoint_indexes + enum otel_endpoint_indexes { - APPD_ENDPOINT_HEADER_PARSER1 - ,APPD_ENDPOINT_HEADER_PARSER2 - ,APPD_ENDPOINT_HEADER_PARSER3 - ,APPD_ENDPOINT_HEADER_PARSER4 - ,APPD_ENDPOINT_HEADER_PARSER5 - ,APPD_ENDPOINT_QUICK_HANDLER1 - ,APPD_ENDPOINT_QUICK_HANDLER2 - ,APPD_ENDPOINT_QUICK_HANDLER3 - ,APPD_ENDPOINT_QUICK_HANDLER4 - ,APPD_ENDPOINT_QUICK_HANDLER5 - ,APPD_ENDPOINT_ACCESS_CHECKER1 - ,APPD_ENDPOINT_ACCESS_CHECKER2 - ,APPD_ENDPOINT_ACCESS_CHECKER3 - ,APPD_ENDPOINT_ACCESS_CHECKER4 - ,APPD_ENDPOINT_ACCESS_CHECKER5 - ,APPD_ENDPOINT_CHECK_USER_ID1 - ,APPD_ENDPOINT_CHECK_USER_ID2 - ,APPD_ENDPOINT_CHECK_USER_ID3 - ,APPD_ENDPOINT_CHECK_USER_ID4 - ,APPD_ENDPOINT_CHECK_USER_ID5 - ,APPD_ENDPOINT_AUTH_CHECKER1 - ,APPD_ENDPOINT_AUTH_CHECKER2 - ,APPD_ENDPOINT_AUTH_CHECKER3 - ,APPD_ENDPOINT_AUTH_CHECKER4 - ,APPD_ENDPOINT_AUTH_CHECKER5 - ,APPD_ENDPOINT_TYPE_CHECKER1 - ,APPD_ENDPOINT_TYPE_CHECKER2 - ,APPD_ENDPOINT_TYPE_CHECKER3 - ,APPD_ENDPOINT_TYPE_CHECKER4 - ,APPD_ENDPOINT_TYPE_CHECKER5 - ,APPD_ENDPOINT_FIXUPS1 - ,APPD_ENDPOINT_FIXUPS2 - ,APPD_ENDPOINT_FIXUPS3 - ,APPD_ENDPOINT_FIXUPS4 - ,APPD_ENDPOINT_FIXUPS5 - ,APPD_ENDPOINT_INSERT_FILTER1 - ,APPD_ENDPOINT_INSERT_FILTER2 - ,APPD_ENDPOINT_INSERT_FILTER3 - ,APPD_ENDPOINT_INSERT_FILTER4 - ,APPD_ENDPOINT_INSERT_FILTER5 - ,APPD_ENDPOINT_HANDLER1 - ,APPD_ENDPOINT_HANDLER2 - ,APPD_ENDPOINT_HANDLER3 - ,APPD_ENDPOINT_HANDLER4 - ,APPD_ENDPOINT_HANDLER5 - ,APPD_ENDPOINT_HANDLER6 - ,APPD_ENDPOINT_HANDLER7 - ,APPD_ENDPOINT_HANDLER8 - ,APPD_ENDPOINT_HANDLER9 - ,APPD_ENDPOINT_HANDLER10 - ,APPD_ENDPOINT_HANDLER11 - ,APPD_ENDPOINT_HANDLER12 - ,APPD_ENDPOINT_HANDLER13 - ,APPD_ENDPOINT_HANDLER14 - ,APPD_ENDPOINT_HANDLER15 - ,APPD_ENDPOINT_HANDLER16 - ,APPD_ENDPOINT_HANDLER17 - ,APPD_ENDPOINT_HANDLER18 - ,APPD_ENDPOINT_HANDLER19 - ,APPD_ENDPOINT_HANDLER20 - ,APPD_ENDPOINT_LOG_TRANSACTION1 - ,APPD_ENDPOINT_LOG_TRANSACTION2 - ,APPD_ENDPOINT_LOG_TRANSACTION3 - ,APPD_ENDPOINT_LOG_TRANSACTION4 - ,APPD_ENDPOINT_LOG_TRANSACTION5 + OTEL_ENDPOINT_HEADER_PARSER1 + ,OTEL_ENDPOINT_HEADER_PARSER2 + ,OTEL_ENDPOINT_HEADER_PARSER3 + ,OTEL_ENDPOINT_HEADER_PARSER4 + ,OTEL_ENDPOINT_HEADER_PARSER5 + ,OTEL_ENDPOINT_QUICK_HANDLER1 + ,OTEL_ENDPOINT_QUICK_HANDLER2 + ,OTEL_ENDPOINT_QUICK_HANDLER3 + ,OTEL_ENDPOINT_QUICK_HANDLER4 + ,OTEL_ENDPOINT_QUICK_HANDLER5 + ,OTEL_ENDPOINT_ACCESS_CHECKER1 + ,OTEL_ENDPOINT_ACCESS_CHECKER2 + ,OTEL_ENDPOINT_ACCESS_CHECKER3 + ,OTEL_ENDPOINT_ACCESS_CHECKER4 + ,OTEL_ENDPOINT_ACCESS_CHECKER5 + ,OTEL_ENDPOINT_CHECK_USER_ID1 + ,OTEL_ENDPOINT_CHECK_USER_ID2 + ,OTEL_ENDPOINT_CHECK_USER_ID3 + ,OTEL_ENDPOINT_CHECK_USER_ID4 + ,OTEL_ENDPOINT_CHECK_USER_ID5 + ,OTEL_ENDPOINT_AUTH_CHECKER1 + ,OTEL_ENDPOINT_AUTH_CHECKER2 + ,OTEL_ENDPOINT_AUTH_CHECKER3 + ,OTEL_ENDPOINT_AUTH_CHECKER4 + ,OTEL_ENDPOINT_AUTH_CHECKER5 + ,OTEL_ENDPOINT_TYPE_CHECKER1 + ,OTEL_ENDPOINT_TYPE_CHECKER2 + ,OTEL_ENDPOINT_TYPE_CHECKER3 + ,OTEL_ENDPOINT_TYPE_CHECKER4 + ,OTEL_ENDPOINT_TYPE_CHECKER5 + ,OTEL_ENDPOINT_FIXUPS1 + ,OTEL_ENDPOINT_FIXUPS2 + ,OTEL_ENDPOINT_FIXUPS3 + ,OTEL_ENDPOINT_FIXUPS4 + ,OTEL_ENDPOINT_FIXUPS5 + ,OTEL_ENDPOINT_INSERT_FILTER1 + ,OTEL_ENDPOINT_INSERT_FILTER2 + ,OTEL_ENDPOINT_INSERT_FILTER3 + ,OTEL_ENDPOINT_INSERT_FILTER4 + ,OTEL_ENDPOINT_INSERT_FILTER5 + ,OTEL_ENDPOINT_HANDLER1 + ,OTEL_ENDPOINT_HANDLER2 + ,OTEL_ENDPOINT_HANDLER3 + ,OTEL_ENDPOINT_HANDLER4 + ,OTEL_ENDPOINT_HANDLER5 + ,OTEL_ENDPOINT_HANDLER6 + ,OTEL_ENDPOINT_HANDLER7 + ,OTEL_ENDPOINT_HANDLER8 + ,OTEL_ENDPOINT_HANDLER9 + ,OTEL_ENDPOINT_HANDLER10 + ,OTEL_ENDPOINT_HANDLER11 + ,OTEL_ENDPOINT_HANDLER12 + ,OTEL_ENDPOINT_HANDLER13 + ,OTEL_ENDPOINT_HANDLER14 + ,OTEL_ENDPOINT_HANDLER15 + ,OTEL_ENDPOINT_HANDLER16 + ,OTEL_ENDPOINT_HANDLER17 + ,OTEL_ENDPOINT_HANDLER18 + ,OTEL_ENDPOINT_HANDLER19 + ,OTEL_ENDPOINT_HANDLER20 + ,OTEL_ENDPOINT_LOG_TRANSACTION1 + ,OTEL_ENDPOINT_LOG_TRANSACTION2 + ,OTEL_ENDPOINT_LOG_TRANSACTION3 + ,OTEL_ENDPOINT_LOG_TRANSACTION4 + ,OTEL_ENDPOINT_LOG_TRANSACTION5 - ,APPD_MAX_ENDPOINTS + ,OTEL_MAX_ENDPOINTS }; static HookContainer& getInstance(); - void addHook(appd_endpoint_indexes index, const std::string& stage, const std::string& module, int order); - const std::string& getStage(appd_endpoint_indexes index) const; - const std::string& getModule(appd_endpoint_indexes index) const; - const char* const* getModuleList(appd_endpoint_indexes index) const; + void addHook(otel_endpoint_indexes index, const std::string& stage, const std::string& module, int order); + const std::string& getStage(otel_endpoint_indexes index) const; + const std::string& getModule(otel_endpoint_indexes index) const; + const char* const* getModuleList(otel_endpoint_indexes index) const; void traceHooks(request_rec* r) const; private: diff --git a/instrumentation/otel-webserver-module/include/core/AgentCore.h b/instrumentation/otel-webserver-module/include/core/AgentCore.h index 68dfad2ae..729abd15e 100644 --- a/instrumentation/otel-webserver-module/include/core/AgentCore.h +++ b/instrumentation/otel-webserver-module/include/core/AgentCore.h @@ -28,9 +28,9 @@ // Contexts did not exist in the beginning. Users put in the serviceNamespace/serviceName/serviceInstanceId // in the init config structure. -#define COREINIT_CONTEXT "APPD_COREINIT_CONTEXT" +#define COREINIT_CONTEXT "OTEL_COREINIT_CONTEXT" -namespace appd { +namespace otel { namespace core { class AgentKernel : public IKernel @@ -39,8 +39,8 @@ class AgentKernel : public IKernel AgentKernel(); ~AgentKernel() = default; - void initKernel(std::shared_ptr config, - std::shared_ptr spanNamer) override; + void initKernel(std::shared_ptr config, + std::shared_ptr spanNamer) override; IRequestProcessingEngine* getRequestProcessingEngine() override; @@ -59,16 +59,16 @@ class AgentKernel : public IKernel class WebServerContext : public IContext { public: - WebServerContext(std::shared_ptr tenantConfig); + WebServerContext(std::shared_ptr tenantConfig); ~WebServerContext() = default; - void initContext(std::shared_ptr spanNamer) override; + void initContext(std::shared_ptr spanNamer) override; IKernel* getKernel() const override { return mAgentKernel.get();} - std::shared_ptr getConfig() override { return mTenantConfig;} + std::shared_ptr getConfig() override { return mTenantConfig;} private: - std::shared_ptr mTenantConfig; + std::shared_ptr mTenantConfig; //TODO: EUM config protected: std::unique_ptr mAgentKernel; @@ -81,8 +81,8 @@ class AgentCore : public ICore ~AgentCore() = default; bool start( - std::shared_ptr initConfig, - std::shared_ptr spanNamer, + std::shared_ptr initConfig, + std::shared_ptr spanNamer, userAddedTenantMap& userAddedTenants) override; void stop() override; @@ -93,7 +93,7 @@ class AgentCore : public ICore void addContext( const std::string& contextName, - std::shared_ptr newConfig) override; + std::shared_ptr newConfig) override; std::shared_ptr getWebServerContext(std::string& name) override; @@ -101,7 +101,7 @@ class AgentCore : public ICore // Member variables private: AgentLogger mLogger; - std::shared_ptr mSpanNamer; + std::shared_ptr mSpanNamer; protected: std::unordered_map #include -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -84,7 +84,7 @@ class RequestContext }; -} // appd +} // otel } // core #endif diff --git a/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h b/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h index db8b525be..a17d79cb5 100644 --- a/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h +++ b/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h @@ -23,7 +23,7 @@ #include "AgentLogger.h" #include -namespace appd { +namespace otel { namespace core { class TenantConfig; @@ -31,17 +31,17 @@ class TenantConfig; /*class RealEnvinronmentReader : public IEnvReader { public: - virtual APPD_SDK_STATUS_CODE ReadMandatory(const std::string& varName, std::string& result); - virtual APPD_SDK_STATUS_CODE ReadOptional(const std::string& varName, std::string& result); + virtual OTEL_SDK_STATUS_CODE ReadMandatory(const std::string& varName, std::string& result); + virtual OTEL_SDK_STATUS_CODE ReadOptional(const std::string& varName, std::string& result); };*/ class PassedEnvinronmentReader : public IEnvReader { public: - APPD_SDK_STATUS_CODE Init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords); + OTEL_SDK_STATUS_CODE Init(OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords); - virtual APPD_SDK_STATUS_CODE ReadMandatory(const std::string& varName, std::string& result); - virtual APPD_SDK_STATUS_CODE ReadOptional(const std::string& varName, std::string& result); + virtual OTEL_SDK_STATUS_CODE ReadMandatory(const std::string& varName, std::string& result); + virtual OTEL_SDK_STATUS_CODE ReadOptional(const std::string& varName, std::string& result); private: std::map env; @@ -58,24 +58,24 @@ class ApiUtils : public IApiUtils /* * TODO: Following functions will be implemented while doing agent init and term */ - APPD_SDK_STATUS_CODE init_boilerplate() override; // initializes agentLogging + OTEL_SDK_STATUS_CODE init_boilerplate() override; // initializes agentLogging - APPD_SDK_STATUS_CODE ReadFromPassedSettings( - APPD_SDK_ENV_RECORD* env, + OTEL_SDK_STATUS_CODE ReadFromPassedSettings( + OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, TenantConfig& tenantConfig, SpanNamer& spanNamer) override; - //APPD_SDK_STATUS_CODE ReadFromEnvinronment(TenantConfig&) override; + //OTEL_SDK_STATUS_CODE ReadFromEnvinronment(TenantConfig&) override; protected: - APPD_SDK_STATUS_CODE ReadSettingsFromReader( + OTEL_SDK_STATUS_CODE ReadSettingsFromReader( IEnvReader& reader, TenantConfig&, SpanNamer&) override; - /*APPD_SDK_STATUS_CODE ReadMandatoryFromReader( + /*OTEL_SDK_STATUS_CODE ReadMandatoryFromReader( IEnvReader& reader, const std::string& varName, unsigned short& result) override;*/ - APPD_SDK_STATUS_CODE ReadOptionalFromReader( + OTEL_SDK_STATUS_CODE ReadOptionalFromReader( IEnvReader& reader, const std::string& varName, bool& result) override; - APPD_SDK_STATUS_CODE ReadOptionalFromReader( + OTEL_SDK_STATUS_CODE ReadOptionalFromReader( IEnvReader& reader, const std::string& varName, unsigned int& result) override; }; diff --git a/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h b/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h index 2d42e13ef..3e98132b1 100755 --- a/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h +++ b/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h @@ -25,114 +25,114 @@ /* {{{ For API user: environment variables to specify Controller connectivity */ -#define APPD_SDK_ENV_OTEL_EXPORTER_TYPE "APPD_SDK_ENV_OTEL_EXPORTER_TYPE" -#define APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT "APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT" /*required*/ -#define APPD_SDK_ENV_OTEL_SSL_ENABLED "APPD_SDK_ENV_OTEL_SSL_ENABLED" /*optional*/ -#define APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH "APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH" /*optional*/ -#define APPD_SDK_ENV_OTEL_PROCESSOR_TYPE "APPD_SDK_ENV_OTEL_PROCESSOR_TYPE" -#define APPD_SDK_ENV_OTEL_SAMPLER_TYPE "APPD_SDK_ENV_OTEL_SAMPLER_TYPE" -#define APPD_SDK_ENV_OTEL_LIBRARY_NAME "APPD_SDK_ENV_OTEL_LIBRARY_NAME" +#define OTEL_SDK_ENV_OTEL_EXPORTER_TYPE "OTEL_SDK_ENV_OTEL_EXPORTER_TYPE" +#define OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT "OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT" /*required*/ +#define OTEL_SDK_ENV_OTEL_SSL_ENABLED "OTEL_SDK_ENV_OTEL_SSL_ENABLED" /*optional*/ +#define OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH "OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH" /*optional*/ +#define OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE "OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE" +#define OTEL_SDK_ENV_OTEL_SAMPLER_TYPE "OTEL_SDK_ENV_OTEL_SAMPLER_TYPE" +#define OTEL_SDK_ENV_OTEL_LIBRARY_NAME "OTEL_SDK_ENV_OTEL_LIBRARY_NAME" /* {{{ For API user: optional, only if connection by aggregator is required */ -#define APPD_SDK_ENV_SERVICE_NAMESPACE "APPD_SDK_ENV_SERVICE_NAMESPACE" -#define APPD_SDK_ENV_SERVICE_NAME "APPD_SDK_ENV_SERVICE_NAME" /*optional*/ -#define APPD_SDK_ENV_SERVICE_INSTANCE_ID "APPD_SDK_ENV_SERVICE_INSTANCE_ID" /*optional*/ +#define OTEL_SDK_ENV_SERVICE_NAMESPACE "OTEL_SDK_ENV_SERVICE_NAMESPACE" +#define OTEL_SDK_ENV_SERVICE_NAME "OTEL_SDK_ENV_SERVICE_NAME" /*optional*/ +#define OTEL_SDK_ENV_SERVICE_INSTANCE_ID "OTEL_SDK_ENV_SERVICE_INSTANCE_ID" /*optional*/ /* }}} */ /* {{{ For API user: environment variables to specify Webserver HostName/IP/Port */ -#define APPD_SDK_ENV_MAX_QUEUE_SIZE "APPD_SDK_ENV_MAX_QUEUE_SIZE" /*required*/ -#define APPD_SDK_ENV_SCHEDULED_DELAY "APPD_SDK_ENV_SCHEDULED_DELAY" /*required*/ -#define APPD_SDK_ENV_EXPORT_BATCH_SIZE "APPD_SDK_ENV_EXPORT_BATCH_SIZE" /*required*/ -#define APPD_SDK_ENV_EXPORT_TIMEOUT "APPD_SDK_ENV_EXPORT_TIMEOUT" +#define OTEL_SDK_ENV_MAX_QUEUE_SIZE "OTEL_SDK_ENV_MAX_QUEUE_SIZE" /*required*/ +#define OTEL_SDK_ENV_SCHEDULED_DELAY "OTEL_SDK_ENV_SCHEDULED_DELAY" /*required*/ +#define OTEL_SDK_ENV_EXPORT_BATCH_SIZE "OTEL_SDK_ENV_EXPORT_BATCH_SIZE" /*required*/ +#define OTEL_SDK_ENV_EXPORT_TIMEOUT "OTEL_SDK_ENV_EXPORT_TIMEOUT" /* }}} */ /* {{{ For API user: environment variables to override SDK installation defaults */ -#define APPD_SDK_ENV_LOG_CONFIG_PATH "APPD_SDK_LOG_CONFIG_PATH" +#define OTEL_SDK_ENV_LOG_CONFIG_PATH "OTEL_SDK_LOG_CONFIG_PATH" /* }}} */ // SPAN NAMING ENV VARIABLES -#define APPD_SDK_ENV_SEGMENT_TYPE "APPD_SDK_ENV_SEGMENT_TYPE" -#define APPD_SDK_ENV_SEGMENT_PARAMETER "APPD_SDK_ENV_SEGMENT_PARAMETER" +#define OTEL_SDK_ENV_SEGMENT_TYPE "OTEL_SDK_ENV_SEGMENT_TYPE" +#define OTEL_SDK_ENV_SEGMENT_PARAMETER "OTEL_SDK_ENV_SEGMENT_PARAMETER" /* {{{ For API user: API User logger */ -#define APPD_LOG_API_USER_LOGGER "api_user" /*logging at the level of sdk function call*/ -#define APPD_LOG_API_LOGGER "api" /*logging at the level of sdk core functionality*/ +#define OTEL_LOG_API_USER_LOGGER "api_user" /*logging at the level of sdk function call*/ +#define OTEL_LOG_API_LOGGER "api" /*logging at the level of sdk core functionality*/ /* }}} */ /* {{{ Internal: Status definition */ -#define APPD_PREFIXED_NAME(prefix, name) prefix##name +#define OTEL_PREFIXED_NAME(prefix, name) prefix##name /* }}} */ /* {{{ For API user: Status code and error helper */ -#define APPD_STATUS(name) APPD_PREFIXED_NAME(appd_sdk_status_,name) -#define APPD_SUCCESS APPD_STATUS(success) -#define APPD_ISFAIL(value) ((value) != APPD_SUCCESS) -#define APPD_ISSUCCESS(value) ((value) == APPD_SUCCESS) +#define OTEL_STATUS(name) OTEL_PREFIXED_NAME(otel_sdk_status_,name) +#define OTEL_SUCCESS OTEL_STATUS(success) +#define OTEL_ISFAIL(value) ((value) != OTEL_SUCCESS) +#define OTEL_ISSUCCESS(value) ((value) == OTEL_SUCCESS) /* }}} */ #if defined(_WIN32) -#define APPD_SDK_API __declspec(dllexport) +#define OTEL_SDK_API __declspec(dllexport) #else -#define APPD_SDK_API __attribute__((visibility("default"))) +#define OTEL_SDK_API __attribute__((visibility("default"))) #endif -typedef enum APPD_SDK_API +typedef enum OTEL_SDK_API { - APPD_STATUS(success) = 0 - ,APPD_STATUS(fail) - ,APPD_STATUS(agent_failed_to_start) - ,APPD_STATUS(unspecified_environment_variable) - ,APPD_STATUS(environment_variable_invalid_value) - ,APPD_STATUS(environment_records_are_invalid) - ,APPD_STATUS(environment_record_name_is_not_specified_or_empty) - ,APPD_STATUS(environment_record_value_is_not_specified) - ,APPD_STATUS(no_log_config) - ,APPD_STATUS(log_init_failed) - ,APPD_STATUS(invalid_bt_type) - ,APPD_STATUS(invalid_backend_type) - ,APPD_STATUS(bt_name_invalid) - ,APPD_STATUS(uninitialized) - ,APPD_STATUS(wrong_handle) - ,APPD_STATUS(cannot_create_handle) - ,APPD_STATUS(already_initialized) - ,APPD_STATUS(payload_reflector_is_null) - ,APPD_STATUS(backend_reflector_is_null) - ,APPD_STATUS(handle_pointer_is_null) - ,APPD_STATUS(invalid_input_string) - ,APPD_STATUS(uninitialized_input) - ,APPD_STATUS(bt_detection_disabled) - ,APPD_STATUS(wrong_process_id) - ,APPD_STATUS(cfg_channel_uninitialized) - ,APPD_STATUS(invalid_context) - ,APPD_STATUS(cannot_add_ws_context_to_core) + OTEL_STATUS(success) = 0 + ,OTEL_STATUS(fail) + ,OTEL_STATUS(agent_failed_to_start) + ,OTEL_STATUS(unspecified_environment_variable) + ,OTEL_STATUS(environment_variable_invalid_value) + ,OTEL_STATUS(environment_records_are_invalid) + ,OTEL_STATUS(environment_record_name_is_not_specified_or_empty) + ,OTEL_STATUS(environment_record_value_is_not_specified) + ,OTEL_STATUS(no_log_config) + ,OTEL_STATUS(log_init_failed) + ,OTEL_STATUS(invalid_bt_type) + ,OTEL_STATUS(invalid_backend_type) + ,OTEL_STATUS(bt_name_invalid) + ,OTEL_STATUS(uninitialized) + ,OTEL_STATUS(wrong_handle) + ,OTEL_STATUS(cannot_create_handle) + ,OTEL_STATUS(already_initialized) + ,OTEL_STATUS(payload_reflector_is_null) + ,OTEL_STATUS(backend_reflector_is_null) + ,OTEL_STATUS(handle_pointer_is_null) + ,OTEL_STATUS(invalid_input_string) + ,OTEL_STATUS(uninitialized_input) + ,OTEL_STATUS(bt_detection_disabled) + ,OTEL_STATUS(wrong_process_id) + ,OTEL_STATUS(cfg_channel_uninitialized) + ,OTEL_STATUS(invalid_context) + ,OTEL_STATUS(cannot_add_ws_context_to_core) /* {{{ Internal: */ - ,APPD_STATUS(count) + ,OTEL_STATUS(count) /* }}} */ -} APPD_SDK_STATUS_CODE; +} OTEL_SDK_STATUS_CODE; /* }}} */ /* {{{ Internal: Handle definitions */ -#define APPD_SDK_HANDLE void* +#define OTEL_SDK_HANDLE void* /* }}} */ /* {{{ For API user: Handle definitions */ -#define APPD_SDK_NO_HANDLE NULL -#define APPD_SDK_HANDLE_REQ APPD_SDK_HANDLE -#define APPD_SDK_HANDLE_INTERACTION APPD_SDK_HANDLE +#define OTEL_SDK_NO_HANDLE NULL +#define OTEL_SDK_HANDLE_REQ OTEL_SDK_HANDLE +#define OTEL_SDK_HANDLE_INTERACTION OTEL_SDK_HANDLE /* }}} */ /* {{{ For API user: function parameter value direction */ -#define APPD_SDK_PARAM_IN -#define APPD_SDK_PARAM_OUT +#define OTEL_SDK_PARAM_IN +#define OTEL_SDK_PARAM_OUT /* }}} */ /* {{{ For API user: backend type */ -typedef struct _APPD_SDK_ENV_RECORD +typedef struct _OTEL_SDK_ENV_RECORD { const char* name; const char* value; -} APPD_SDK_ENV_RECORD; +} OTEL_SDK_ENV_RECORD; /* }}} */ #endif /* APPDYNAMICS_SDK_H */ diff --git a/instrumentation/otel-webserver-module/include/core/api/Interface.h b/instrumentation/otel-webserver-module/include/core/api/Interface.h index b704c9ef2..990ea07c6 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Interface.h +++ b/instrumentation/otel-webserver-module/include/core/api/Interface.h @@ -20,7 +20,7 @@ #include #include -namespace appd { +namespace otel { namespace core { class IRequestProcessingEngine; @@ -28,9 +28,9 @@ class IRequestProcessingEngine; class IEnvReader { public: - virtual APPD_SDK_STATUS_CODE ReadMandatory( + virtual OTEL_SDK_STATUS_CODE ReadMandatory( const std::string& varName, std::string& result) = 0; - virtual APPD_SDK_STATUS_CODE ReadOptional( + virtual OTEL_SDK_STATUS_CODE ReadOptional( const std::string& varName, std::string& result) = 0; }; @@ -39,22 +39,22 @@ class IApiUtils public: virtual ~IApiUtils() = default; - virtual APPD_SDK_STATUS_CODE init_boilerplate() = 0; // initializes agentLogging + virtual OTEL_SDK_STATUS_CODE init_boilerplate() = 0; // initializes agentLogging - virtual APPD_SDK_STATUS_CODE ReadFromPassedSettings( - APPD_SDK_ENV_RECORD* env, + virtual OTEL_SDK_STATUS_CODE ReadFromPassedSettings( + OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, TenantConfig& tenantConfig, SpanNamer& spanNamer) = 0; protected: - //virtual APPD_SDK_STATUS_CODE ReadFromEnvinronment(TenantConfig&) = 0; - virtual APPD_SDK_STATUS_CODE ReadSettingsFromReader( + //virtual OTEL_SDK_STATUS_CODE ReadFromEnvinronment(TenantConfig&) = 0; + virtual OTEL_SDK_STATUS_CODE ReadSettingsFromReader( IEnvReader& reader, TenantConfig&, SpanNamer&) = 0; - /*virtual APPD_SDK_STATUS_CODE ReadMandatoryFromReader( + /*virtual OTEL_SDK_STATUS_CODE ReadMandatoryFromReader( IEnvReader& reader, const std::string& varName, unsigned short& result) = 0;*/ - virtual APPD_SDK_STATUS_CODE ReadOptionalFromReader( + virtual OTEL_SDK_STATUS_CODE ReadOptionalFromReader( IEnvReader& reader, const std::string& varName, bool& result) = 0; - virtual APPD_SDK_STATUS_CODE ReadOptionalFromReader( + virtual OTEL_SDK_STATUS_CODE ReadOptionalFromReader( IEnvReader& reader, const std::string& varName, unsigned int& result) = 0; }; @@ -63,8 +63,8 @@ class IKernel public: virtual ~IKernel() = default; - virtual void initKernel(std::shared_ptr config, - std::shared_ptr spanNamer) = 0; + virtual void initKernel(std::shared_ptr config, + std::shared_ptr spanNamer) = 0; virtual IRequestProcessingEngine* getRequestProcessingEngine() = 0; }; @@ -74,11 +74,11 @@ class IContext public: virtual ~IContext() = default; - virtual void initContext(std::shared_ptr spanNamer) = 0; + virtual void initContext(std::shared_ptr spanNamer) = 0; virtual IKernel* getKernel() const = 0; - virtual std::shared_ptr getConfig() = 0; + virtual std::shared_ptr getConfig() = 0; }; class ICore @@ -90,8 +90,8 @@ class ICore virtual ~ICore() = default; virtual bool start( - std::shared_ptr initConfig, - std::shared_ptr spanNamer, + std::shared_ptr initConfig, + std::shared_ptr spanNamer, userAddedTenantMap& userAddedTenants) = 0; virtual void stop() = 0; diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index fc06a4736..a3325e0b2 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -20,13 +20,13 @@ #include #include "sdkwrapper/SdkConstants.h" -namespace appd { +namespace otel { namespace core { //----------------------------------------------------------------------------------------- // RequestPayload // Used for following purposes: -// 1) Get the incoming request information from the web-server and pass it to the appdynamics +// 1) Get the incoming request information from the web-server and pass it to the otel // core sdk library //----------------------------------------------------------------------------------------- class RequestPayload @@ -126,7 +126,7 @@ struct EndInteractionPayload {} }; -} // appd +} // otel } // core #endif diff --git a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h index b1b28a4d9..68706c02a 100644 --- a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h +++ b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h @@ -24,7 +24,7 @@ #include -namespace appd { +namespace otel { namespace core { class TenantConfig; @@ -45,20 +45,20 @@ class IRequestProcessingEngine { virtual ~IRequestProcessingEngine() {} virtual void init(std::shared_ptr& config, std::shared_ptr spanNamer) = 0; - virtual APPD_SDK_STATUS_CODE startRequest( + virtual OTEL_SDK_STATUS_CODE startRequest( const std::string& wscontext, RequestPayload* payload, - APPD_SDK_HANDLE_REQ* reqHandle) = 0; - virtual APPD_SDK_STATUS_CODE endRequest( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_HANDLE_REQ* reqHandle) = 0; + virtual OTEL_SDK_STATUS_CODE endRequest( + OTEL_SDK_HANDLE_REQ reqHandle, const char* error, const ResponsePayload* payload = nullptr) = 0; - virtual APPD_SDK_STATUS_CODE startInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + virtual OTEL_SDK_STATUS_CODE startInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, std::unordered_map& propagationHeaders) = 0; - virtual APPD_SDK_STATUS_CODE endInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + virtual OTEL_SDK_STATUS_CODE endInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, bool ignoreBackend, EndInteractionPayload *payload) = 0; }; @@ -71,31 +71,31 @@ class RequestProcessingEngine : public IRequestProcessingEngine { void init(std::shared_ptr& config, std::shared_ptr spanNamer) override; - APPD_SDK_STATUS_CODE startRequest( + OTEL_SDK_STATUS_CODE startRequest( const std::string& wscontext, RequestPayload* payload, - APPD_SDK_HANDLE_REQ* reqHandle) override; - APPD_SDK_STATUS_CODE endRequest( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_HANDLE_REQ* reqHandle) override; + OTEL_SDK_STATUS_CODE endRequest( + OTEL_SDK_HANDLE_REQ reqHandle, const char* error, const ResponsePayload* payload = nullptr) override; - APPD_SDK_STATUS_CODE startInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_STATUS_CODE startInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, std::unordered_map& propagationHeaders) override; - APPD_SDK_API APPD_SDK_STATUS_CODE endInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_API OTEL_SDK_STATUS_CODE endInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, bool ignoreBackend, EndInteractionPayload *payload) override; protected: - std::shared_ptr m_sdkWrapper; - std::shared_ptr m_spanNamer; + std::shared_ptr m_sdkWrapper; + std::shared_ptr m_spanNamer; private: AgentLogger mLogger; }; } // core -} // appd +} // otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h b/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h index ba7e53ddb..2ca3997be 100644 --- a/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h +++ b/instrumentation/otel-webserver-module/include/core/api/SpanNamer.h @@ -17,7 +17,7 @@ #include -namespace appd { +namespace otel { namespace core { enum class SegmentType @@ -52,6 +52,6 @@ class SpanNamer }; } // core -} // appd +} // otel diff --git a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h index 7069c1647..a51c8a00a 100644 --- a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h +++ b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h @@ -18,7 +18,7 @@ #include #include -namespace appd { +namespace otel { namespace core { class TenantConfig @@ -95,7 +95,7 @@ class TenantConfig //: configuration options have not been added for these; as of now they will have their default vaules }; -inline std::ostream& operator<< (std::ostream &os, const appd::core::TenantConfig &config) +inline std::ostream& operator<< (std::ostream &os, const otel::core::TenantConfig &config) { os << "\n ServiceNamespace: " << config.getServiceNamespace() << "\n ServiceName: " << config.getServiceName() @@ -113,6 +113,6 @@ inline std::ostream& operator<< (std::ostream &os, const appd::core::TenantConfi } } // core -} // appd +} // otel diff --git a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h index abe2817ef..e4563c43c 100644 --- a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h +++ b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef APPD_WS_AGENT_H -#define APPD_WS_AGENT_H +#ifndef OTEL_WS_AGENT_H +#define OTEL_WS_AGENT_H #include "api/AppdynamicsSdk.h" #include @@ -26,7 +26,7 @@ #include "api/Payload.h" #include -namespace appd { +namespace otel { namespace core { /** @@ -49,41 +49,41 @@ class WSAgent bool isInitialised(); - APPD_SDK_STATUS_CODE init( - APPD_SDK_ENV_RECORD* env, + OTEL_SDK_STATUS_CODE init( + OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords); - APPD_SDK_STATUS_CODE term(); + OTEL_SDK_STATUS_CODE term(); - APPD_SDK_STATUS_CODE startRequest( + OTEL_SDK_STATUS_CODE startRequest( const char* wscontext, RequestPayload* payload, - APPD_SDK_HANDLE_REQ* reqHandle); + OTEL_SDK_HANDLE_REQ* reqHandle); - APPD_SDK_STATUS_CODE endRequest( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_STATUS_CODE endRequest( + OTEL_SDK_HANDLE_REQ reqHandle, const char* error, const ResponsePayload* payload = nullptr ); - APPD_SDK_STATUS_CODE startInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_STATUS_CODE startInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, std::unordered_map& propagationHeaders); - APPD_SDK_STATUS_CODE endInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_STATUS_CODE endInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, bool ignoreBackend, EndInteractionPayload *payload); /** - * Add webserver context to AppDynamics configuration for multi-tenancy. + * Add webserver context to OpenTelemetry configuration for multi-tenancy. * * @param contextName * A unique identifier to refer to the context by * @param contextConfig - * AppDynamics context configuration object + * OpenTelemetry context configuration object */ - APPD_SDK_API int addWSContextToCore( + OTEL_SDK_API int addWSContextToCore( const char* wscontext, WSContextConfig* contextConfig); @@ -92,10 +92,10 @@ class WSAgent unsigned long long initPid; std::mutex initMutex; - APPD_SDK_STATUS_CODE checkPID(); + OTEL_SDK_STATUS_CODE checkPID(); void initialisePid(); - APPD_SDK_STATUS_CODE validateAndInitialise(); - APPD_SDK_STATUS_CODE readConfig(APPD_SDK_ENV_RECORD* env, + OTEL_SDK_STATUS_CODE validateAndInitialise(); + OTEL_SDK_STATUS_CODE readConfig(OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, std::shared_ptr tenantConfig, std::shared_ptr spanNamer); diff --git a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h index 00010b837..7a47ec41b 100644 --- a/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h +++ b/instrumentation/otel-webserver-module/include/core/api/opentelemetry_ngx_api.h @@ -74,11 +74,11 @@ struct cNode{ void initDependency(); void populatePayload(request_payload* req_payload, void* payload); void setRequestResponseHeaders(const char* request, const char* response); -APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN); -APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle); -APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int* ix); -APPD_SDK_STATUS_CODE stopModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg); -APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg, response_payload* payload); +OTEL_SDK_STATUS_CODE opentelemetry_core_init(OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN); +OTEL_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, OTEL_SDK_HANDLE_REQ* reqHandle); +OTEL_SDK_STATUS_CODE startModuleInteraction(OTEL_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, OTEL_SDK_ENV_RECORD* propagationHeaders, int* ix); +OTEL_SDK_STATUS_CODE stopModuleInteraction(OTEL_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg); +OTEL_SDK_STATUS_CODE endRequest(OTEL_SDK_HANDLE_REQ req_handle_key, const char* errMsg, response_payload* payload); #ifdef __cplusplus } diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h index 21645173e..0a88bfbcb 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/IScopedSpan.h @@ -23,7 +23,7 @@ #include -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -51,7 +51,7 @@ class IScopedSpan { } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h index 3d58baeb9..65622ceec 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkHelperFactory.h @@ -23,7 +23,7 @@ #include "opentelemetry/trace/tracer.h" #include "opentelemetry/context/propagation/text_map_propagator.h" -namespace appd { +namespace otel { namespace core { using OtelTracer = opentelemetry::nostd::shared_ptr; @@ -41,6 +41,6 @@ class ISdkHelperFactory { } // sdkwrapper } // core -} // appd +} // otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h index 4438cea8d..c1e53c756 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h @@ -23,7 +23,7 @@ #include "sdkwrapper/IScopedSpan.h" #include "api/TenantConfig.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -45,7 +45,7 @@ class ISdkWrapper { } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h index 3b95378c7..b4a1d9357 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ScopedSpan.h @@ -25,7 +25,7 @@ #include #include "AgentLogger.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -59,6 +59,6 @@ class ScopedSpan : public IScopedSpan { } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h index 3f236e8cf..99cc237d9 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h @@ -15,7 +15,7 @@ */ #pragma once -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -50,4 +50,4 @@ constexpr unsigned int kStatusCodeInit = 0; } // sdkwrapper } // core -} // appd +} // otel diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h index 339693887..bbfab3c32 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkEnums.h @@ -16,7 +16,7 @@ #pragma once -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -34,4 +34,4 @@ enum class SpanKind { } // sdkwrapper } // core -} // appd +} // otel diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h index 7561d0950..ab7153144 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkHelperFactory.h @@ -33,7 +33,7 @@ #include "sdkwrapper/ISdkWrapper.h" #include "AgentLogger.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -71,6 +71,6 @@ class SdkHelperFactory: public ISdkHelperFactory { } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h index 92bb186d2..a9c662288 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkUtils.h @@ -21,7 +21,7 @@ #include #include -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -55,6 +55,6 @@ class OtelCarrier : public opentelemetry::context::propagation::TextMapCarrier } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h index 93196c2b0..a8f5d5dcf 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h @@ -22,7 +22,7 @@ #include "AgentLogger.h" #include -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -51,6 +51,6 @@ class SdkWrapper : public ISdkWrapper{ } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h index 338cc3b8c..7b2dbb3c0 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ServerSpan.h @@ -25,7 +25,7 @@ #include #include "AgentLogger.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -62,6 +62,6 @@ class ServerSpan : public IScopedSpan { } //sdkwrapper } //core -} //appd +} //otel #endif diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp index 0e7d2fbe2..1f22cb2ab 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp @@ -44,7 +44,7 @@ std::unordered_map > ApacheConfig const char* ApacheConfigHandlers::helperChar( cmd_parms* cmd, - appd_cfg* cfg, + otel_cfg* cfg, const char* arg, const char*& var, int& initialized, @@ -58,7 +58,7 @@ const char* ApacheConfigHandlers::helperChar( const char* ApacheConfigHandlers::helperInt( cmd_parms* cmd, - appd_cfg* cfg, + otel_cfg* cfg, const char* arg, int& var, int& initialized, @@ -70,7 +70,7 @@ const char* ApacheConfigHandlers::helperInt( return NULL; } -void ApacheConfigHandlers::insertWebserverContext(cmd_parms* cmd, const appd_cfg* cfg) +void ApacheConfigHandlers::insertWebserverContext(cmd_parms* cmd, const otel_cfg* cfg) { std::string contextName = computeContextName(cfg); if (contextName.empty()) @@ -105,68 +105,68 @@ void ApacheConfigHandlers::insertWebserverContext(cmd_parms* cmd, const appd_cfg cfg->serviceNamespace, cfg->serviceName, cfg->serviceInstanceId); } -// int appdEnabled; -// int appdEnabled_initialized; -const char* ApacheConfigHandlers::appd_set_enabled(cmd_parms *cmd, void *conf, const char *arg) +// int otelEnabled; +// int otelEnabled_initialized; +const char* ApacheConfigHandlers::otel_set_enabled(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperInt(cmd, cfg, arg, cfg->appdEnabled, cfg->appdEnabled_initialized, "appd_set_enabled"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperInt(cmd, cfg, arg, cfg->otelEnabled, cfg->otelEnabled_initialized, "otel_set_enabled"); } // char *otelExporterEndpoint; // int otelExporterEndpoint_initialized; -const char* ApacheConfigHandlers::appd_set_otelExporterEndpoint(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelExporterEndpoint(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelExporterEndpoint, cfg->otelExporterEndpoint_initialized, "appd_set_otelExporterEndpoint"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelExporterEndpoint, cfg->otelExporterEndpoint_initialized, "otel_set_otelExporterEndpoint"); } // char *otelSslEnabled; // int otelSslEnabled_initialized; -const char* ApacheConfigHandlers::appd_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperInt(cmd, cfg, arg, cfg->otelSslEnabled, cfg->otelSslEnabled_initialized, "appd_set_otelSslEnabled"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperInt(cmd, cfg, arg, cfg->otelSslEnabled, cfg->otelSslEnabled_initialized, "otel_set_otelSslEnabled"); } // char *otelSslCertificatePath; // int otelSslCertificatePath_initialized; -const char* ApacheConfigHandlers::appd_set_otelSslCertificatePath(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelSslCertificatePath(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelSslCertificatePath, cfg->otelSslCertificatePath_initialized, "appd_set_otelSslCertificatePath"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelSslCertificatePath, cfg->otelSslCertificatePath_initialized, "otel_set_otelSslCertificatePath"); } // char *otelExporterType; // int otelExporterType_initialized; -const char* ApacheConfigHandlers::appd_set_otelExporterType(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelExporterType(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelExporterType, cfg->otelExporterType_initialized, "appd_set_otelExporterType"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelExporterType, cfg->otelExporterType_initialized, "otel_set_otelExporterType"); } // char *otelProcessorType; // int otelProcessorType_initialized; -const char* ApacheConfigHandlers::appd_set_otelProcessorType(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelProcessorType(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelProcessorType, cfg->otelProcessorType_initialized, "appd_set_otelProcessorType"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelProcessorType, cfg->otelProcessorType_initialized, "otel_set_otelProcessorType"); } // char *otelSamplerType; // int otelSamplerType_initialized; -const char* ApacheConfigHandlers::appd_set_otelSamplerType(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelSamplerType(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelSamplerType, cfg->otelSamplerType_initialized, "appd_set_otelSamplerType"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelSamplerType, cfg->otelSamplerType_initialized, "otel_set_otelSamplerType"); } // char *serviceNamespace; // int serviceNamespace_initialized; -const char* ApacheConfigHandlers::appd_set_serviceNamespace(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_serviceNamespace(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - const char* rc = helperChar(cmd, cfg, arg, cfg->serviceNamespace, cfg->serviceNamespace_initialized, "appd_set_serviceNamespace"); + otel_cfg* cfg = (otel_cfg*) conf; + const char* rc = helperChar(cmd, cfg, arg, cfg->serviceNamespace, cfg->serviceNamespace_initialized, "otel_set_serviceNamespace"); if (cfg->serviceNamespace_initialized && cfg->serviceName_initialized && cfg->serviceInstanceId_initialized) { // There are separate Apache directives for setting serviceNamespace, serviceName and serviceInstanceId. @@ -178,10 +178,10 @@ const char* ApacheConfigHandlers::appd_set_serviceNamespace(cmd_parms *cmd, void // char *serviceName; // int serviceName_initialized; -const char* ApacheConfigHandlers::appd_set_serviceName(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_serviceName(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - const char* rc = helperChar(cmd, cfg, arg, cfg->serviceName, cfg->serviceName_initialized, "appd_set_serviceName"); + otel_cfg* cfg = (otel_cfg*) conf; + const char* rc = helperChar(cmd, cfg, arg, cfg->serviceName, cfg->serviceName_initialized, "otel_set_serviceName"); if (cfg->serviceNamespace_initialized && cfg->serviceName_initialized && cfg->serviceInstanceId_initialized) { // There are separate Apache directives for setting serviceNamespace, serviceName and serviceInstanceId. @@ -193,10 +193,10 @@ const char* ApacheConfigHandlers::appd_set_serviceName(cmd_parms *cmd, void *con // char *serviceInstanceId; // int serviceInstanceId_initialized; -const char* ApacheConfigHandlers::appd_set_serviceInstanceId(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_serviceInstanceId(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - const char* rc = helperChar(cmd, cfg, arg, cfg->serviceInstanceId, cfg->serviceInstanceId_initialized, "appd_set_serviceInstanceId"); + otel_cfg* cfg = (otel_cfg*) conf; + const char* rc = helperChar(cmd, cfg, arg, cfg->serviceInstanceId, cfg->serviceInstanceId_initialized, "otel_set_serviceInstanceId"); if (cfg->serviceNamespace_initialized && cfg->serviceName_initialized && cfg->serviceInstanceId_initialized) { // There are separate Apache directives for setting serviceNamespace, serviceName and serviceInstanceId. @@ -208,66 +208,66 @@ const char* ApacheConfigHandlers::appd_set_serviceInstanceId(cmd_parms *cmd, voi // char *otelMaxQueueSize; // int otelMaxQueueSize_initialized; -const char* ApacheConfigHandlers::appd_set_otelMaxQueueSize(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelMaxQueueSize(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelMaxQueueSize, cfg->otelMaxQueueSize_initialized, "appd_set_otelMaxQueueSize"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelMaxQueueSize, cfg->otelMaxQueueSize_initialized, "otel_set_otelMaxQueueSize"); } // char *otelScheduledDelay; // int otelScheduledDelay_initialized; -const char* ApacheConfigHandlers::appd_set_otelScheduledDelay(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelScheduledDelay(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelScheduledDelay, cfg->otelScheduledDelay_initialized, "appd_set_otelScheduledDelay"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelScheduledDelay, cfg->otelScheduledDelay_initialized, "otel_set_otelScheduledDelay"); } // char *otelExportTimeout; // int otelExportTimeout_initialized; -const char* ApacheConfigHandlers::appd_set_otelExportTimeout(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelExportTimeout(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelExportTimeout, cfg->otelExportTimeout_initialized, "appd_set_otelExportTimeout"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelExportTimeout, cfg->otelExportTimeout_initialized, "otel_set_otelExportTimeout"); } // char *otelMaxExportBatchSize; // int otelMaxExportBatchSize_initialized; -const char* ApacheConfigHandlers::appd_set_otelMaxExportBatchSize(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_otelMaxExportBatchSize(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperChar(cmd, cfg, arg, cfg->otelMaxExportBatchSize, cfg->otelMaxExportBatchSize_initialized, "appd_set_otelMaxExportBatchSize"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelMaxExportBatchSize, cfg->otelMaxExportBatchSize_initialized, "otel_set_otelMaxExportBatchSize"); } // int resolveBackends; // int resolveBackends_initialized; -const char* ApacheConfigHandlers::appd_set_resolveBackends(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_resolveBackends(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - return helperInt(cmd, cfg, arg, cfg->resolveBackends, cfg->resolveBackends_initialized, "appd_set_resolveBackends"); + otel_cfg* cfg = (otel_cfg*) conf; + return helperInt(cmd, cfg, arg, cfg->resolveBackends, cfg->resolveBackends_initialized, "otel_set_resolveBackends"); } // int traceAsError; // int traceAsError_initialized; -const char* ApacheConfigHandlers::appd_set_traceAsError(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_traceAsError(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperInt(cmd, cfg, arg, cfg->traceAsError, cfg->traceAsError_initialized, "appd_set_traceAsError"); + otel_cfg* cfg = (otel_cfg*) conf; + helperInt(cmd, cfg, arg, cfg->traceAsError, cfg->traceAsError_initialized, "otel_set_traceAsError"); ApacheTracing::m_traceAsErrorFromUser = cfg->traceAsError; return NULL; } // int reportAllInstrumentedModules; // int reportAllInstrumentedModules_initialized; -const char* ApacheConfigHandlers::appd_set_reportAllInstrumentedModules(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_reportAllInstrumentedModules(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; + otel_cfg* cfg = (otel_cfg*) conf; helperInt( cmd, cfg, arg, cfg->reportAllInstrumentedModules, cfg->reportAllInstrumentedModules_initialized, - "appd_set_reportAllInstrumentedModules"); + "otel_set_reportAllInstrumentedModules"); ApacheHooks::m_reportAllStages = cfg->reportAllInstrumentedModules; return NULL; } @@ -276,39 +276,39 @@ const char* ApacheConfigHandlers::appd_set_reportAllInstrumentedModules(cmd_parm // int maskCookie // int maskCookie_intialized -const char* ApacheConfigHandlers::appd_set_maskCookie(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_maskCookie(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperInt(cmd, cfg, arg, cfg->maskCookie, cfg->maskCookie_initialized, "appd_set_maskCookie"); + otel_cfg* cfg = (otel_cfg*) conf; + helperInt(cmd, cfg, arg, cfg->maskCookie, cfg->maskCookie_initialized, "otel_set_maskCookie"); // ApacheHooks::m_maskCookie = cfg->maskCookie; return NULL; } // char *cookiePattern // int cookiePattern_initialized -const char* ApacheConfigHandlers::appd_set_cookiePattern(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_cookiePattern(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->cookiePattern, cfg->cookiePattern_initialized, "appd_set_cookiePattern"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->cookiePattern, cfg->cookiePattern_initialized, "otel_set_cookiePattern"); // ApacheHooks::m_cookiePattern = cfg->cookiePattern; return NULL; } // int maskSmUser // int maskSmUser_intialized -const char* ApacheConfigHandlers::appd_set_maskSmUser(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_maskSmUser(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperInt(cmd, cfg, arg, cfg->maskSmUser, cfg->maskSmUser_initialized, "appd_set_maskSmUser"); + otel_cfg* cfg = (otel_cfg*) conf; + helperInt(cmd, cfg, arg, cfg->maskSmUser, cfg->maskSmUser_initialized, "otel_set_maskSmUser"); // ApacheHooks::m_maskSmUser = cfg->maskSmUser; return NULL; } // char *delimiter // int delimiter_initialized -const char* ApacheConfigHandlers::appd_set_delimiter(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_delimiter(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->delimiter, cfg->delimiter_initialized, "appd_set_delimiter"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->delimiter, cfg->delimiter_initialized, "otel_set_delimiter"); // UrlFilterManager::m_delimiter = cfg->delimiter; if (cfg->delimiter_initialized && cfg->segment_initialized && cfg->matchFilter_initialized && cfg->matchPattern_initialized) { @@ -320,10 +320,10 @@ const char* ApacheConfigHandlers::appd_set_delimiter(cmd_parms *cmd, void *conf, // char *segment // int segment_initialized -const char* ApacheConfigHandlers::appd_set_segment(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_segment(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->segment, cfg->segment_initialized, "appd_set_segment"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->segment, cfg->segment_initialized, "otel_set_segment"); // UrlFilterManager::m_segment = cfg->segment; if (cfg->delimiter_initialized && cfg->segment_initialized && cfg->matchFilter_initialized && cfg->matchPattern_initialized) { @@ -335,10 +335,10 @@ const char* ApacheConfigHandlers::appd_set_segment(cmd_parms *cmd, void *conf, c // char *matchFilter // int matchFilter_initialized -const char* ApacheConfigHandlers::appd_set_matchFilter(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_matchFilter(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->matchFilter, cfg->matchFilter_initialized, "appd_set_matchFilter"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->matchFilter, cfg->matchFilter_initialized, "otel_set_matchFilter"); // UrlFilterManager::m_matchFilter = cfg->matchFilter; if (cfg->delimiter_initialized && cfg->segment_initialized && cfg->matchFilter_initialized && cfg->matchPattern_initialized) { @@ -350,10 +350,10 @@ const char* ApacheConfigHandlers::appd_set_matchFilter(cmd_parms *cmd, void *con // char *matchPattern // int matchPattern_initialized -const char* ApacheConfigHandlers::appd_set_matchPattern(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_matchPattern(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->matchPattern, cfg->matchPattern_initialized, "appd_set_matchPattern"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->matchPattern, cfg->matchPattern_initialized, "otel_set_matchPattern"); // UrlFilterManager::m_matchPattern = cfg->matchPattern; if (cfg->delimiter_initialized && cfg->segment_initialized && cfg->matchFilter_initialized && cfg->matchPattern_initialized) { @@ -365,10 +365,10 @@ const char* ApacheConfigHandlers::appd_set_matchPattern(cmd_parms *cmd, void *co // char *segmentType // int segmentType_initialized -const char* ApacheConfigHandlers::appd_set_segmentType(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_segmentType(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->segmentType, cfg->segmentType_initialized, "appd_set_segmentType"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->segmentType, cfg->segmentType_initialized, "otel_set_segmentType"); if (cfg->segmentType_initialized && cfg->segmentParameter_initialized) { @@ -378,10 +378,10 @@ const char* ApacheConfigHandlers::appd_set_segmentType(cmd_parms *cmd, void *con // char *segmentParameter // int segmentParameter_initialized -const char* ApacheConfigHandlers::appd_set_segmentParameter(cmd_parms *cmd, void *conf, const char *arg) +const char* ApacheConfigHandlers::otel_set_segmentParameter(cmd_parms *cmd, void *conf, const char *arg) { - appd_cfg* cfg = (appd_cfg*) conf; - helperChar(cmd, cfg, arg, cfg->segmentParameter, cfg->segmentParameter_initialized, "appd_set_segmentParameter"); + otel_cfg* cfg = (otel_cfg*) conf; + helperChar(cmd, cfg, arg, cfg->segmentParameter, cfg->segmentParameter_initialized, "otel_set_segmentParameter"); if (cfg->segmentType_initialized && cfg->segmentParameter_initialized) { @@ -389,7 +389,7 @@ const char* ApacheConfigHandlers::appd_set_segmentParameter(cmd_parms *cmd, void return NULL; } -std::string ApacheConfigHandlers::computeContextName(const appd_cfg* cfg) +std::string ApacheConfigHandlers::computeContextName(const otel_cfg* cfg) { if (!cfg->serviceNamespace_initialized || !cfg->serviceName_initialized || !cfg->serviceInstanceId_initialized) { @@ -401,14 +401,14 @@ std::string ApacheConfigHandlers::computeContextName(const appd_cfg* cfg) return oss.str(); } -const char* ApacheConfigHandlers::appd_add_webserver_context( +const char* ApacheConfigHandlers::otel_add_webserver_context( cmd_parms* cmd, void* conf, const char* serviceNamespace, const char* serviceName, const char* serviceInstanceId) { - appd_cfg* cfg = (appd_cfg*) conf; + otel_cfg* cfg = (otel_cfg*) conf; cfg->serviceNamespace = apr_pstrdup(cmd->pool, serviceNamespace); cfg->serviceNamespace_initialized = 1; @@ -421,14 +421,14 @@ const char* ApacheConfigHandlers::appd_add_webserver_context( return NULL; } -void appd_cfg::init() +void otel_cfg::init() { // Agent to Controller Connection Configuration - // appdEnabled OPTIONAL: 0 for false, 1 for true (defaults to true) - appdEnabled = 1; - appdEnabled_initialized = 0; + // otelEnabled OPTIONAL: 0 for false, 1 for true (defaults to true) + otelEnabled = 1; + otelEnabled_initialized = 0; - // otelExporterEndpoint REQUIRED: AppDynamics endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces + // otelExporterEndpoint REQUIRED: Collecter endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces otelExporterEndpoint = ""; otelExporterEndpoint_initialized = 0; @@ -452,11 +452,11 @@ void appd_cfg::init() otelSamplerType = "ALWAYSON"; otelSamplerType_initialized = 0; - // serviceNamespace REQUIRED: A namespace for the AppdServiceName; equivalent to your AppDynamics application name + // serviceNamespace REQUIRED: A namespace for the ServiceName; serviceNamespace = ""; serviceNamespace_initialized = 0; - // serviceName REQUIRED: Logical name of the service; equivalent to your AppDynamics tier name + // serviceName REQUIRED: Logical name of the service; serviceName = ""; serviceName_initialized = 0; @@ -529,49 +529,49 @@ void appd_cfg::init() segmentParameter_initialized = 0; } -bool appd_cfg::validate(const request_rec *r) +bool otel_cfg::validate(const request_rec *r) { bool config_valid = true; // Agent to Controller Connection Configuration - // appdEnabled - should be either 1 or 0 - if ((appdEnabled != 0) && (appdEnabled != 1)) + // otelEnabled - should be either 1 or 0 + if ((otelEnabled != 0) && (otelEnabled != 1)) { - ApacheTracing::writeError(r->server, __func__, "Enabled flag is invalid - appd not enabled"); + ApacheTracing::writeError(r->server, __func__, "Enabled flag is invalid - otel not enabled"); config_valid = false; } // otelExporterEndpoint - must be non empty if (strlen(otelExporterEndpoint) < 1) { - ApacheTracing::writeError(r->server, __func__, "Otel Exporter Endpoint not specified - appd not enabled"); + ApacheTracing::writeError(r->server, __func__, "Otel Exporter Endpoint not specified - otel not enabled"); config_valid = false; } if ((otelSslEnabled != 0) && strlen(otelSslCertificatePath) < 1) { - ApacheTracing::writeError(r->server, __func__, "Otel Exporter Certificate Path not specified - appd not enabled"); + ApacheTracing::writeError(r->server, __func__, "Otel Exporter Certificate Path not specified - otel not enabled"); config_valid = false; } // serviceNamespace - must be specified if (strlen(serviceNamespace) < 1) { - ApacheTracing::writeError(r->server, __func__, "Service Namespace not specified - appd not enabled"); + ApacheTracing::writeError(r->server, __func__, "Service Namespace not specified - otel not enabled"); config_valid = false; } // serviceName - must be non empty if (strlen(serviceName) < 1) { - ApacheTracing::writeError(r->server, __func__, "Service name not specified - appd not enabled"); + ApacheTracing::writeError(r->server, __func__, "Service name not specified - otel not enabled"); config_valid = false; } // serviceInstanceId - must be non empty if (strlen(serviceInstanceId) < 1) { - ApacheTracing::writeError(r->server, __func__, "Service Instance ID not specified - appd not enabled"); + ApacheTracing::writeError(r->server, __func__, "Service Instance ID not specified - otel not enabled"); config_valid = false; } @@ -588,12 +588,12 @@ bool appd_cfg::validate(const request_rec *r) // // The return value is a pointer to the created module-specific // structure. -void* ApacheConfigHandlers::appd_create_dir_config(apr_pool_t* p, char* dirspec) +void* ApacheConfigHandlers::otel_create_dir_config(apr_pool_t* p, char* dirspec) { const char* dname = (dirspec != NULL) ? dirspec : ""; // Allocate the space for our record from the pool supplied. - appd_cfg* cfg = (appd_cfg*) apr_pcalloc(p, sizeof(appd_cfg)); + otel_cfg* cfg = (otel_cfg*) apr_pcalloc(p, sizeof(otel_cfg)); if (cfg) // Set Default values on creation { cfg->init(); // Set Default values on creation @@ -618,19 +618,19 @@ void* ApacheConfigHandlers::appd_create_dir_config(apr_pool_t* p, char* dirspec) // // The return value is a pointer to the created module-specific structure // containing the merged values. -void* ApacheConfigHandlers::appd_merge_dir_config(apr_pool_t* p, void* parent_conf, void* newloc_conf) +void* ApacheConfigHandlers::otel_merge_dir_config(apr_pool_t* p, void* parent_conf, void* newloc_conf) { - // the "(char*)" is to remove the compiler warning, look at appd_create_dir_config for more explanation - appd_cfg* merged_config = (appd_cfg*) appd_create_dir_config(p, (char*)"Merged Directory Configuration"); - appd_cfg* pconf = (appd_cfg*) parent_conf; - appd_cfg* nconf = (appd_cfg*) newloc_conf; + // the "(char*)" is to remove the compiler warning, look at otel_create_dir_config for more explanation + otel_cfg* merged_config = (otel_cfg*) otel_create_dir_config(p, (char*)"Merged Directory Configuration"); + otel_cfg* pconf = (otel_cfg*) parent_conf; + otel_cfg* nconf = (otel_cfg*) newloc_conf; // Agent to Controller Connection Configuration - // appdEnabled OPTIONAL: 0 for false, 1 for true (defaults to false) - merged_config->appdEnabled = nconf->appdEnabled_initialized ? nconf->appdEnabled : pconf->appdEnabled; - merged_config->appdEnabled_initialized = 1; + // otelEnabled OPTIONAL: 0 for false, 1 for true (defaults to false) + merged_config->otelEnabled = nconf->otelEnabled_initialized ? nconf->otelEnabled : pconf->otelEnabled; + merged_config->otelEnabled_initialized = 1; - // otelExporterEndpoint REQUIRED: AppDynamics endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces + // otelExporterEndpoint REQUIRED: Collector endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces merged_config->otelExporterEndpoint = nconf->otelExporterEndpoint_initialized ? apr_pstrdup(p, nconf->otelExporterEndpoint) : apr_pstrdup(p, pconf->otelExporterEndpoint); merged_config->otelExporterEndpoint_initialized = 1; @@ -660,12 +660,12 @@ void* ApacheConfigHandlers::appd_merge_dir_config(apr_pool_t* p, void* parent_co apr_pstrdup(p, nconf->otelSamplerType) : apr_pstrdup(p, pconf->otelSamplerType); merged_config->otelSamplerType_initialized = 1; - // serviceNamespace REQUIRED: A namespace for the AppdServiceName; equivalent to your AppDynamics application name + // serviceNamespace REQUIRED: A namespace for the ServiceName; merged_config->serviceNamespace = nconf->serviceNamespace_initialized ? apr_pstrdup(p, nconf->serviceNamespace) : apr_pstrdup(p, pconf->serviceNamespace); merged_config->serviceNamespace_initialized = 1; - // serviceName REQUIRED: Logical name of the service; equivalent to your AppDynamics tier name + // serviceName REQUIRED: Logical name of the service; merged_config->serviceName = nconf->serviceName_initialized ? apr_pstrdup(p, nconf->serviceName) : apr_pstrdup(p, pconf->serviceName); merged_config->serviceName_initialized = 1; @@ -743,9 +743,9 @@ void* ApacheConfigHandlers::appd_merge_dir_config(apr_pool_t* p, void* parent_co return static_cast(merged_config); } -appd_cfg* ApacheConfigHandlers::getConfig(const request_rec* r) +otel_cfg* ApacheConfigHandlers::getConfig(const request_rec* r) { - appd_cfg* cfg = ApacheConfigHandlers::our_dconfig(r); + otel_cfg* cfg = ApacheConfigHandlers::our_dconfig(r); if (cfg && cfg->validate(r)) { @@ -758,15 +758,15 @@ appd_cfg* ApacheConfigHandlers::getConfig(const request_rec* r) /* Function to set user data/config in the process pool */ -appd_cfg* ApacheConfigHandlers::getProcessConfig(const request_rec* r) +otel_cfg* ApacheConfigHandlers::getProcessConfig(const request_rec* r) { - appd_cfg* our_config = ApacheConfigHandlers::getConfig(r); + otel_cfg* our_config = ApacheConfigHandlers::getConfig(r); - appd_cfg *process_cfg; - process_cfg = (appd_cfg *) apr_pcalloc(r->server->process->pool, sizeof(appd_cfg)); + otel_cfg *process_cfg; + process_cfg = (otel_cfg *) apr_pcalloc(r->server->process->pool, sizeof(otel_cfg)); - process_cfg->appdEnabled = our_config->appdEnabled; - process_cfg->appdEnabled_initialized = our_config->appdEnabled_initialized; + process_cfg->otelEnabled = our_config->otelEnabled; + process_cfg->otelEnabled_initialized = our_config->otelEnabled_initialized; process_cfg->otelExporterEndpoint = apr_pstrdup(r->server->process->pool, our_config->otelExporterEndpoint); process_cfg->otelExporterEndpoint_initialized = our_config->otelExporterEndpoint_initialized; @@ -837,7 +837,7 @@ std::string ApacheConfigHandlers::hashPassword(const char* arg) /* Function to log config. */ -void ApacheConfigHandlers::traceConfig(const request_rec* r, const appd_cfg* cfg) +void ApacheConfigHandlers::traceConfig(const request_rec* r, const otel_cfg* cfg) { ApacheTracing::writeTrace(r->server, __func__, "config{" @@ -863,7 +863,7 @@ void ApacheConfigHandlers::traceConfig(const request_rec* r, const appd_cfg* cfg "(SegmentType=\"%s\")" "(SegmentParameter=\"%s\")" "}", - cfg->appdEnabled, + cfg->otelEnabled, cfg->otelExporterEndpoint, cfg->otelSslEnabled, cfg->otelSslCertificatePath, diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index da69c69bf..346795a43 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -43,21 +43,21 @@ const std::initializer_list ApacheHooks::httpHeaders = { "traceparent", "tracestate" }; -const char* ApacheHooks::APPD_CONFIG_KEY = "appd_configuration"; -const char* ApacheHooks::APPD_CORRELATION_HEADER_KEY = "singularityheader"; -const char* ApacheHooks::APPD_INTERACTION_HANDLE_KEY = "appd_interaction_handle_key"; -const char* ApacheHooks::APPD_REQ_HANDLE_KEY = "appd_req_handle_key"; -const char* APPD_OUTPUT_FILTER_NAME = "APPD_EUM_AUTOINJECT"; +const char* ApacheHooks::OTEL_CONFIG_KEY = "otel_configuration"; +const char* ApacheHooks::OTEL_CORRELATION_HEADER_KEY = "singularityheader"; +const char* ApacheHooks::OTEL_INTERACTION_HANDLE_KEY = "otel_interaction_handle_key"; +const char* ApacheHooks::OTEL_REQ_HANDLE_KEY = "otel_req_handle_key"; +const char* OTEL_OUTPUT_FILTER_NAME = "OTEL_EUM_AUTOINJECT"; -appd::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic +otel::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic -using namespace appd::core::sdkwrapper; +using namespace otel::core::sdkwrapper; void ApacheHooks::registerHooks(apr_pool_t *p) { // Place a hook that executes when a child process is spawned // (commonly used for initializing modules after the server has forked) - ap_hook_child_init(appd_child_init, NULL, NULL, APR_HOOK_MIDDLE); + ap_hook_child_init(otel_child_init, NULL, NULL, APR_HOOK_MIDDLE); //------------------------------------------------------------------------------ // The -2 and +2 below is a trick to ensure that our hooks are before and after @@ -67,25 +67,25 @@ void ApacheHooks::registerHooks(apr_pool_t *p) //------------------------------------------------------------------------------ // request_begin and request_end hooks - ap_hook_header_parser(ApacheHooks::appd_hook_header_parser_begin, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_log_transaction(ApacheHooks::appd_hook_log_transaction_end, NULL, NULL, APR_HOOK_REALLY_LAST + 2); + ap_hook_header_parser(ApacheHooks::otel_hook_header_parser_begin, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_log_transaction(ApacheHooks::otel_hook_log_transaction_end, NULL, NULL, APR_HOOK_REALLY_LAST + 2); // Register the output filter after the response resource is generated (AP_FTYPE_CONTENT_SET). - // The filter gets added into the chain in appd_hook_interaction_end_insert_filter via ap_hook_insert_filter. - ap_register_output_filter(APPD_OUTPUT_FILTER_NAME, ApacheHooks::appd_output_filter, NULL, AP_FTYPE_CONTENT_SET); - ap_hook_insert_filter(ApacheHooks::appd_hook_interaction_end_insert_filter, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + // The filter gets added into the chain in otel_hook_interaction_end_insert_filter via ap_hook_insert_filter. + ap_register_output_filter(OTEL_OUTPUT_FILTER_NAME, ApacheHooks::otel_output_filter, NULL, AP_FTYPE_CONTENT_SET); + ap_hook_insert_filter(ApacheHooks::otel_hook_interaction_end_insert_filter, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); // TODO: For the time being put in a hook at the very beginning of every stage we are instrumenting. This is a // catch all to stop a interaction. We can be smarter and only put it in when we know that there is a // module we care about for a previous stage. This means we need to know the deterministic stage order. - ap_hook_quick_handler(ApacheHooks::appd_hook_interaction_end_quick_handler, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_access_checker(ApacheHooks::appd_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_check_user_id(ApacheHooks::appd_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_auth_checker(ApacheHooks::appd_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_type_checker(ApacheHooks::appd_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_fixups(ApacheHooks::appd_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_handler(ApacheHooks::appd_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); - ap_hook_log_transaction(ApacheHooks::appd_hook_interaction_end_log_transaction, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_quick_handler(ApacheHooks::otel_hook_interaction_end_quick_handler, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_access_checker(ApacheHooks::otel_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_check_user_id(ApacheHooks::otel_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_auth_checker(ApacheHooks::otel_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_type_checker(ApacheHooks::otel_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_fixups(ApacheHooks::otel_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_handler(ApacheHooks::otel_hook_interaction_end, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); + ap_hook_log_transaction(ApacheHooks::otel_hook_interaction_end_log_transaction, NULL, NULL, APR_HOOK_REALLY_FIRST - 2); // Stage Hooks // TODO: Decide among the following stages at what all we need the modules to be instrumented, @@ -94,85 +94,85 @@ void ApacheHooks::registerHooks(apr_pool_t *p) p, ap_hook_get_header_parser, ap_hook_header_parser, - ApacheHooksForStage::appd_header_parser_hooks, - ApacheHooksForStage::appd_header_parser_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_header_parser_hooks, + ApacheHooksForStage::otel_header_parser_indexes, + ApacheHooks::otel_hook_interaction_end, "header_parser"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_quick_handler, ap_hook_quick_handler, - ApacheHooksForStage::appd_quick_handler_hooks, - ApacheHooksForStage::appd_quick_handler_indexes, - ApacheHooks::appd_hook_interaction_end_quick_handler, + ApacheHooksForStage::otel_quick_handler_hooks, + ApacheHooksForStage::otel_quick_handler_indexes, + ApacheHooks::otel_hook_interaction_end_quick_handler, "quick_handler"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_access_checker, ap_hook_access_checker, - ApacheHooksForStage::appd_access_checker_hooks, - ApacheHooksForStage::appd_access_checker_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_access_checker_hooks, + ApacheHooksForStage::otel_access_checker_indexes, + ApacheHooks::otel_hook_interaction_end, "access_checker"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_check_user_id, ap_hook_check_user_id, - ApacheHooksForStage::appd_check_user_id_hooks, - ApacheHooksForStage::appd_check_user_id_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_check_user_id_hooks, + ApacheHooksForStage::otel_check_user_id_indexes, + ApacheHooks::otel_hook_interaction_end, "check_user_id"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_auth_checker, ap_hook_auth_checker, - ApacheHooksForStage::appd_auth_checker_hooks, - ApacheHooksForStage::appd_auth_checker_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_auth_checker_hooks, + ApacheHooksForStage::otel_auth_checker_indexes, + ApacheHooks::otel_hook_interaction_end, "auth_checker"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_type_checker, ap_hook_type_checker, - ApacheHooksForStage::appd_type_checker_hooks, - ApacheHooksForStage::appd_type_checker_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_type_checker_hooks, + ApacheHooksForStage::otel_type_checker_indexes, + ApacheHooks::otel_hook_interaction_end, "type_checker"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_fixups, ap_hook_fixups, - ApacheHooksForStage::appd_fixups_hooks, - ApacheHooksForStage::appd_fixups_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_fixups_hooks, + ApacheHooksForStage::otel_fixups_indexes, + ApacheHooks::otel_hook_interaction_end, "fixups"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_insert_filter, ap_hook_insert_filter, - ApacheHooksForStage::appd_insert_filter_hooks, - ApacheHooksForStage::appd_insert_filter_indexes, - ApacheHooks::appd_hook_interaction_end_insert_filter, + ApacheHooksForStage::otel_insert_filter_hooks, + ApacheHooksForStage::otel_insert_filter_indexes, + ApacheHooks::otel_hook_interaction_end_insert_filter, "insert_filter"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_handler, ap_hook_handler, - ApacheHooksForStage::appd_handler_hooks, - ApacheHooksForStage::appd_handler_indexes, - ApacheHooks::appd_hook_interaction_end_handler, + ApacheHooksForStage::otel_handler_hooks, + ApacheHooksForStage::otel_handler_indexes, + ApacheHooks::otel_hook_interaction_end_handler, "handler"); ApacheHooksForStage::insertHooksForStage( p, ap_hook_get_log_transaction, ap_hook_log_transaction, - ApacheHooksForStage::appd_log_transaction_hooks, - ApacheHooksForStage::appd_log_transaction_indexes, - ApacheHooks::appd_hook_interaction_end, + ApacheHooksForStage::otel_log_transaction_hooks, + ApacheHooksForStage::otel_log_transaction_indexes, + ApacheHooks::otel_hook_interaction_end, "log_transaction"); } -apr_status_t ApacheHooks::appd_output_filter(ap_filter_t* f, apr_bucket_brigade* bb) +apr_status_t ApacheHooks::otel_output_filter(ap_filter_t* f, apr_bucket_brigade* bb) { if (APR_BRIGADE_EMPTY(bb)) { @@ -191,13 +191,13 @@ apr_status_t ApacheHooks::appd_output_filter(ap_filter_t* f, apr_bucket_brigade* } // end the interaction -void ApacheHooks::appd_stopInteraction(request_rec *r, bool isAlwaysRunStage, bool ignoreBackend) +void ApacheHooks::otel_stopInteraction(request_rec *r, bool isAlwaysRunStage, bool ignoreBackend) { if ((!isAlwaysRunStage && !m_reportAllStages) || !r || !r->notes || !ap_is_initial_req(r)) { return; } - APPD_SDK_HANDLE_REQ reqHandlePtr = (APPD_SDK_HANDLE_REQ)apr_table_get(r->notes, APPD_REQ_HANDLE_KEY); + OTEL_SDK_HANDLE_REQ reqHandlePtr = (OTEL_SDK_HANDLE_REQ)apr_table_get(r->notes, OTEL_REQ_HANDLE_KEY); if (reqHandlePtr) { // TODO: Work on backend naming and type @@ -206,16 +206,16 @@ void ApacheHooks::appd_stopInteraction(request_rec *r, bool isAlwaysRunStage, bo long errorCode = r->status; std::ostringstream oss(""); - if (appd_requestHasErrors(r)) + if (otel_requestHasErrors(r)) { oss << "HTTP ERROR CODE:" << r->status; } - std::unique_ptr payload(new - appd::core::EndInteractionPayload(backendName, backendType, errorCode, oss.str())); - APPD_SDK_STATUS_CODE res = wsAgent.endInteraction(reqHandlePtr, ignoreBackend, payload.get()); + std::unique_ptr payload(new + otel::core::EndInteractionPayload(backendName, backendType, errorCode, oss.str())); + OTEL_SDK_STATUS_CODE res = wsAgent.endInteraction(reqHandlePtr, ignoreBackend, payload.get()); - if (APPD_ISFAIL(res)) + if (OTEL_ISFAIL(res)) { ApacheTracing::writeTrace(r->server, __func__, "result code: %d", res); } @@ -224,16 +224,16 @@ void ApacheHooks::appd_stopInteraction(request_rec *r, bool isAlwaysRunStage, bo // stop endpoint interaction if one currently is running // begin the new interaction -APPD_SDK_STATUS_CODE ApacheHooks::appd_startInteraction( +OTEL_SDK_STATUS_CODE ApacheHooks::otel_startInteraction( request_rec* r, - HookContainer::appd_endpoint_indexes endpointIndex, + HookContainer::otel_endpoint_indexes endpointIndex, bool isAlwaysRunStage, bool ignoreBackend) { /* Retrieve the stage and module name from endpointIndex and start an interaction to module. */ - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; if ((!isAlwaysRunStage && !m_reportAllStages) || !r || !r->notes || !ap_is_initial_req(r)) { return res; @@ -242,33 +242,33 @@ APPD_SDK_STATUS_CODE ApacheHooks::appd_startInteraction( const std::string& stage = HookContainer::getInstance().getStage(endpointIndex); const std::string& module = HookContainer::getInstance().getModule(endpointIndex); - APPD_SDK_HANDLE_REQ reqHandlePtr = (APPD_SDK_HANDLE_REQ)apr_table_get(r->notes, APPD_REQ_HANDLE_KEY); + OTEL_SDK_HANDLE_REQ reqHandlePtr = (OTEL_SDK_HANDLE_REQ)apr_table_get(r->notes, OTEL_REQ_HANDLE_KEY); if (reqHandlePtr) { // In case a previous "end hook" is never called. End current interaction before starting new one - appd_stopInteraction(r, isAlwaysRunStage, ignoreBackend); + otel_stopInteraction(r, isAlwaysRunStage, ignoreBackend); bool resolveBackends = false; - appd_cfg* cfg = ApacheConfigHandlers::getConfig(r); + otel_cfg* cfg = ApacheConfigHandlers::getConfig(r); if (cfg) { resolveBackends = cfg->getResolveBackends(); } - std::unique_ptr payload(new - appd::core::InteractionPayload(module, stage, resolveBackends)); + std::unique_ptr payload(new + otel::core::InteractionPayload(module, stage, resolveBackends)); // Create propagationHeaders to be populated in startInteraction. std::unordered_map propagationHeaders; res = wsAgent.startInteraction(reqHandlePtr, payload.get(), propagationHeaders); - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { // remove the singularity header if any - apr_table_unset(r->headers_in, APPD_CORRELATION_HEADER_KEY); + apr_table_unset(r->headers_in, OTEL_CORRELATION_HEADER_KEY); if (!propagationHeaders.empty()) { - appd_payload_decorator(r, propagationHeaders); + otel_payload_decorator(r, propagationHeaders); } else { @@ -290,7 +290,7 @@ APPD_SDK_STATUS_CODE ApacheHooks::appd_startInteraction( // Used for following purposes: // 1) adding the correlation for this backend request to the headers //----------------------------------------------------------------------------------------- -void ApacheHooks::appd_payload_decorator(request_rec* request, std::unordered_map propagationHeaders) +void ApacheHooks::otel_payload_decorator(request_rec* request, std::unordered_map propagationHeaders) { for (auto itr = propagationHeaders.begin(); itr != propagationHeaders.end(); itr++) { @@ -305,11 +305,11 @@ void ApacheHooks::appd_payload_decorator(request_rec* request, std::unordered_ma } // Utility routine for initializing the SDK based on configuration parameters -bool ApacheHooks::initialize_appdynamics(const request_rec *r) +bool ApacheHooks::initialize_opentelemetry(const request_rec *r) { // check to see if we have already been initialized by getting user data from the process pool void* config_data = NULL; - apr_pool_userdata_get(&config_data, APPD_CONFIG_KEY, r->server->process->pool); + apr_pool_userdata_get(&config_data, OTEL_CONFIG_KEY, r->server->process->pool); if (config_data != NULL) { @@ -321,7 +321,7 @@ bool ApacheHooks::initialize_appdynamics(const request_rec *r) // try to initialize and store a config in the process memory pool ApacheTracing::writeTrace(r->server, __func__, "no config stored in the process memory pool"); - appd_cfg* our_config = ApacheConfigHandlers::getConfig(r); + otel_cfg* our_config = ApacheConfigHandlers::getConfig(r); if (our_config == NULL) { ApacheTracing::writeTrace(r->server, __func__, "config was NULL"); @@ -331,97 +331,97 @@ bool ApacheHooks::initialize_appdynamics(const request_rec *r) ApacheConfigHandlers::traceConfig(r, our_config); // Check to see if the agent is enabled - if (our_config->getAppdEnabled() == 1) + if (our_config->getOtelEnabled() == 1) { // Intialize the SDK with our configuration information - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; wsAgent.initDependency(); // ENV RECORDS SIZE TO INCLUDE THE LOG PATH AND THE AGGREGATOR DIRECTORY // // Update the apr_pcalloc if we add another parameter to the input array! - APPD_SDK_ENV_RECORD* env_config = - (APPD_SDK_ENV_RECORD*) apr_pcalloc(r->pool, 16 * sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env_config = + (OTEL_SDK_ENV_RECORD*) apr_pcalloc(r->pool, 16 * sizeof(OTEL_SDK_ENV_RECORD)); int ix = 0; // Otel Exporter Type - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_TYPE; env_config[ix].value = our_config->getOtelExporterType(); ++ix; // Otel Exporter Endpoint - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT; env_config[ix].value = our_config->getOtelExporterEndpoint(); ++ix; // Otel SSL Enabled - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_ENABLED; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = our_config->getOtelSslEnabled() == 1 ? "1" : "0"; ++ix; // Otel Certificate Path - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; env_config[ix].value = our_config->getOtelSslCertificatePath(); ++ix; // sdk libaray name - env_config[ix].name = APPD_SDK_ENV_OTEL_LIBRARY_NAME; + env_config[ix].name = OTEL_SDK_ENV_OTEL_LIBRARY_NAME; env_config[ix].value = "Apache"; ++ix; // Otel Processor Type - env_config[ix].name = APPD_SDK_ENV_OTEL_PROCESSOR_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE; env_config[ix].value = our_config->getOtelProcessorType(); ++ix; // Otel Sampler Type - env_config[ix].name = APPD_SDK_ENV_OTEL_SAMPLER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SAMPLER_TYPE; env_config[ix].value = our_config->getOtelSamplerType(); ++ix; // Service Namespace - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAMESPACE; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAMESPACE; env_config[ix].value = our_config->getServiceNamespace(); ++ix; // Service Name - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAME; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAME; env_config[ix].value = our_config->getServiceName(); ++ix; // Service Instance ID - env_config[ix].name = APPD_SDK_ENV_SERVICE_INSTANCE_ID; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_INSTANCE_ID; env_config[ix].value = our_config->getServiceInstanceId(); ++ix; // Otel Max Queue Size - env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; + env_config[ix].name = OTEL_SDK_ENV_MAX_QUEUE_SIZE; env_config[ix].value = our_config->getOtelMaxQueueSize(); ++ix; // Otel Scheduled Delay - env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; + env_config[ix].name = OTEL_SDK_ENV_SCHEDULED_DELAY; env_config[ix].value = our_config->getOtelScheduledDelay(); ++ix; // Otel Max Export Batch Size - env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_BATCH_SIZE; env_config[ix].value = our_config->getOtelMaxExportBatchSize(); ++ix; // Otel Export Timeout - env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_TIMEOUT; env_config[ix].value = our_config->getOtelExportTimeout(); ++ix; // Segment Type - env_config[ix].name = APPD_SDK_ENV_SEGMENT_TYPE; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_TYPE; env_config[ix].value = our_config->getSegmentType(); ++ix; // Segment Parameter - env_config[ix].name = APPD_SDK_ENV_SEGMENT_PARAMETER; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_PARAMETER; env_config[ix].value = our_config->getSegmentParameter(); ++ix; @@ -431,7 +431,7 @@ bool ApacheHooks::initialize_appdynamics(const request_rec *r) for (auto it = ApacheConfigHandlers::m_webServerContexts.begin(); it != ApacheConfigHandlers::m_webServerContexts.end(); ++it) { - appd::core::WSContextConfig cfg; + otel::core::WSContextConfig cfg; cfg.serviceNamespace = it->second->m_serviceNamespace; cfg.serviceName = it->second->m_serviceName; cfg.serviceInstanceId = it->second->m_serviceInstanceId; @@ -445,13 +445,13 @@ bool ApacheHooks::initialize_appdynamics(const request_rec *r) } res = wsAgent.init(env_config, ix); - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { ApacheTracing::writeTrace(r->server, __func__, "initializing SDK succceeded"); // Store the config that was selected for all other methods to be able to use - appd_cfg* process_cfg = ApacheConfigHandlers::getProcessConfig(r); - apr_pool_userdata_set((const void *)process_cfg, APPD_CONFIG_KEY, apr_pool_cleanup_null, r->server->process->pool); + otel_cfg* process_cfg = ApacheConfigHandlers::getProcessConfig(r); + apr_pool_userdata_set((const void *)process_cfg, OTEL_CONFIG_KEY, apr_pool_cleanup_null, r->server->process->pool); return true; } @@ -469,12 +469,12 @@ bool ApacheHooks::initialize_appdynamics(const request_rec *r) return false; } -bool ApacheHooks::appd_requestHasErrors(request_rec* r) +bool ApacheHooks::otel_requestHasErrors(request_rec* r) { return r->status >= LOWEST_HTTP_ERROR_CODE; } -void fillRequestPayload(request_rec* request, appd::core::RequestPayload* payload) +void fillRequestPayload(request_rec* request, otel::core::RequestPayload* payload) { const char* val; @@ -565,15 +565,15 @@ void fillRequestPayload(request_rec* request, appd::core::RequestPayload* payloa // directory configuration. // // This is a RUN_ALL hook. -int ApacheHooks::appd_hook_header_parser_begin(request_rec *r) +int ApacheHooks::otel_hook_header_parser_begin(request_rec *r) { if (!ap_is_initial_req(r)) { return DECLINED; } - else if (!initialize_appdynamics(r)) + else if (!initialize_opentelemetry(r)) { - ApacheTracing::writeTrace(r->server, __func__, "appdynamics did not get initialized"); + ApacheTracing::writeTrace(r->server, __func__, "opentelemetry did not get initialized"); return DECLINED; } @@ -581,11 +581,11 @@ int ApacheHooks::appd_hook_header_parser_begin(request_rec *r) HookContainer::getInstance().traceHooks(r); - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; - APPD_SDK_HANDLE_REQ reqHandle = APPD_SDK_NO_HANDLE; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; + OTEL_SDK_HANDLE_REQ reqHandle = OTEL_SDK_NO_HANDLE; const char* wscontext = NULL; - appd_cfg* cfg = ApacheConfigHandlers::getConfig(r); + otel_cfg* cfg = ApacheConfigHandlers::getConfig(r); std::string tmpContextName; if (cfg) @@ -601,27 +601,27 @@ int ApacheHooks::appd_hook_header_parser_begin(request_rec *r) ApacheTracing::writeTrace(r->server, __func__, "%s", (wscontext ? wscontext : "using default context")); // Fill the Request payload information - std::unique_ptr requestPayload(new appd::core::RequestPayload); + std::unique_ptr requestPayload(new otel::core::RequestPayload); fillRequestPayload(r, requestPayload.get()); // Start Request res = wsAgent.startRequest(wscontext, requestPayload.get(), &reqHandle); // Store the request data into pool - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { // Store the Request Handle on the request object - APPD_SDK_HANDLE_REQ reqHandleValue = (APPD_SDK_HANDLE_REQ)apr_palloc(r->pool, sizeof(APPD_SDK_HANDLE_REQ)); + OTEL_SDK_HANDLE_REQ reqHandleValue = (OTEL_SDK_HANDLE_REQ)apr_palloc(r->pool, sizeof(OTEL_SDK_HANDLE_REQ)); if (reqHandleValue) { reqHandleValue = reqHandle; - apr_table_setn(r->notes, APPD_REQ_HANDLE_KEY, (const char*)reqHandleValue); + apr_table_setn(r->notes, OTEL_REQ_HANDLE_KEY, (const char*)reqHandleValue); } ApacheTracing::writeTrace(r->server, __func__, "request begin successful"); } - else if (res == APPD_STATUS(cfg_channel_uninitialized) || res == APPD_STATUS(bt_detection_disabled)) + else if (res == OTEL_STATUS(cfg_channel_uninitialized) || res == OTEL_STATUS(bt_detection_disabled)) { ApacheTracing::writeTrace(r->server, __func__, "request begin detection disabled, result code: %d", res); } @@ -633,7 +633,7 @@ int ApacheHooks::appd_hook_header_parser_begin(request_rec *r) return DECLINED; } -int ApacheHooks::appd_hook_log_transaction_end(request_rec* r) +int ApacheHooks::otel_hook_log_transaction_end(request_rec* r) { /* End the request and report the associated metrics. @@ -646,37 +646,37 @@ int ApacheHooks::appd_hook_log_transaction_end(request_rec* r) // TODO - Determine whether there were any errors from any other part of this request processing (even prior to our handler) - appd_cfg* cfg = NULL; - apr_pool_userdata_get((void**)&cfg, APPD_CONFIG_KEY, r->server->process->pool); + otel_cfg* cfg = NULL; + apr_pool_userdata_get((void**)&cfg, OTEL_CONFIG_KEY, r->server->process->pool); if (!cfg) { ApacheTracing::writeTrace(r->server, __func__, "configuration is NULL"); return DECLINED; } - else if (!cfg->getAppdEnabled()) + else if (!cfg->getOtelEnabled()) { ApacheTracing::writeError(r->server, __func__, "agent is disabled"); return DECLINED; } - appd_stopInteraction(r); + otel_stopInteraction(r); - APPD_SDK_HANDLE_REQ reqHandle = (APPD_SDK_HANDLE_REQ) apr_table_get(r->notes, APPD_REQ_HANDLE_KEY); + OTEL_SDK_HANDLE_REQ reqHandle = (OTEL_SDK_HANDLE_REQ) apr_table_get(r->notes, OTEL_REQ_HANDLE_KEY); if (!reqHandle) { return DECLINED; } - apr_table_unset(r->notes, APPD_REQ_HANDLE_KEY); + apr_table_unset(r->notes, OTEL_REQ_HANDLE_KEY); - APPD_SDK_STATUS_CODE res; - std::unique_ptr responsePayload - (new appd::core::ResponsePayload); + OTEL_SDK_STATUS_CODE res; + std::unique_ptr responsePayload + (new otel::core::ResponsePayload); responsePayload->status_code = r->status; - if (appd_requestHasErrors(r)) + if (otel_requestHasErrors(r)) { std::ostringstream oss; oss << r->status; @@ -689,7 +689,7 @@ int ApacheHooks::appd_hook_log_transaction_end(request_rec* r) reqHandle, NULL, responsePayload.get()); } - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { ApacheTracing::writeTrace(r->server, __func__, "request end successful (HTTP status=%d)", r->status); } @@ -710,7 +710,7 @@ int ApacheHooks::appd_hook_log_transaction_end(request_rec* r) // declaration near the bottom of this file.) Note that these may be // called for situations that don't relate primarily to our function - in // other words, the fixup handler shouldn't assume that the request has -// to do with "appdynamics" stuff. +// to do with "opentelemetry" stuff. // // With the exception of the content handler, all of our routines will be // called for each request, unless an earlier handler from another module @@ -737,14 +737,14 @@ int ApacheHooks::appd_hook_log_transaction_end(request_rec* r) // any, are noted with each routine. //-------------------------------------------------------------------------- -apr_status_t ApacheHooks::appd_child_exit(void* data) +apr_status_t ApacheHooks::otel_child_exit(void* data) { server_rec* s = static_cast(data); const char* sname = (s->server_hostname ? s->server_hostname : ""); void* retdata; - apr_pool_userdata_get(&retdata, APPD_CONFIG_KEY, s->process->pool); - appd_cfg* our_config = static_cast(retdata); + apr_pool_userdata_get(&retdata, OTEL_CONFIG_KEY, s->process->pool); + otel_cfg* our_config = static_cast(retdata); if (our_config) { @@ -755,314 +755,314 @@ apr_status_t ApacheHooks::appd_child_exit(void* data) return APR_SUCCESS; } -void ApacheHooks::appd_child_init(apr_pool_t* p, server_rec* s) +void ApacheHooks::otel_child_init(apr_pool_t* p, server_rec* s) { ApacheTracing::logStartupTrace(s); - apr_pool_cleanup_register(p, s, appd_child_exit, appd_child_exit); + apr_pool_cleanup_register(p, s, otel_child_exit, otel_child_exit); } // Stage Hooks -int ApacheHooksForStage::appd_hook_header_parser1(request_rec* r) +int ApacheHooksForStage::otel_hook_header_parser1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HEADER_PARSER1); + HookContainer::OTEL_ENDPOINT_HEADER_PARSER1); return DECLINED; } -int ApacheHooksForStage::appd_hook_header_parser2(request_rec* r) +int ApacheHooksForStage::otel_hook_header_parser2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HEADER_PARSER2); + HookContainer::OTEL_ENDPOINT_HEADER_PARSER2); return DECLINED; } -int ApacheHooksForStage::appd_hook_header_parser3(request_rec* r) +int ApacheHooksForStage::otel_hook_header_parser3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HEADER_PARSER3); + HookContainer::OTEL_ENDPOINT_HEADER_PARSER3); return DECLINED; } -int ApacheHooksForStage::appd_hook_header_parser4(request_rec* r) +int ApacheHooksForStage::otel_hook_header_parser4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HEADER_PARSER4); + HookContainer::OTEL_ENDPOINT_HEADER_PARSER4); return DECLINED; } -int ApacheHooksForStage::appd_hook_header_parser5(request_rec* r) +int ApacheHooksForStage::otel_hook_header_parser5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HEADER_PARSER5); + HookContainer::OTEL_ENDPOINT_HEADER_PARSER5); return DECLINED; } -int ApacheHooksForStage::appd_hook_quick_handler1(request_rec* r, int i) +int ApacheHooksForStage::otel_hook_quick_handler1(request_rec* r, int i) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_QUICK_HANDLER1); + HookContainer::OTEL_ENDPOINT_QUICK_HANDLER1); return DECLINED; } -int ApacheHooksForStage::appd_hook_quick_handler2(request_rec* r, int i) +int ApacheHooksForStage::otel_hook_quick_handler2(request_rec* r, int i) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_QUICK_HANDLER2); + HookContainer::OTEL_ENDPOINT_QUICK_HANDLER2); return DECLINED; } -int ApacheHooksForStage::appd_hook_quick_handler3(request_rec* r, int i) +int ApacheHooksForStage::otel_hook_quick_handler3(request_rec* r, int i) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_QUICK_HANDLER3); + HookContainer::OTEL_ENDPOINT_QUICK_HANDLER3); return DECLINED; } -int ApacheHooksForStage::appd_hook_quick_handler4(request_rec* r, int i) +int ApacheHooksForStage::otel_hook_quick_handler4(request_rec* r, int i) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_QUICK_HANDLER4); + HookContainer::OTEL_ENDPOINT_QUICK_HANDLER4); return DECLINED; } -int ApacheHooksForStage::appd_hook_quick_handler5(request_rec* r, int i) +int ApacheHooksForStage::otel_hook_quick_handler5(request_rec* r, int i) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_QUICK_HANDLER5); + HookContainer::OTEL_ENDPOINT_QUICK_HANDLER5); return DECLINED; } -int ApacheHooksForStage::appd_hook_access_checker1(request_rec* r) +int ApacheHooksForStage::otel_hook_access_checker1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_ACCESS_CHECKER1); + HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER1); return DECLINED; } -int ApacheHooksForStage::appd_hook_access_checker2(request_rec* r) +int ApacheHooksForStage::otel_hook_access_checker2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_ACCESS_CHECKER2); + HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER2); return DECLINED; } -int ApacheHooksForStage::appd_hook_access_checker3(request_rec* r) +int ApacheHooksForStage::otel_hook_access_checker3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_ACCESS_CHECKER3); + HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER3); return DECLINED; } -int ApacheHooksForStage::appd_hook_access_checker4(request_rec* r) +int ApacheHooksForStage::otel_hook_access_checker4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_ACCESS_CHECKER4); + HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER4); return DECLINED; } -int ApacheHooksForStage::appd_hook_access_checker5(request_rec* r) +int ApacheHooksForStage::otel_hook_access_checker5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_ACCESS_CHECKER5); + HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER5); return DECLINED; } -int ApacheHooksForStage::appd_hook_check_user_id1(request_rec* r) +int ApacheHooksForStage::otel_hook_check_user_id1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_CHECK_USER_ID1); + HookContainer::OTEL_ENDPOINT_CHECK_USER_ID1); return DECLINED; } -int ApacheHooksForStage::appd_hook_check_user_id2(request_rec* r) +int ApacheHooksForStage::otel_hook_check_user_id2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_CHECK_USER_ID2); + HookContainer::OTEL_ENDPOINT_CHECK_USER_ID2); return DECLINED; } -int ApacheHooksForStage::appd_hook_check_user_id3(request_rec* r) +int ApacheHooksForStage::otel_hook_check_user_id3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_CHECK_USER_ID3); + HookContainer::OTEL_ENDPOINT_CHECK_USER_ID3); return DECLINED; } -int ApacheHooksForStage::appd_hook_check_user_id4(request_rec* r) +int ApacheHooksForStage::otel_hook_check_user_id4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_CHECK_USER_ID4); + HookContainer::OTEL_ENDPOINT_CHECK_USER_ID4); return DECLINED; } -int ApacheHooksForStage::appd_hook_check_user_id5(request_rec* r) +int ApacheHooksForStage::otel_hook_check_user_id5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_CHECK_USER_ID5); + HookContainer::OTEL_ENDPOINT_CHECK_USER_ID5); return DECLINED; } -int ApacheHooksForStage::appd_hook_auth_checker1(request_rec* r) +int ApacheHooksForStage::otel_hook_auth_checker1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_AUTH_CHECKER1); + HookContainer::OTEL_ENDPOINT_AUTH_CHECKER1); return DECLINED; } -int ApacheHooksForStage::appd_hook_auth_checker2(request_rec* r) +int ApacheHooksForStage::otel_hook_auth_checker2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_AUTH_CHECKER2); + HookContainer::OTEL_ENDPOINT_AUTH_CHECKER2); return DECLINED; } -int ApacheHooksForStage::appd_hook_auth_checker3(request_rec* r) +int ApacheHooksForStage::otel_hook_auth_checker3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_AUTH_CHECKER3); + HookContainer::OTEL_ENDPOINT_AUTH_CHECKER3); return DECLINED; } -int ApacheHooksForStage::appd_hook_auth_checker4(request_rec* r) +int ApacheHooksForStage::otel_hook_auth_checker4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_AUTH_CHECKER4); + HookContainer::OTEL_ENDPOINT_AUTH_CHECKER4); return DECLINED; } -int ApacheHooksForStage::appd_hook_auth_checker5(request_rec* r) +int ApacheHooksForStage::otel_hook_auth_checker5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_AUTH_CHECKER5); + HookContainer::OTEL_ENDPOINT_AUTH_CHECKER5); return DECLINED; } -int ApacheHooksForStage::appd_hook_type_checker1(request_rec* r) +int ApacheHooksForStage::otel_hook_type_checker1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_TYPE_CHECKER1); + HookContainer::OTEL_ENDPOINT_TYPE_CHECKER1); return DECLINED; } -int ApacheHooksForStage::appd_hook_type_checker2(request_rec* r) +int ApacheHooksForStage::otel_hook_type_checker2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_TYPE_CHECKER2); + HookContainer::OTEL_ENDPOINT_TYPE_CHECKER2); return DECLINED; } -int ApacheHooksForStage::appd_hook_type_checker3(request_rec* r) +int ApacheHooksForStage::otel_hook_type_checker3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_TYPE_CHECKER3); + HookContainer::OTEL_ENDPOINT_TYPE_CHECKER3); return DECLINED; } -int ApacheHooksForStage::appd_hook_type_checker4(request_rec* r) +int ApacheHooksForStage::otel_hook_type_checker4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_TYPE_CHECKER4); + HookContainer::OTEL_ENDPOINT_TYPE_CHECKER4); return DECLINED; } -int ApacheHooksForStage::appd_hook_type_checker5(request_rec* r) +int ApacheHooksForStage::otel_hook_type_checker5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_TYPE_CHECKER5); + HookContainer::OTEL_ENDPOINT_TYPE_CHECKER5); return DECLINED; } -int ApacheHooksForStage::appd_hook_fixups1(request_rec* r) +int ApacheHooksForStage::otel_hook_fixups1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_FIXUPS1); + HookContainer::OTEL_ENDPOINT_FIXUPS1); return DECLINED; } -int ApacheHooksForStage::appd_hook_fixups2(request_rec* r) +int ApacheHooksForStage::otel_hook_fixups2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_FIXUPS2); + HookContainer::OTEL_ENDPOINT_FIXUPS2); return DECLINED; } -int ApacheHooksForStage::appd_hook_fixups3(request_rec* r) +int ApacheHooksForStage::otel_hook_fixups3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_FIXUPS3); + HookContainer::OTEL_ENDPOINT_FIXUPS3); return DECLINED; } -int ApacheHooksForStage::appd_hook_fixups4(request_rec* r) +int ApacheHooksForStage::otel_hook_fixups4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_FIXUPS4); + HookContainer::OTEL_ENDPOINT_FIXUPS4); return DECLINED; } -int ApacheHooksForStage::appd_hook_fixups5(request_rec* r) +int ApacheHooksForStage::otel_hook_fixups5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_FIXUPS5); + HookContainer::OTEL_ENDPOINT_FIXUPS5); return DECLINED; } -void ApacheHooksForStage::appd_hook_insert_filter1(request_rec* r) +void ApacheHooksForStage::otel_hook_insert_filter1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_INSERT_FILTER1); + HookContainer::OTEL_ENDPOINT_INSERT_FILTER1); } -void ApacheHooksForStage::appd_hook_insert_filter2(request_rec* r) +void ApacheHooksForStage::otel_hook_insert_filter2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_INSERT_FILTER2); + HookContainer::OTEL_ENDPOINT_INSERT_FILTER2); } -void ApacheHooksForStage::appd_hook_insert_filter3(request_rec* r) +void ApacheHooksForStage::otel_hook_insert_filter3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_INSERT_FILTER3); + HookContainer::OTEL_ENDPOINT_INSERT_FILTER3); } -void ApacheHooksForStage::appd_hook_insert_filter4(request_rec* r) +void ApacheHooksForStage::otel_hook_insert_filter4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_INSERT_FILTER4); + HookContainer::OTEL_ENDPOINT_INSERT_FILTER4); } -void ApacheHooksForStage::appd_hook_insert_filter5(request_rec* r) +void ApacheHooksForStage::otel_hook_insert_filter5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_INSERT_FILTER5); + HookContainer::OTEL_ENDPOINT_INSERT_FILTER5); } // The HANDLER stage does not always run all the hooks. After a hook returns "OK", the stage @@ -1071,248 +1071,248 @@ void ApacheHooksForStage::appd_hook_insert_filter5(request_rec* r) // we ignore that backend call in the SDK. // // ASSUMPTION: if a module returns DECLINED, it does not go out to another tier. -int ApacheHooksForStage::appd_hook_handler1(request_rec* r) +int ApacheHooksForStage::otel_hook_handler1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER1, + HookContainer::OTEL_ENDPOINT_HANDLER1, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler2(request_rec* r) +int ApacheHooksForStage::otel_hook_handler2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER2, + HookContainer::OTEL_ENDPOINT_HANDLER2, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler3(request_rec* r) +int ApacheHooksForStage::otel_hook_handler3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER3, + HookContainer::OTEL_ENDPOINT_HANDLER3, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler4(request_rec* r) +int ApacheHooksForStage::otel_hook_handler4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER4, + HookContainer::OTEL_ENDPOINT_HANDLER4, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler5(request_rec* r) +int ApacheHooksForStage::otel_hook_handler5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER5, + HookContainer::OTEL_ENDPOINT_HANDLER5, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler6(request_rec* r) +int ApacheHooksForStage::otel_hook_handler6(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER6, + HookContainer::OTEL_ENDPOINT_HANDLER6, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler7(request_rec* r) +int ApacheHooksForStage::otel_hook_handler7(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER7, + HookContainer::OTEL_ENDPOINT_HANDLER7, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler8(request_rec* r) +int ApacheHooksForStage::otel_hook_handler8(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER8, + HookContainer::OTEL_ENDPOINT_HANDLER8, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler9(request_rec* r) +int ApacheHooksForStage::otel_hook_handler9(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER9, + HookContainer::OTEL_ENDPOINT_HANDLER9, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler10(request_rec* r) +int ApacheHooksForStage::otel_hook_handler10(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER10, + HookContainer::OTEL_ENDPOINT_HANDLER10, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler11(request_rec* r) +int ApacheHooksForStage::otel_hook_handler11(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER11, + HookContainer::OTEL_ENDPOINT_HANDLER11, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler12(request_rec* r) +int ApacheHooksForStage::otel_hook_handler12(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER12, + HookContainer::OTEL_ENDPOINT_HANDLER12, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler13(request_rec* r) +int ApacheHooksForStage::otel_hook_handler13(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER13, + HookContainer::OTEL_ENDPOINT_HANDLER13, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler14(request_rec* r) +int ApacheHooksForStage::otel_hook_handler14(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER14, + HookContainer::OTEL_ENDPOINT_HANDLER14, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler15(request_rec* r) +int ApacheHooksForStage::otel_hook_handler15(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER15, + HookContainer::OTEL_ENDPOINT_HANDLER15, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler16(request_rec* r) +int ApacheHooksForStage::otel_hook_handler16(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER16, + HookContainer::OTEL_ENDPOINT_HANDLER16, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler17(request_rec* r) +int ApacheHooksForStage::otel_hook_handler17(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER17, + HookContainer::OTEL_ENDPOINT_HANDLER17, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler18(request_rec* r) +int ApacheHooksForStage::otel_hook_handler18(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER18, + HookContainer::OTEL_ENDPOINT_HANDLER18, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler19(request_rec* r) +int ApacheHooksForStage::otel_hook_handler19(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER19, + HookContainer::OTEL_ENDPOINT_HANDLER19, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_handler20(request_rec* r) +int ApacheHooksForStage::otel_hook_handler20(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_HANDLER20, + HookContainer::OTEL_ENDPOINT_HANDLER20, true, // always run true); // ignore backend if one exists return DECLINED; } -int ApacheHooksForStage::appd_hook_log_transaction1(request_rec* r) +int ApacheHooksForStage::otel_hook_log_transaction1(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_LOG_TRANSACTION1); + HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION1); return DECLINED; } -int ApacheHooksForStage::appd_hook_log_transaction2(request_rec* r) +int ApacheHooksForStage::otel_hook_log_transaction2(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_LOG_TRANSACTION2); + HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION2); return DECLINED; } -int ApacheHooksForStage::appd_hook_log_transaction3(request_rec* r) +int ApacheHooksForStage::otel_hook_log_transaction3(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_LOG_TRANSACTION3); + HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION3); return DECLINED; } -int ApacheHooksForStage::appd_hook_log_transaction4(request_rec* r) +int ApacheHooksForStage::otel_hook_log_transaction4(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_LOG_TRANSACTION4); + HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION4); return DECLINED; } -int ApacheHooksForStage::appd_hook_log_transaction5(request_rec* r) +int ApacheHooksForStage::otel_hook_log_transaction5(request_rec* r) { - ApacheHooks::appd_startInteraction( + ApacheHooks::otel_startInteraction( r, - HookContainer::APPD_ENDPOINT_LOG_TRANSACTION5); + HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION5); return DECLINED; } // These hooks are for stopping interactions after a module -int ApacheHooks::appd_hook_interaction_end(request_rec *r) +int ApacheHooks::otel_hook_interaction_end(request_rec *r) { - appd_stopInteraction(r); + otel_stopInteraction(r); return DECLINED; } @@ -1322,28 +1322,28 @@ int ApacheHooks::appd_hook_interaction_end(request_rec *r) // we ignore that endpoint call in the SDK. // // ASSUMPTION: if a module returns DECLINED, it does not go out to another tier. -int ApacheHooks::appd_hook_interaction_end_handler(request_rec *r) +int ApacheHooks::otel_hook_interaction_end_handler(request_rec *r) { - appd_stopInteraction(r, true, true); // always run and ignore backend if triggered + otel_stopInteraction(r, true, true); // always run and ignore backend if triggered return DECLINED; } -int ApacheHooks::appd_hook_interaction_end_quick_handler(request_rec *r, int i) +int ApacheHooks::otel_hook_interaction_end_quick_handler(request_rec *r, int i) { - appd_stopInteraction(r); + otel_stopInteraction(r); return DECLINED; } -void ApacheHooks::appd_hook_interaction_end_insert_filter(request_rec *r) +void ApacheHooks::otel_hook_interaction_end_insert_filter(request_rec *r) { // Add our output filter into the chain for this request. - ap_add_output_filter(APPD_OUTPUT_FILTER_NAME, NULL, r, r->connection); - appd_stopInteraction(r); + ap_add_output_filter(OTEL_OUTPUT_FILTER_NAME, NULL, r, r->connection); + otel_stopInteraction(r); } -int ApacheHooks::appd_hook_interaction_end_log_transaction(request_rec *r) +int ApacheHooks::otel_hook_interaction_end_log_transaction(request_rec *r) { - appd_stopInteraction(r, true, false); // always run and do not ignore backends + otel_stopInteraction(r, true, false); // always run and do not ignore backends return DECLINED; } @@ -1353,7 +1353,7 @@ void ApacheHooksForStage::insertHooksForStage( hook_get_t getModules, T setHook, const std::vector &beginHandlers, - const std::vector &indexes, + const std::vector &indexes, S endHandler, const std::string& stage) { @@ -1386,153 +1386,153 @@ void ApacheHooksForStage::insertHooksForStage( } } -const std::vector ApacheHooksForStage::appd_header_parser_hooks = - {appd_hook_header_parser1 - ,appd_hook_header_parser2 - ,appd_hook_header_parser3 - ,appd_hook_header_parser4 - ,appd_hook_header_parser5}; -const std::vector ApacheHooksForStage::appd_header_parser_indexes = - {HookContainer::APPD_ENDPOINT_HEADER_PARSER1 - ,HookContainer::APPD_ENDPOINT_HEADER_PARSER2 - ,HookContainer::APPD_ENDPOINT_HEADER_PARSER3 - ,HookContainer::APPD_ENDPOINT_HEADER_PARSER4 - ,HookContainer::APPD_ENDPOINT_HEADER_PARSER5}; -const std::vector ApacheHooksForStage::appd_quick_handler_hooks = - {appd_hook_quick_handler1 - ,appd_hook_quick_handler2 - ,appd_hook_quick_handler3 - ,appd_hook_quick_handler4 - ,appd_hook_quick_handler5}; -const std::vector ApacheHooksForStage::appd_quick_handler_indexes = - {HookContainer::APPD_ENDPOINT_QUICK_HANDLER1 - ,HookContainer::APPD_ENDPOINT_QUICK_HANDLER2 - ,HookContainer::APPD_ENDPOINT_QUICK_HANDLER3 - ,HookContainer::APPD_ENDPOINT_QUICK_HANDLER4 - ,HookContainer::APPD_ENDPOINT_QUICK_HANDLER5}; -const std::vector ApacheHooksForStage::appd_access_checker_hooks = - {appd_hook_access_checker1 - ,appd_hook_access_checker2 - ,appd_hook_access_checker3 - ,appd_hook_access_checker4 - ,appd_hook_access_checker5}; -const std::vector ApacheHooksForStage::appd_access_checker_indexes = - {HookContainer::APPD_ENDPOINT_ACCESS_CHECKER1 - ,HookContainer::APPD_ENDPOINT_ACCESS_CHECKER2 - ,HookContainer::APPD_ENDPOINT_ACCESS_CHECKER3 - ,HookContainer::APPD_ENDPOINT_ACCESS_CHECKER4 - ,HookContainer::APPD_ENDPOINT_ACCESS_CHECKER5}; -const std::vector ApacheHooksForStage::appd_check_user_id_hooks = - {appd_hook_check_user_id1 - ,appd_hook_check_user_id2 - ,appd_hook_check_user_id3 - ,appd_hook_check_user_id4 - ,appd_hook_check_user_id5}; -const std::vector ApacheHooksForStage::appd_check_user_id_indexes = - {HookContainer::APPD_ENDPOINT_CHECK_USER_ID1 - ,HookContainer::APPD_ENDPOINT_CHECK_USER_ID2 - ,HookContainer::APPD_ENDPOINT_CHECK_USER_ID3 - ,HookContainer::APPD_ENDPOINT_CHECK_USER_ID4 - ,HookContainer::APPD_ENDPOINT_CHECK_USER_ID5}; -const std::vector ApacheHooksForStage::appd_auth_checker_hooks = - {appd_hook_auth_checker1 - ,appd_hook_auth_checker2 - ,appd_hook_auth_checker3 - ,appd_hook_auth_checker4 - ,appd_hook_auth_checker5}; -const std::vector ApacheHooksForStage::appd_auth_checker_indexes = - {HookContainer::APPD_ENDPOINT_AUTH_CHECKER1 - ,HookContainer::APPD_ENDPOINT_AUTH_CHECKER2 - ,HookContainer::APPD_ENDPOINT_AUTH_CHECKER3 - ,HookContainer::APPD_ENDPOINT_AUTH_CHECKER4 - ,HookContainer::APPD_ENDPOINT_AUTH_CHECKER5}; -const std::vector ApacheHooksForStage::appd_type_checker_hooks = - {appd_hook_type_checker1 - ,appd_hook_type_checker2 - ,appd_hook_type_checker3 - ,appd_hook_type_checker4 - ,appd_hook_type_checker5}; -const std::vector ApacheHooksForStage::appd_type_checker_indexes = - {HookContainer::APPD_ENDPOINT_TYPE_CHECKER1 - ,HookContainer::APPD_ENDPOINT_TYPE_CHECKER2 - ,HookContainer::APPD_ENDPOINT_TYPE_CHECKER3 - ,HookContainer::APPD_ENDPOINT_TYPE_CHECKER4 - ,HookContainer::APPD_ENDPOINT_TYPE_CHECKER5}; -const std::vector ApacheHooksForStage::appd_fixups_hooks = - {appd_hook_fixups1 - ,appd_hook_fixups2 - ,appd_hook_fixups3 - ,appd_hook_fixups4 - ,appd_hook_fixups5}; -const std::vector ApacheHooksForStage::appd_fixups_indexes = - {HookContainer::APPD_ENDPOINT_FIXUPS1 - ,HookContainer::APPD_ENDPOINT_FIXUPS2 - ,HookContainer::APPD_ENDPOINT_FIXUPS3 - ,HookContainer::APPD_ENDPOINT_FIXUPS4 - ,HookContainer::APPD_ENDPOINT_FIXUPS5}; -const std::vector ApacheHooksForStage::appd_insert_filter_hooks = - {appd_hook_insert_filter1 - ,appd_hook_insert_filter2 - ,appd_hook_insert_filter3 - ,appd_hook_insert_filter4 - ,appd_hook_insert_filter5}; -const std::vector ApacheHooksForStage::appd_insert_filter_indexes = - {HookContainer::APPD_ENDPOINT_INSERT_FILTER1 - ,HookContainer::APPD_ENDPOINT_INSERT_FILTER2 - ,HookContainer::APPD_ENDPOINT_INSERT_FILTER3 - ,HookContainer::APPD_ENDPOINT_INSERT_FILTER4 - ,HookContainer::APPD_ENDPOINT_INSERT_FILTER5}; -const std::vector ApacheHooksForStage::appd_handler_hooks = - {appd_hook_handler1 - ,appd_hook_handler2 - ,appd_hook_handler3 - ,appd_hook_handler4 - ,appd_hook_handler5 - ,appd_hook_handler6 - ,appd_hook_handler7 - ,appd_hook_handler8 - ,appd_hook_handler9 - ,appd_hook_handler10 - ,appd_hook_handler11 - ,appd_hook_handler12 - ,appd_hook_handler13 - ,appd_hook_handler14 - ,appd_hook_handler15 - ,appd_hook_handler16 - ,appd_hook_handler17 - ,appd_hook_handler18 - ,appd_hook_handler19 - ,appd_hook_handler20}; -const std::vector ApacheHooksForStage::appd_handler_indexes = - {HookContainer::APPD_ENDPOINT_HANDLER1 - ,HookContainer::APPD_ENDPOINT_HANDLER2 - ,HookContainer::APPD_ENDPOINT_HANDLER3 - ,HookContainer::APPD_ENDPOINT_HANDLER4 - ,HookContainer::APPD_ENDPOINT_HANDLER5 - ,HookContainer::APPD_ENDPOINT_HANDLER6 - ,HookContainer::APPD_ENDPOINT_HANDLER7 - ,HookContainer::APPD_ENDPOINT_HANDLER8 - ,HookContainer::APPD_ENDPOINT_HANDLER9 - ,HookContainer::APPD_ENDPOINT_HANDLER10 - ,HookContainer::APPD_ENDPOINT_HANDLER11 - ,HookContainer::APPD_ENDPOINT_HANDLER12 - ,HookContainer::APPD_ENDPOINT_HANDLER13 - ,HookContainer::APPD_ENDPOINT_HANDLER14 - ,HookContainer::APPD_ENDPOINT_HANDLER15 - ,HookContainer::APPD_ENDPOINT_HANDLER16 - ,HookContainer::APPD_ENDPOINT_HANDLER17 - ,HookContainer::APPD_ENDPOINT_HANDLER18 - ,HookContainer::APPD_ENDPOINT_HANDLER19 - ,HookContainer::APPD_ENDPOINT_HANDLER20}; -const std::vector ApacheHooksForStage::appd_log_transaction_hooks = - {appd_hook_log_transaction1 - ,appd_hook_log_transaction2 - ,appd_hook_log_transaction3 - ,appd_hook_log_transaction4 - ,appd_hook_log_transaction5}; -const std::vector ApacheHooksForStage::appd_log_transaction_indexes = - {HookContainer::APPD_ENDPOINT_LOG_TRANSACTION1 - ,HookContainer::APPD_ENDPOINT_LOG_TRANSACTION2 - ,HookContainer::APPD_ENDPOINT_LOG_TRANSACTION3 - ,HookContainer::APPD_ENDPOINT_LOG_TRANSACTION4 - ,HookContainer::APPD_ENDPOINT_LOG_TRANSACTION5}; +const std::vector ApacheHooksForStage::otel_header_parser_hooks = + {otel_hook_header_parser1 + ,otel_hook_header_parser2 + ,otel_hook_header_parser3 + ,otel_hook_header_parser4 + ,otel_hook_header_parser5}; +const std::vector ApacheHooksForStage::otel_header_parser_indexes = + {HookContainer::OTEL_ENDPOINT_HEADER_PARSER1 + ,HookContainer::OTEL_ENDPOINT_HEADER_PARSER2 + ,HookContainer::OTEL_ENDPOINT_HEADER_PARSER3 + ,HookContainer::OTEL_ENDPOINT_HEADER_PARSER4 + ,HookContainer::OTEL_ENDPOINT_HEADER_PARSER5}; +const std::vector ApacheHooksForStage::otel_quick_handler_hooks = + {otel_hook_quick_handler1 + ,otel_hook_quick_handler2 + ,otel_hook_quick_handler3 + ,otel_hook_quick_handler4 + ,otel_hook_quick_handler5}; +const std::vector ApacheHooksForStage::otel_quick_handler_indexes = + {HookContainer::OTEL_ENDPOINT_QUICK_HANDLER1 + ,HookContainer::OTEL_ENDPOINT_QUICK_HANDLER2 + ,HookContainer::OTEL_ENDPOINT_QUICK_HANDLER3 + ,HookContainer::OTEL_ENDPOINT_QUICK_HANDLER4 + ,HookContainer::OTEL_ENDPOINT_QUICK_HANDLER5}; +const std::vector ApacheHooksForStage::otel_access_checker_hooks = + {otel_hook_access_checker1 + ,otel_hook_access_checker2 + ,otel_hook_access_checker3 + ,otel_hook_access_checker4 + ,otel_hook_access_checker5}; +const std::vector ApacheHooksForStage::otel_access_checker_indexes = + {HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER1 + ,HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER2 + ,HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER3 + ,HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER4 + ,HookContainer::OTEL_ENDPOINT_ACCESS_CHECKER5}; +const std::vector ApacheHooksForStage::otel_check_user_id_hooks = + {otel_hook_check_user_id1 + ,otel_hook_check_user_id2 + ,otel_hook_check_user_id3 + ,otel_hook_check_user_id4 + ,otel_hook_check_user_id5}; +const std::vector ApacheHooksForStage::otel_check_user_id_indexes = + {HookContainer::OTEL_ENDPOINT_CHECK_USER_ID1 + ,HookContainer::OTEL_ENDPOINT_CHECK_USER_ID2 + ,HookContainer::OTEL_ENDPOINT_CHECK_USER_ID3 + ,HookContainer::OTEL_ENDPOINT_CHECK_USER_ID4 + ,HookContainer::OTEL_ENDPOINT_CHECK_USER_ID5}; +const std::vector ApacheHooksForStage::otel_auth_checker_hooks = + {otel_hook_auth_checker1 + ,otel_hook_auth_checker2 + ,otel_hook_auth_checker3 + ,otel_hook_auth_checker4 + ,otel_hook_auth_checker5}; +const std::vector ApacheHooksForStage::otel_auth_checker_indexes = + {HookContainer::OTEL_ENDPOINT_AUTH_CHECKER1 + ,HookContainer::OTEL_ENDPOINT_AUTH_CHECKER2 + ,HookContainer::OTEL_ENDPOINT_AUTH_CHECKER3 + ,HookContainer::OTEL_ENDPOINT_AUTH_CHECKER4 + ,HookContainer::OTEL_ENDPOINT_AUTH_CHECKER5}; +const std::vector ApacheHooksForStage::otel_type_checker_hooks = + {otel_hook_type_checker1 + ,otel_hook_type_checker2 + ,otel_hook_type_checker3 + ,otel_hook_type_checker4 + ,otel_hook_type_checker5}; +const std::vector ApacheHooksForStage::otel_type_checker_indexes = + {HookContainer::OTEL_ENDPOINT_TYPE_CHECKER1 + ,HookContainer::OTEL_ENDPOINT_TYPE_CHECKER2 + ,HookContainer::OTEL_ENDPOINT_TYPE_CHECKER3 + ,HookContainer::OTEL_ENDPOINT_TYPE_CHECKER4 + ,HookContainer::OTEL_ENDPOINT_TYPE_CHECKER5}; +const std::vector ApacheHooksForStage::otel_fixups_hooks = + {otel_hook_fixups1 + ,otel_hook_fixups2 + ,otel_hook_fixups3 + ,otel_hook_fixups4 + ,otel_hook_fixups5}; +const std::vector ApacheHooksForStage::otel_fixups_indexes = + {HookContainer::OTEL_ENDPOINT_FIXUPS1 + ,HookContainer::OTEL_ENDPOINT_FIXUPS2 + ,HookContainer::OTEL_ENDPOINT_FIXUPS3 + ,HookContainer::OTEL_ENDPOINT_FIXUPS4 + ,HookContainer::OTEL_ENDPOINT_FIXUPS5}; +const std::vector ApacheHooksForStage::otel_insert_filter_hooks = + {otel_hook_insert_filter1 + ,otel_hook_insert_filter2 + ,otel_hook_insert_filter3 + ,otel_hook_insert_filter4 + ,otel_hook_insert_filter5}; +const std::vector ApacheHooksForStage::otel_insert_filter_indexes = + {HookContainer::OTEL_ENDPOINT_INSERT_FILTER1 + ,HookContainer::OTEL_ENDPOINT_INSERT_FILTER2 + ,HookContainer::OTEL_ENDPOINT_INSERT_FILTER3 + ,HookContainer::OTEL_ENDPOINT_INSERT_FILTER4 + ,HookContainer::OTEL_ENDPOINT_INSERT_FILTER5}; +const std::vector ApacheHooksForStage::otel_handler_hooks = + {otel_hook_handler1 + ,otel_hook_handler2 + ,otel_hook_handler3 + ,otel_hook_handler4 + ,otel_hook_handler5 + ,otel_hook_handler6 + ,otel_hook_handler7 + ,otel_hook_handler8 + ,otel_hook_handler9 + ,otel_hook_handler10 + ,otel_hook_handler11 + ,otel_hook_handler12 + ,otel_hook_handler13 + ,otel_hook_handler14 + ,otel_hook_handler15 + ,otel_hook_handler16 + ,otel_hook_handler17 + ,otel_hook_handler18 + ,otel_hook_handler19 + ,otel_hook_handler20}; +const std::vector ApacheHooksForStage::otel_handler_indexes = + {HookContainer::OTEL_ENDPOINT_HANDLER1 + ,HookContainer::OTEL_ENDPOINT_HANDLER2 + ,HookContainer::OTEL_ENDPOINT_HANDLER3 + ,HookContainer::OTEL_ENDPOINT_HANDLER4 + ,HookContainer::OTEL_ENDPOINT_HANDLER5 + ,HookContainer::OTEL_ENDPOINT_HANDLER6 + ,HookContainer::OTEL_ENDPOINT_HANDLER7 + ,HookContainer::OTEL_ENDPOINT_HANDLER8 + ,HookContainer::OTEL_ENDPOINT_HANDLER9 + ,HookContainer::OTEL_ENDPOINT_HANDLER10 + ,HookContainer::OTEL_ENDPOINT_HANDLER11 + ,HookContainer::OTEL_ENDPOINT_HANDLER12 + ,HookContainer::OTEL_ENDPOINT_HANDLER13 + ,HookContainer::OTEL_ENDPOINT_HANDLER14 + ,HookContainer::OTEL_ENDPOINT_HANDLER15 + ,HookContainer::OTEL_ENDPOINT_HANDLER16 + ,HookContainer::OTEL_ENDPOINT_HANDLER17 + ,HookContainer::OTEL_ENDPOINT_HANDLER18 + ,HookContainer::OTEL_ENDPOINT_HANDLER19 + ,HookContainer::OTEL_ENDPOINT_HANDLER20}; +const std::vector ApacheHooksForStage::otel_log_transaction_hooks = + {otel_hook_log_transaction1 + ,otel_hook_log_transaction2 + ,otel_hook_log_transaction3 + ,otel_hook_log_transaction4 + ,otel_hook_log_transaction5}; +const std::vector ApacheHooksForStage::otel_log_transaction_indexes = + {HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION1 + ,HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION2 + ,HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION3 + ,HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION4 + ,HookContainer::OTEL_ENDPOINT_LOG_TRANSACTION5}; diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h index 72717c54c..ace3e8adf 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h +++ b/instrumentation/otel-webserver-module/src/apache/ApacheTracing.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef APPD_APACHETRACING_H -#define APPD_APACHETRACING_H +#ifndef APACHETRACING_H +#define APACHETRACING_H #include #include diff --git a/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp b/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp index d4c06465e..124ab1bb1 100644 --- a/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp +++ b/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp @@ -30,7 +30,7 @@ HookContainer& HookContainer::getInstance() } void HookContainer::addHook( - appd_endpoint_indexes index, + otel_endpoint_indexes index, const std::string& stage, const std::string& module, int order) @@ -38,21 +38,21 @@ void HookContainer::addHook( hooks.insert(std::pair(index, HookInfo(stage, module, order))); } -const std::string& HookContainer::getStage(appd_endpoint_indexes index) const +const std::string& HookContainer::getStage(otel_endpoint_indexes index) const { static std::string blank; auto it = hooks.find(index); return (it == hooks.end() ? blank : it->second.stage); } -const std::string& HookContainer::getModule(appd_endpoint_indexes index) const +const std::string& HookContainer::getModule(otel_endpoint_indexes index) const { static std::string blank; auto it = hooks.find(index); return (it == hooks.end() ? blank : it->second.module); } -const char* const* HookContainer::getModuleList(appd_endpoint_indexes index) const +const char* const* HookContainer::getModuleList(otel_endpoint_indexes index) const { auto it = hooks.find(index); return (it == hooks.end() ? NULL : it->second.moduleList); diff --git a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp index 3a04bf6da..e27595bff 100644 --- a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp +++ b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp @@ -15,7 +15,7 @@ */ /* - * AppDynamics Agent Module. Module that hooks in to apache at the relevant + * OpenTelemetry Agent Module. Module that hooks in to apache at the relevant * request processing phases to allow apache to appear as an entity in the flow map. * * TODO: Add the description of the BT Logic @@ -44,167 +44,167 @@ // http://wolfgang.groogroo.com/apache-cplusplus/cplusplus/strong_types.html //-------------------------------------------------------------------------- typedef const char *(*CMD_HAND_TYPE) (); -static const command_rec appd_cmds[] = +static const command_rec otel_cmds[] = { AP_INIT_TAKE1( "apacheModuleEnabled", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_enabled, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_enabled, NULL, OR_ALL, "Enable or disable webserver apache module"), AP_INIT_TAKE1( "apacheModuleOtelSpanExporter", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelExporterType, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelExporterType, NULL, OR_ALL, "Type of exporter to be configured in TracerProvider of OTel SDK embedded into Agent"), AP_INIT_TAKE1( "apacheModuleOtelExporterEndpoint", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelExporterEndpoint, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelExporterEndpoint, NULL, OR_ALL, - "AppDynamics endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces"), + "Collector Endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces"), AP_INIT_TAKE1( "apacheModuleOtelSslEnabled", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelSslEnabled, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelSslEnabled, NULL, OR_ALL, "Decision whether communication to backend is secured"), AP_INIT_TAKE1( "apacheModuleOtelSslCertificatePath", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelSslCertificatePath, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelSslCertificatePath, NULL, OR_ALL, "Path to SSL certificate"), AP_INIT_TAKE1( "apacheModuleOtelSpanProcessor", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelProcessorType, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelProcessorType, NULL, OR_ALL, "Decision on how to pass finished and export-friendly span data representation to configured span exporter"), AP_INIT_TAKE1( "apacheModuleOtelSampler", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelSamplerType, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelSamplerType, NULL, OR_ALL, "Type of Otel Sampler"), AP_INIT_TAKE1( "apacheModuleServiceName", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_serviceName, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_serviceName, NULL, OR_ALL, - "Logical name of the service; equivalent to your AppDynamics tier name"), + "Logical name of the service"), AP_INIT_TAKE1( "apacheModuleServiceNamespace", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_serviceNamespace, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_serviceNamespace, NULL, OR_ALL, - "A namespace for the AppdynamicsServiceName; equivalent to your AppDynamics application name"), + "Logical namespace of the service;"), AP_INIT_TAKE1( "apacheModuleServiceInstanceId", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_serviceInstanceId, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_serviceInstanceId, NULL, OR_ALL, "The string ID of the service instance. Distinguish between instances of a service"), AP_INIT_TAKE1( "apacheModuleOtelMaxQueueSize", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelMaxQueueSize, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelMaxQueueSize, NULL, OR_ALL, "The maximum queue size. After the size is reached spans are dropped"), AP_INIT_TAKE1( "apacheModuleOtelScheduledDelayMillis", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelScheduledDelay, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelScheduledDelay, NULL, OR_ALL, "The delay interval in milliseconds between two consecutive exports"), AP_INIT_TAKE1( "apacheModuleOtelExportTimeoutMillis", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelExportTimeout, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelExportTimeout, NULL, OR_ALL, "How long the export can run in milliseconds before it is cancelled"), AP_INIT_TAKE1( "apacheModuleOtelMaxExportBatchSize", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_otelMaxExportBatchSize, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelMaxExportBatchSize, NULL, OR_ALL, "The maximum batch size of every export. It must be smaller or equal to maxQueueSize"), AP_INIT_TAKE1( "apacheModuleResolveBackends", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_resolveBackends, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_resolveBackends, NULL, OR_ALL, "Determine if backends need to be resolved as a tier"), AP_INIT_TAKE1( "apacheModuleTraceAsError", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_traceAsError, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_traceAsError, NULL, OR_ALL, "Trace level for information in the Apache log"), AP_INIT_TAKE1( "apacheModuleReportAllInstrumentedModules", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_reportAllInstrumentedModules, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_reportAllInstrumentedModules, NULL, OR_ALL, "Report all modules as endpoints instead of only those in the HANDLER stage"), AP_INIT_TAKE3( "apacheModuleWebserverContext", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_add_webserver_context, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_add_webserver_context, NULL, OR_ALL, "Specify webserver context for a mutli-tenant mode"), AP_INIT_TAKE1( "apacheModuleMaskCookie", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_maskCookie, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_maskCookie, NULL, OR_ALL, "Specify whether to mask the cookies"), AP_INIT_TAKE1( "apacheModuleCookieMatchPattern", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_cookiePattern, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_cookiePattern, NULL, OR_ALL, "Specify the pattern of cookie name to be masked"), AP_INIT_TAKE1( "apacheModuleMaskSmUser", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_maskSmUser, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_maskSmUser, NULL, OR_ALL, "Specify whether to mask SM_USER"), AP_INIT_TAKE1( "apacheModuleDelimiter", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_delimiter, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_delimiter, NULL, OR_ALL, "Specify the character that you want to use as URL segment endpoints"), AP_INIT_TAKE1( "apacheModuleSegment", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_segment, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_segment, NULL, OR_ALL, "Specify a comma-separated list to indicate the segments that you want the agent to filter"), AP_INIT_TAKE1( "apacheModuleMatchfilter", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_matchFilter, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_matchFilter, NULL, OR_ALL, "The type of filtering to be used to match the url"), AP_INIT_TAKE1( "apacheModuleMatchpattern", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_matchPattern, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_matchPattern, NULL, OR_ALL, "Specify the string that you want to be filtered by the match-filter"), AP_INIT_TAKE1( "apacheModuleSegmentType", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_segmentType, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_segmentType, NULL, OR_ALL, "Specify the string (FIRST|LAST|CUSTOM) that you want to be filtered for Span Creation"), AP_INIT_TAKE1( "apacheModuleSegmentParameter", - (CMD_HAND_TYPE)ApacheConfigHandlers::appd_set_segmentParameter, + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_segmentParameter, NULL, OR_ALL, "Specify the segment count or segment numbers that you want to display for Span Creation"), @@ -221,16 +221,16 @@ static const command_rec appd_cmds[] = DLL_PUBLIC module AP_MODULE_DECLARE_DATA otel_apache_module = { STANDARD20_MODULE_STUFF, - ApacheConfigHandlers::appd_create_dir_config, // per-directory config creator - ApacheConfigHandlers::appd_merge_dir_config, // dir config merger + ApacheConfigHandlers::otel_create_dir_config, // per-directory config creator + ApacheConfigHandlers::otel_merge_dir_config, // dir config merger NULL, NULL, - appd_cmds, // command table + otel_cmds, // command table ApacheHooks::registerHooks // set up other request processing hooks }; // Locate our directory configuration record for the current request. -appd_cfg* ApacheConfigHandlers::our_dconfig(const request_rec *r) +otel_cfg* ApacheConfigHandlers::our_dconfig(const request_rec *r) { - return (appd_cfg *) ap_get_module_config(r->per_dir_config, &otel_apache_module); + return (otel_cfg *) ap_get_module_config(r->per_dir_config, &otel_apache_module); } diff --git a/instrumentation/otel-webserver-module/src/core/AgentCore.cpp b/instrumentation/otel-webserver-module/src/core/AgentCore.cpp index 5d5122796..56579d7e7 100644 --- a/instrumentation/otel-webserver-module/src/core/AgentCore.cpp +++ b/instrumentation/otel-webserver-module/src/core/AgentCore.cpp @@ -16,7 +16,7 @@ #include "AgentCore.h" -namespace appd { +namespace otel { namespace core { AgentKernel::AgentKernel() : @@ -166,5 +166,5 @@ AgentCore::getRequestProcessor( } } // core -} // appd +} // otel diff --git a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp index 6dbe1572b..c428f6309 100755 --- a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp @@ -24,7 +24,7 @@ #include #endif -namespace appd { +namespace otel { namespace core { AgentLogger ApiUtils::apiLogger = 0; @@ -36,13 +36,13 @@ void ApiUtils::cleanup() apiUserLogger = 0; } -APPD_SDK_STATUS_CODE ApiUtils::init_boilerplate() +OTEL_SDK_STATUS_CODE ApiUtils::init_boilerplate() { try { boost::filesystem::path logConfigPath; - char* envLogConfigPath = getenv(APPD_SDK_ENV_LOG_CONFIG_PATH); + char* envLogConfigPath = getenv(OTEL_SDK_ENV_LOG_CONFIG_PATH); if(envLogConfigPath) { logConfigPath = envLogConfigPath; @@ -60,28 +60,28 @@ APPD_SDK_STATUS_CODE ApiUtils::init_boilerplate() { std::cerr << (boost::format( "Error: %1%: Invalid logging config file: %2%") % BOOST_CURRENT_FUNCTION % logConfigPath) << std::endl; - return APPD_STATUS(no_log_config); + return OTEL_STATUS(no_log_config); } bool res = initLogging(logConfigPath); if(!res) { - return APPD_STATUS(log_init_failed); + return OTEL_STATUS(log_init_failed); } - ApiUtils::apiLogger = getLogger(APPD_LOG_API_LOGGER); + ApiUtils::apiLogger = getLogger(OTEL_LOG_API_LOGGER); if(!ApiUtils::apiLogger) { - return APPD_STATUS(log_init_failed); + return OTEL_STATUS(log_init_failed); } LOG4CXX_INFO(ApiUtils::apiLogger, "API logger initialized using log configuration file: " << logConfigPath.string()); - ApiUtils::apiUserLogger = getLogger(APPD_LOG_API_USER_LOGGER); + ApiUtils::apiUserLogger = getLogger(OTEL_LOG_API_USER_LOGGER); if(!ApiUtils::apiUserLogger) { - return APPD_STATUS(log_init_failed); + return OTEL_STATUS(log_init_failed); } LOG4CXX_INFO(ApiUtils::apiUserLogger, "API User logger initialized using log configuration file:" << logConfigPath.string()); @@ -90,10 +90,10 @@ APPD_SDK_STATUS_CODE ApiUtils::init_boilerplate() } catch(...) { - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } - return APPD_SUCCESS; + return OTEL_SUCCESS; } boost::filesystem::path ApiUtils::getSDKInstallPath() @@ -135,15 +135,15 @@ boost::filesystem::path ApiUtils::getSDKInstallPath() return installPath; } -APPD_SDK_STATUS_CODE ApiUtils::ReadFromPassedSettings( - APPD_SDK_ENV_RECORD* envIn, +OTEL_SDK_STATUS_CODE ApiUtils::ReadFromPassedSettings( + OTEL_SDK_ENV_RECORD* envIn, unsigned numberOfRecords, TenantConfig& tenantConfig, SpanNamer& spanNamer) { PassedEnvinronmentReader env; - APPD_SDK_STATUS_CODE res = env.Init(envIn, numberOfRecords); - if(APPD_ISFAIL(res)) + OTEL_SDK_STATUS_CODE res = env.Init(envIn, numberOfRecords); + if(OTEL_ISFAIL(res)) { return res; } @@ -151,13 +151,13 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadFromPassedSettings( return ReadSettingsFromReader(env, tenantConfig, spanNamer); } -/*APPD_SDK_STATUS_CODE ApiUtils::ReadFromEnvinronment(TenantConfig& tenantConfig) +/*OTEL_SDK_STATUS_CODE ApiUtils::ReadFromEnvinronment(TenantConfig& tenantConfig) { RealEnvinronmentReader env; return ReadSettingsFromReader(env, tenantConfig); }*/ -APPD_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( +OTEL_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( IEnvReader& reader, TenantConfig& tenantConfig, SpanNamer& spanNamer) { @@ -181,79 +181,79 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( std::string segmentType; std::string segmentParameter; - APPD_SDK_STATUS_CODE status; + OTEL_SDK_STATUS_CODE status; status = reader.ReadMandatory( - std::string(APPD_SDK_ENV_SERVICE_NAMESPACE), serviceNamespace); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_SERVICE_NAMESPACE), serviceNamespace); + if(OTEL_ISFAIL(status)) return status; status = reader.ReadMandatory( - std::string(APPD_SDK_ENV_SERVICE_NAME), serviceName); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_SERVICE_NAME), serviceName); + if(OTEL_ISFAIL(status)) return status; status = reader.ReadMandatory( - std::string(APPD_SDK_ENV_SERVICE_INSTANCE_ID), serviceInstanceId); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_SERVICE_INSTANCE_ID), serviceInstanceId); + if(OTEL_ISFAIL(status)) return status; status = reader.ReadOptional( - std::string(APPD_SDK_ENV_OTEL_EXPORTER_TYPE), otelExporterType); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_OTEL_EXPORTER_TYPE), otelExporterType); + if(OTEL_ISFAIL(status)) return status; status = reader.ReadMandatory( - std::string(APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT), otelExporterEndpoint); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT), otelExporterEndpoint); + if(OTEL_ISFAIL(status)) return status; status = ReadOptionalFromReader( - reader, std::string(APPD_SDK_ENV_OTEL_SSL_ENABLED), otelSslEnabled); - if(APPD_ISFAIL(status)) + reader, std::string(OTEL_SDK_ENV_OTEL_SSL_ENABLED), otelSslEnabled); + if(OTEL_ISFAIL(status)) return status; status = reader.ReadOptional( - std::string(APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH), otelSslCertPath); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH), otelSslCertPath); + if(OTEL_ISFAIL(status)) return status; status = reader.ReadMandatory( - std::string(APPD_SDK_ENV_OTEL_LIBRARY_NAME), otelLibraryName); - if(APPD_ISFAIL(status)) + std::string(OTEL_SDK_ENV_OTEL_LIBRARY_NAME), otelLibraryName); + if(OTEL_ISFAIL(status)) return status; reader.ReadOptional( - std::string(APPD_SDK_ENV_OTEL_PROCESSOR_TYPE), otelProcessorType); + std::string(OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE), otelProcessorType); reader.ReadOptional( - std::string(APPD_SDK_ENV_OTEL_SAMPLER_TYPE), otelSamplerType); + std::string(OTEL_SDK_ENV_OTEL_SAMPLER_TYPE), otelSamplerType); status = ReadOptionalFromReader( - reader, std::string(APPD_SDK_ENV_MAX_QUEUE_SIZE), otelMaxQueueSize); - if(APPD_ISFAIL(status)) + reader, std::string(OTEL_SDK_ENV_MAX_QUEUE_SIZE), otelMaxQueueSize); + if(OTEL_ISFAIL(status)) return status; status = ReadOptionalFromReader( - reader, std::string(APPD_SDK_ENV_SCHEDULED_DELAY), otelScheduledDelayMillis); - if(APPD_ISFAIL(status)) + reader, std::string(OTEL_SDK_ENV_SCHEDULED_DELAY), otelScheduledDelayMillis); + if(OTEL_ISFAIL(status)) return status; status = ReadOptionalFromReader( - reader, std::string(APPD_SDK_ENV_EXPORT_BATCH_SIZE), otelMaxExportBatchSize); - if(APPD_ISFAIL(status)) + reader, std::string(OTEL_SDK_ENV_EXPORT_BATCH_SIZE), otelMaxExportBatchSize); + if(OTEL_ISFAIL(status)) return status; /*status = reader.ReadOptionalFromReader( - reader, std::string(APPD_SDK_ENV_EXPORT_BATCH_SIZE), setOtelExportTimeoutMillis); - if(APPD_ISFAIL(status)) + reader, std::string(OTEL_SDK_ENV_EXPORT_BATCH_SIZE), setOtelExportTimeoutMillis); + if(OTEL_ISFAIL(status)) return status;*/ reader.ReadOptional( - std::string(APPD_SDK_ENV_SEGMENT_TYPE), segmentType); + std::string(OTEL_SDK_ENV_SEGMENT_TYPE), segmentType); reader.ReadOptional( - std::string(APPD_SDK_ENV_SEGMENT_PARAMETER), segmentParameter); + std::string(OTEL_SDK_ENV_SEGMENT_PARAMETER), segmentParameter); tenantConfig.setServiceNamespace(serviceNamespace); @@ -273,17 +273,17 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( spanNamer.setSegmentRules(segmentType, segmentParameter); - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( +OTEL_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( IEnvReader& reader, const std::string& varName, bool& result) { std::string value; - APPD_SDK_STATUS_CODE status = reader.ReadOptional(varName, value); + OTEL_SDK_STATUS_CODE status = reader.ReadOptional(varName, value); if (value.empty()) { - return APPD_SUCCESS; + return OTEL_SUCCESS; } try @@ -298,20 +298,20 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( % value % e.target_type().name()); - return APPD_STATUS(environment_variable_invalid_value); + return OTEL_STATUS(environment_variable_invalid_value); } - return APPD_SUCCESS; + return OTEL_SUCCESS; } -/*APPD_SDK_STATUS_CODE ApiUtils::ReadMandatoryFromReader( +/*OTEL_SDK_STATUS_CODE ApiUtils::ReadMandatoryFromReader( IEnvReader& reader, const std::string& varName, unsigned short& result) { std::string value; - APPD_SDK_STATUS_CODE status = reader.ReadMandatory(varName, value); + OTEL_SDK_STATUS_CODE status = reader.ReadMandatory(varName, value); - if (APPD_ISFAIL(status)) + if (OTEL_ISFAIL(status)) { return status; } @@ -328,21 +328,21 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( % value % e.target_type().name()); - return APPD_STATUS(environment_variable_invalid_value); + return OTEL_STATUS(environment_variable_invalid_value); } - return APPD_SUCCESS; + return OTEL_SUCCESS; }*/ -APPD_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( +OTEL_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( IEnvReader& reader, const std::string& varName, unsigned int& result) { std::string value; - APPD_SDK_STATUS_CODE status = reader.ReadOptional(varName, value); + OTEL_SDK_STATUS_CODE status = reader.ReadOptional(varName, value); if (value.empty()) { - return APPD_SUCCESS; + return OTEL_SUCCESS; } try @@ -357,13 +357,13 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( % value % e.target_type().name()); - return APPD_STATUS(environment_variable_invalid_value); + return OTEL_STATUS(environment_variable_invalid_value); } - return APPD_SUCCESS; + return OTEL_SUCCESS; } -/*APPD_SDK_STATUS_CODE RealEnvinronmentReader::ReadMandatory( +/*OTEL_SDK_STATUS_CODE RealEnvinronmentReader::ReadMandatory( const std::string& varName, std::string& result) { result.clear(); @@ -372,22 +372,22 @@ APPD_SDK_STATUS_CODE ApiUtils::ReadOptionalFromReader( if(!pValue) { LOG4CXX_ERROR(ApiUtils::apiLogger, boost::format("Environment variable %1% must be specified") % varName.c_str()); - return APPD_STATUS(unspecified_environment_variable); + return OTEL_STATUS(unspecified_environment_variable); } std::string value = pValue; if(value.empty()) { LOG4CXX_ERROR(ApiUtils::apiLogger, boost::format("Environment variable %1% must be non-empty") % varName.c_str()); - return APPD_STATUS(unspecified_environment_variable); + return OTEL_STATUS(unspecified_environment_variable); } result = value; - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE RealEnvinronmentReader::ReadOptional( +OTEL_SDK_STATUS_CODE RealEnvinronmentReader::ReadOptional( const std::string& varName, std::string& result) { result.clear(); @@ -396,27 +396,27 @@ APPD_SDK_STATUS_CODE RealEnvinronmentReader::ReadOptional( if(!varValue) { LOG4CXX_TRACE(ApiUtils::apiLogger, boost::format("Environment variable %1% is not specified") % varName.c_str()); - return APPD_SUCCESS; + return OTEL_SUCCESS; } std::string value = varValue; if(value.empty()) { LOG4CXX_TRACE(ApiUtils::apiLogger, boost::format("Environment variable %1% is non-empty") % varName.c_str()); - return APPD_SUCCESS; + return OTEL_SUCCESS; } result = value; - return APPD_SUCCESS; + return OTEL_SUCCESS; }*/ -APPD_SDK_STATUS_CODE PassedEnvinronmentReader::Init( - APPD_SDK_ENV_RECORD* envIn, unsigned numberOfRecords) +OTEL_SDK_STATUS_CODE PassedEnvinronmentReader::Init( + OTEL_SDK_ENV_RECORD* envIn, unsigned numberOfRecords) { if(!envIn) { - return APPD_STATUS(environment_records_are_invalid); + return OTEL_STATUS(environment_records_are_invalid); } env.clear(); @@ -424,22 +424,22 @@ APPD_SDK_STATUS_CODE PassedEnvinronmentReader::Init( { if (!envIn[i].name || (strlen(envIn[i].name) == 0)) { - return APPD_STATUS(environment_record_name_is_not_specified_or_empty); + return OTEL_STATUS(environment_record_name_is_not_specified_or_empty); } std::string sName = envIn[i].name; if (!envIn[i].value) // we allow empty string for value { - return APPD_STATUS(environment_record_value_is_not_specified); + return OTEL_STATUS(environment_record_value_is_not_specified); } std::string sValue = envIn[i].value; env[sName] = sValue; } - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE PassedEnvinronmentReader::ReadMandatory( +OTEL_SDK_STATUS_CODE PassedEnvinronmentReader::ReadMandatory( const std::string& varName, std::string& result) { result.clear(); @@ -448,22 +448,22 @@ APPD_SDK_STATUS_CODE PassedEnvinronmentReader::ReadMandatory( if(found == env.end()) { LOG4CXX_ERROR(ApiUtils::apiLogger, boost::format("Environment variable %1% must be specified") % varName.c_str()); - return APPD_STATUS(unspecified_environment_variable); + return OTEL_STATUS(unspecified_environment_variable); } std::string value = (*found).second; if(value.empty()) { LOG4CXX_ERROR(ApiUtils::apiLogger, boost::format("Environment variable %1% must be non-empty") % varName.c_str()); - return APPD_STATUS(environment_variable_invalid_value); + return OTEL_STATUS(environment_variable_invalid_value); } result = value; - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE PassedEnvinronmentReader::ReadOptional( +OTEL_SDK_STATUS_CODE PassedEnvinronmentReader::ReadOptional( const std::string& varName, std::string& result) { result.clear(); @@ -472,19 +472,19 @@ APPD_SDK_STATUS_CODE PassedEnvinronmentReader::ReadOptional( if(found == env.end()) { LOG4CXX_TRACE(ApiUtils::apiLogger, boost::format("Environment variable %1% is not specified") % varName.c_str()); - return APPD_SUCCESS; + return OTEL_SUCCESS; } std::string value = (*found).second; if(value.empty()) { LOG4CXX_TRACE(ApiUtils::apiLogger, boost::format("Environment variable %1% is non-empty") % varName.c_str()); - return APPD_SUCCESS; + return OTEL_SUCCESS; } result = value; - return APPD_SUCCESS; + return OTEL_SUCCESS; } diff --git a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp index 6b1169147..c246e5a49 100644 --- a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp @@ -30,7 +30,7 @@ #include -namespace appd { +namespace otel { namespace core { using namespace sdkwrapper; @@ -50,22 +50,22 @@ void RequestProcessingEngine::init(std::shared_ptr& config, m_spanNamer = spanNamer; } -APPD_SDK_STATUS_CODE RequestProcessingEngine::startRequest( +OTEL_SDK_STATUS_CODE RequestProcessingEngine::startRequest( const std::string& wscontext, RequestPayload* payload, - APPD_SDK_HANDLE_REQ* reqHandle) { + OTEL_SDK_HANDLE_REQ* reqHandle) { if (!reqHandle) { - LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << APPD_STATUS(handle_pointer_is_null)); - return APPD_STATUS(handle_pointer_is_null); + LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << OTEL_STATUS(handle_pointer_is_null)); + return OTEL_STATUS(handle_pointer_is_null); } if (!payload) { - LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << APPD_STATUS(payload_reflector_is_null)); - return APPD_STATUS(payload_reflector_is_null); + LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << OTEL_STATUS(payload_reflector_is_null)); + return OTEL_STATUS(payload_reflector_is_null); } std::string spanName = m_spanNamer->getSpanName(payload->get_uri()); - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + otel::core::sdkwrapper::OtelKeyValueMap keyValueMap; keyValueMap[kAttrRequestProtocol] = payload->get_request_protocol(); keyValueMap[kAttrHTTPServerName] = payload->get_server_name(); keyValueMap[kAttrHTTPMethod] = payload->get_http_request_method(); @@ -93,17 +93,17 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startRequest( // Fill the requestHandle *reqHandle = (void*)requestContext; - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE RequestProcessingEngine::endRequest( - APPD_SDK_HANDLE_REQ reqHandle, +OTEL_SDK_STATUS_CODE RequestProcessingEngine::endRequest( + OTEL_SDK_HANDLE_REQ reqHandle, const char* error, const ResponsePayload* payload) { if (!reqHandle) { LOG4CXX_ERROR(mLogger, "Invalid request, can't end request"); - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } RequestContext* requestContext = (RequestContext*)reqHandle; @@ -164,22 +164,22 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::endRequest( rootSpan->End(); delete requestContext; - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE RequestProcessingEngine::startInteraction( - APPD_SDK_HANDLE_REQ reqHandle, +OTEL_SDK_STATUS_CODE RequestProcessingEngine::startInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, std::unordered_map& propagationHeaders) { if (!reqHandle) { - LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << APPD_STATUS(handle_pointer_is_null)); - return APPD_STATUS(handle_pointer_is_null); + LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << OTEL_STATUS(handle_pointer_is_null)); + return OTEL_STATUS(handle_pointer_is_null); } if (!payload) { - LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << APPD_STATUS(payload_reflector_is_null)); - return APPD_STATUS(payload_reflector_is_null); + LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << OTEL_STATUS(payload_reflector_is_null)); + return OTEL_STATUS(payload_reflector_is_null); } RequestContext* requestContext = (RequestContext*)reqHandle; @@ -187,7 +187,7 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startInteraction( // TODO : Add internal spans for virtual hosts post MVP // Create client span for this interaction. And set it in RequestContext object. - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + otel::core::sdkwrapper::OtelKeyValueMap keyValueMap; // TODO : confirm and update name later std::string spanName = payload->moduleName + "_" + payload->phaseName; @@ -199,22 +199,22 @@ APPD_SDK_STATUS_CODE RequestProcessingEngine::startInteraction( // Add the interaction to the request context. requestContext->addInteraction(interactionSpan); - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_API APPD_SDK_STATUS_CODE RequestProcessingEngine::endInteraction( - APPD_SDK_HANDLE_REQ reqHandle, +OTEL_SDK_API OTEL_SDK_STATUS_CODE RequestProcessingEngine::endInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, bool ignoreBackend, EndInteractionPayload *payload) { if (!reqHandle) { - LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << APPD_STATUS(handle_pointer_is_null)); - return APPD_STATUS(handle_pointer_is_null); + LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << OTEL_STATUS(handle_pointer_is_null)); + return OTEL_STATUS(handle_pointer_is_null); } if (!payload) { - LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << APPD_STATUS(payload_reflector_is_null)); - return APPD_STATUS(payload_reflector_is_null); + LOG4CXX_ERROR(mLogger, __FUNCTION__ << " " << OTEL_STATUS(payload_reflector_is_null)); + return OTEL_STATUS(payload_reflector_is_null); } // TODO : incorporate ignore backend logic here. @@ -223,8 +223,8 @@ APPD_SDK_API APPD_SDK_STATUS_CODE RequestProcessingEngine::endInteraction( if (!rContext->hasActiveInteraction()) { // error : requestContext has no corresponding interaction. - LOG4CXX_TRACE(mLogger, __FUNCTION__ << " " << APPD_STATUS(invalid_context)); - return APPD_STATUS(invalid_context); + LOG4CXX_TRACE(mLogger, __FUNCTION__ << " " << OTEL_STATUS(invalid_context)); + return OTEL_STATUS(invalid_context); } auto interactionSpan = rContext->lastActiveInteraction(); @@ -261,8 +261,8 @@ APPD_SDK_API APPD_SDK_STATUS_CODE RequestProcessingEngine::endInteraction( LOG4CXX_TRACE(mLogger, "Ending Span with id: " << interactionSpan.get()); interactionSpan->End(); rContext->removeInteraction(); - return APPD_SUCCESS; + return OTEL_SUCCESS; } } // core -} // appd +} // otel diff --git a/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp b/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp index b328a588b..b0ec2d9e6 100644 --- a/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/SpanNamer.cpp @@ -20,7 +20,7 @@ #include #include -namespace appd { +namespace otel { namespace core { const unsigned DefaultSegmentCount = 2; diff --git a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp index 20c5438ee..e32ffe5d2 100644 --- a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp @@ -23,10 +23,10 @@ #include "AgentCore.h" #include "api/SpanNamer.h" -namespace appd { +namespace otel { namespace core { -inline void apiFuncTraceError(const char* funcName, APPD_SDK_STATUS_CODE ret) +inline void apiFuncTraceError(const char* funcName, OTEL_SDK_STATUS_CODE ret) { std::ostringstream errMsg; errMsg << "Error: " << funcName << ": Error Code: " << ret; @@ -43,18 +43,18 @@ inline void apiFuncTraceError(const char* funcName, APPD_SDK_STATUS_CODE ret) WSAgent::WSAgent() : initPid(0) {} -APPD_SDK_STATUS_CODE -WSAgent::init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords) +OTEL_SDK_STATUS_CODE +WSAgent::init(OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords) { std::lock_guard lock(initMutex); - APPD_SDK_STATUS_CODE res = validateAndInitialise(); - if (APPD_ISFAIL(res)) + OTEL_SDK_STATUS_CODE res = validateAndInitialise(); + if (OTEL_ISFAIL(res)) { return res; } res = mApiUtils->init_boilerplate(); - if(APPD_ISFAIL(res)) + if(OTEL_ISFAIL(res)) { apiFuncTraceError(BOOST_CURRENT_FUNCTION, res); return(res); @@ -64,7 +64,7 @@ WSAgent::init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords) std::shared_ptr tenantConfig(std::make_shared()); std::shared_ptr spanNamer(std::make_shared()); res = readConfig(env, numberOfRecords, tenantConfig, spanNamer); - if(APPD_ISFAIL(res)) + if(OTEL_ISFAIL(res)) { apiFuncTraceError(BOOST_CURRENT_FUNCTION, res); return(res); @@ -73,16 +73,16 @@ WSAgent::init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords) // Start the Agent Core. if (!mAgentCore->start(tenantConfig, spanNamer, mUserAddedTenant)) { - apiFuncTraceError(BOOST_CURRENT_FUNCTION, APPD_STATUS(agent_failed_to_start)); - return(APPD_STATUS(agent_failed_to_start)); + apiFuncTraceError(BOOST_CURRENT_FUNCTION, OTEL_STATUS(agent_failed_to_start)); + return(OTEL_STATUS(agent_failed_to_start)); } initialisePid(); - return APPD_SUCCESS; + return OTEL_SUCCESS; } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::term() { if (mAgentCore) @@ -91,11 +91,11 @@ WSAgent::term() } } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::startRequest( const char* wscontext, RequestPayload* requestPayload, - APPD_SDK_HANDLE_REQ* reqHandle) + OTEL_SDK_HANDLE_REQ* reqHandle) { std::string context {wscontext}; auto *engine = mAgentCore->getRequestProcessor(context); @@ -104,12 +104,12 @@ WSAgent::startRequest( return engine->startRequest(context, requestPayload, reqHandle); } - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::endRequest( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_HANDLE_REQ reqHandle, const char* error, const ResponsePayload* payload) { // TODO: How to get the context here? @@ -123,12 +123,12 @@ WSAgent::endRequest( { return engine->endRequest(reqHandle, error, payload); } - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::startInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_HANDLE_REQ reqHandle, const InteractionPayload* payload, std::unordered_map& propagationHeaders) { @@ -139,12 +139,12 @@ WSAgent::startInteraction( { return engine->startInteraction(reqHandle, payload, propagationHeaders); } - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::endInteraction( - APPD_SDK_HANDLE_REQ reqHandle, + OTEL_SDK_HANDLE_REQ reqHandle, bool ignoreBackend, EndInteractionPayload *payload) { @@ -155,7 +155,7 @@ WSAgent::endInteraction( { return engine->endInteraction(reqHandle, ignoreBackend, payload); } - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } int @@ -166,13 +166,13 @@ WSAgent::addWSContextToCore( std::string contextName {wscontext}; if (contextName.empty() || contextName == COREINIT_CONTEXT) { - apiFuncTraceError("Invalid context name", APPD_STATUS(cannot_add_ws_context_to_core)); + apiFuncTraceError("Invalid context name", OTEL_STATUS(cannot_add_ws_context_to_core)); return -1; } if (!contextConfig) { - apiFuncTraceError("Invalid context config", APPD_STATUS(cannot_add_ws_context_to_core)); + apiFuncTraceError("Invalid context config", OTEL_STATUS(cannot_add_ws_context_to_core)); return -1; } std::string serviceNamespace = contextConfig->serviceNamespace; @@ -181,19 +181,19 @@ WSAgent::addWSContextToCore( if (serviceNamespace.empty()) { - apiFuncTraceError("Invalid serviceNamespace", APPD_STATUS(cannot_add_ws_context_to_core)); + apiFuncTraceError("Invalid serviceNamespace", OTEL_STATUS(cannot_add_ws_context_to_core)); return -1; } if (serviceName.empty()) { - apiFuncTraceError("Invalid serviceName", APPD_STATUS(cannot_add_ws_context_to_core)); + apiFuncTraceError("Invalid serviceName", OTEL_STATUS(cannot_add_ws_context_to_core)); return -1; } if (serviceInstanceId.empty()) { - apiFuncTraceError("Invalid serviceInstanceId", APPD_STATUS(cannot_add_ws_context_to_core)); + apiFuncTraceError("Invalid serviceInstanceId", OTEL_STATUS(cannot_add_ws_context_to_core)); return -1; } @@ -260,20 +260,20 @@ WSAgent::initDependency() { } } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::checkPID() { if (!initPid) { - return appd_sdk_status_uninitialized; + return otel_sdk_status_uninitialized; } else if (initPid != getpid()) { - return appd_sdk_status_wrong_process_id; + return otel_sdk_status_wrong_process_id; } else { - return appd_sdk_status_success; + return otel_sdk_status_success; } } @@ -283,22 +283,22 @@ WSAgent::initialisePid() initPid = getpid(); } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::validateAndInitialise() { - APPD_SDK_STATUS_CODE res = checkPID(); - if (res == appd_sdk_status_uninitialized) + OTEL_SDK_STATUS_CODE res = checkPID(); + if (res == otel_sdk_status_uninitialized) { // this is expected and means it is a valid sdk_init call. - res = appd_sdk_status_success; + res = otel_sdk_status_success; } - else if (res == appd_sdk_status_success) + else if (res == otel_sdk_status_success) { // this means sdk_init was already called - apiFuncTraceError(BOOST_CURRENT_FUNCTION, appd_sdk_status_already_initialized); - return(appd_sdk_status_already_initialized); + apiFuncTraceError(BOOST_CURRENT_FUNCTION, otel_sdk_status_already_initialized); + return(otel_sdk_status_already_initialized); } - else if(APPD_ISFAIL(res)) + else if(OTEL_ISFAIL(res)) { apiFuncTraceError(BOOST_CURRENT_FUNCTION, res); return(res); @@ -307,15 +307,15 @@ WSAgent::validateAndInitialise() return res; } -APPD_SDK_STATUS_CODE +OTEL_SDK_STATUS_CODE WSAgent::readConfig( - APPD_SDK_ENV_RECORD* env, + OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, std::shared_ptr tenantConfig, std::shared_ptr spanNamer) { // Read all Config passed in env or from environment - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; /*if(!env || numberOfRecords == 0) { res = mApiUtils->ReadFromEnvinronment(*tenantConfig); diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index ebafeacbf..38d514385 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -22,14 +22,14 @@ #include #include -appd::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic +otel::core::WSAgent wsAgent; // global variable for interface between Hooks and Core Logic std::unordered_set requestHeadersToCapture; std::unordered_set responseHeadersToCapture; constexpr char delimiter = ','; void populatePayload(request_payload* req_payload, void* load) { - appd::core::RequestPayload* payload = (appd::core::RequestPayload*)load; + otel::core::RequestPayload* payload = (otel::core::RequestPayload*)load; payload->set_uri(req_payload->uri); payload->set_scheme(req_payload->scheme); payload->set_flavor(req_payload->flavor); @@ -79,13 +79,13 @@ void initDependency() wsAgent.initDependency(); } -APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN) +OTEL_SDK_STATUS_CODE opentelemetry_core_init(OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, struct cNode *rootCN) { - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; struct cNode *curCN = rootCN; while(curCN){ - appd::core::WSContextConfig cfg; + otel::core::WSContextConfig cfg; cfg.serviceNamespace = (curCN->cInfo).sNamespace; cfg.serviceName = (curCN->cInfo).sName; cfg.serviceInstanceId = (curCN->cInfo).sInstanceId; @@ -98,24 +98,24 @@ APPD_SDK_STATUS_CODE opentelemetry_core_init(APPD_SDK_ENV_RECORD* env, unsigned return res; } -APPD_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, APPD_SDK_HANDLE_REQ* reqHandle) +OTEL_SDK_STATUS_CODE startRequest(const char* wscontext, request_payload* req_payload, OTEL_SDK_HANDLE_REQ* reqHandle) { - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; - std::unique_ptr requestPayload(new appd::core::RequestPayload); + std::unique_ptr requestPayload(new otel::core::RequestPayload); populatePayload(req_payload, requestPayload.get()); res = wsAgent.startRequest(wscontext, requestPayload.get(), reqHandle); return res; } -APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* errMsg, +OTEL_SDK_STATUS_CODE endRequest(OTEL_SDK_HANDLE_REQ req_handle_key, const char* errMsg, response_payload* payload) { - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; - std::unique_ptr - responsePayload(new appd::core::ResponsePayload); + std::unique_ptr + responsePayload(new otel::core::ResponsePayload); if (payload != NULL) { for (int i = 0; i < payload->response_headers_count; i++) { std::string key(payload->response_headers[i].name); @@ -133,17 +133,17 @@ APPD_SDK_STATUS_CODE endRequest(APPD_SDK_HANDLE_REQ req_handle_key, const char* return res; } -APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, APPD_SDK_ENV_RECORD* propagationHeaders, int *ix) +OTEL_SDK_STATUS_CODE startModuleInteraction(OTEL_SDK_HANDLE_REQ req_handle_key, const char* module_name, const char* stage, bool resolveBackends, OTEL_SDK_ENV_RECORD* propagationHeaders, int *ix) { - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; std::unordered_map pHeaders; std::string module(module_name); std::string m_stage(stage); - std::unique_ptr payload(new appd::core::InteractionPayload(module, m_stage, resolveBackends)); + std::unique_ptr payload(new otel::core::InteractionPayload(module, m_stage, resolveBackends)); res = wsAgent.startInteraction(req_handle_key, payload.get(), pHeaders); - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { if (!pHeaders.empty()) { @@ -162,10 +162,10 @@ APPD_SDK_STATUS_CODE startModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, return res; } -APPD_SDK_STATUS_CODE stopModuleInteraction(APPD_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg) +OTEL_SDK_STATUS_CODE stopModuleInteraction(OTEL_SDK_HANDLE_REQ req_handle_key, const char* backendName, const char* backendType, unsigned int err_code, const char* msg) { - std::unique_ptr payload(new appd::core::EndInteractionPayload(backendName, backendType, err_code, msg)); - APPD_SDK_STATUS_CODE res = wsAgent.endInteraction(req_handle_key, false, payload.get()); + std::unique_ptr payload(new otel::core::EndInteractionPayload(backendName, backendType, err_code, msg)); + OTEL_SDK_STATUS_CODE res = wsAgent.endInteraction(req_handle_key, false, payload.get()); return res; } diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp index 6d19c769e..399244d47 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp @@ -16,7 +16,7 @@ #include "sdkwrapper/ScopedSpan.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -81,4 +81,4 @@ SpanKind ScopedSpan::GetSpanKind() } //sdkwrapper } //core -} //appd +} //otel diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp index 8a75ac8b3..2962bb375 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp @@ -31,7 +31,7 @@ #include #include -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -188,5 +188,5 @@ OtelSampler SdkHelperFactory::GetSampler( } //sdkwrapper } //core -} //appd +} //otel diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp index ebac105f6..25ac06c27 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp @@ -20,7 +20,7 @@ #include "sdkwrapper/SdkUtils.h" #include "sdkwrapper/SdkHelperFactory.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -103,4 +103,4 @@ trace::SpanKind SdkWrapper::GetTraceSpanKind(const SpanKind& kind) } //sdkwrapper } //core -} //appd +} //otel diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp index 63defff4d..8a0c458f0 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ServerSpan.cpp @@ -17,7 +17,7 @@ #include "sdkwrapper/ServerSpan.h" #include "sdkwrapper/ScopedSpan.h" #include "sdkwrapper/SdkUtils.h" -namespace appd { +namespace otel { namespace core { namespace sdkwrapper { @@ -76,4 +76,4 @@ SpanKind ServerSpan::GetSpanKind() } //sdkwrapper } //core -} //appd +} //otel diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c index f861da5cf..31977d5da 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.c @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h index 9df692435..4bd84b16e 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_log.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 3452adefd..aef0c5105 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -689,8 +689,8 @@ static void ngx_otel_set_global_context(ngx_http_opentelemetry_loc_conf_t * prev /* Begin a new interaction */ -static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const char* module_name){ - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; +static OTEL_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const char* module_name){ + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; ngx_http_otel_handles_t* ctx; if(!r || r->internal) @@ -709,17 +709,17 @@ static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c { resolveBackends = conf->nginxModuleResolveBackends; } - APPD_SDK_ENV_RECORD* propagationHeaders = ngx_pcalloc(r->pool, 5 * sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* propagationHeaders = ngx_pcalloc(r->pool, 5 * sizeof(OTEL_SDK_ENV_RECORD)); if (propagationHeaders == NULL) { ngx_writeError(r->connection->log, __func__, "Failed to allocate memory for propagation headers"); - return APPD_STATUS(fail); + return OTEL_STATUS(fail); } ngx_writeTrace(r->connection->log, __func__, "Starting a new module interaction for: %s", module_name); int ix = 0; res = startModuleInteraction((void*)ctx->otel_req_handle_key, module_name, "", resolveBackends, propagationHeaders, &ix); - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { removeUnwantedHeader(r); otel_payload_decorator(r, propagationHeaders, ix); @@ -740,7 +740,7 @@ static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c return res; } -static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* propagationHeaders, int count) +static void otel_payload_decorator(ngx_http_request_t* r, OTEL_SDK_ENV_RECORD* propagationHeaders, int count) { ngx_list_part_t *part; ngx_table_elt_t *header; @@ -817,7 +817,7 @@ static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name, return; } - APPD_SDK_HANDLE_REQ otel_req_handle_key = APPD_SDK_NO_HANDLE; + OTEL_SDK_HANDLE_REQ otel_req_handle_key = OTEL_SDK_NO_HANDLE; ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); if (r->pool == NULL && request_handle_key != NULL) { @@ -850,8 +850,8 @@ static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name, strcat(msg, code); } ngx_writeTrace(r->connection->log, __func__, "Stopping the Interaction for: %s", module_name); - APPD_SDK_STATUS_CODE res = stopModuleInteraction(otel_req_handle_key, backendName, backendType, errCode, msg); - if (APPD_ISFAIL(res)) + OTEL_SDK_STATUS_CODE res = stopModuleInteraction(otel_req_handle_key, backendName, backendType, errCode, msg); + if (OTEL_ISFAIL(res)) { ngx_writeError(r->connection->log, __func__, "Error: Stop Interaction failed, result code: %d", res); } @@ -895,7 +895,7 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) if (conf->nginxModuleEnabled) { - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; char *qs = (char *)malloc(6); char *et = (char *)malloc(6); char *es = (char *)malloc(6); @@ -913,7 +913,7 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) // Update the apr_pcalloc if we add another parameter to the input array! - APPD_SDK_ENV_RECORD* env_config = ngx_pcalloc(r->pool, 16 * sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env_config = ngx_pcalloc(r->pool, 16 * sizeof(OTEL_SDK_ENV_RECORD)); if(env_config == NULL) { ngx_writeError(r->connection->log, __func__, "Not Able to allocate memory for the Env Config"); @@ -922,86 +922,86 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) int ix = 0; // Otel Exporter Type - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_TYPE; env_config[ix].value = (const char*)((conf->nginxModuleOtelSpanExporter).data); ++ix; // sdk libaray name - env_config[ix].name = APPD_SDK_ENV_OTEL_LIBRARY_NAME; + env_config[ix].name = OTEL_SDK_ENV_OTEL_LIBRARY_NAME; env_config[ix].value = "Nginx"; ++ix; // Otel Exporter Endpoint - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT; env_config[ix].value = (const char*)(conf->nginxModuleOtelExporterEndpoint).data; ++ix; // Otel SSL Enabled - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_ENABLED; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = conf->nginxModuleOtelSslEnabled == 1 ? "1" : "0"; ++ix; // Otel SSL Certificate Path - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; env_config[ix].value = (const char*)(conf->nginxModuleOtelSslCertificatePath).data; ++ix; // Otel Processor Type - env_config[ix].name = APPD_SDK_ENV_OTEL_PROCESSOR_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE; env_config[ix].value = (const char*)(conf->nginxModuleOtelSpanProcessor).data; ++ix; // Otel Sampler Type - env_config[ix].name = APPD_SDK_ENV_OTEL_SAMPLER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SAMPLER_TYPE; env_config[ix].value = (const char*)(conf->nginxModuleOtelSampler).data; ++ix; // Service Namespace - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAMESPACE; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAMESPACE; env_config[ix].value = (const char*)(conf->nginxModuleServiceNamespace).data; ++ix; // Service Name - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAME; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAME; env_config[ix].value = (const char*)(conf->nginxModuleServiceName).data; ++ix; // Service Instance ID - env_config[ix].name = APPD_SDK_ENV_SERVICE_INSTANCE_ID; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_INSTANCE_ID; env_config[ix].value = (const char*)(conf->nginxModuleServiceInstanceId).data; ++ix; // Otel Max Queue Size - env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; + env_config[ix].name = OTEL_SDK_ENV_MAX_QUEUE_SIZE; sprintf(qs, "%lu", conf->nginxModuleOtelMaxQueueSize); env_config[ix].value = qs; ++ix; // Otel Scheduled Delay - env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; + env_config[ix].name = OTEL_SDK_ENV_SCHEDULED_DELAY; sprintf(sd, "%lu", conf->nginxModuleOtelScheduledDelayMillis); env_config[ix].value = sd; ++ix; // Otel Max Export Batch Size - env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_BATCH_SIZE; sprintf(es, "%lu", conf->nginxModuleOtelMaxExportBatchSize); env_config[ix].value = es; ++ix; // Otel Export Timeout - env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_TIMEOUT; sprintf(et, "%lu", conf->nginxModuleOtelExportTimeoutMillis); env_config[ix].value = et; ++ix; // Segment Type - env_config[ix].name = APPD_SDK_ENV_SEGMENT_TYPE; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_TYPE; env_config[ix].value = (const char*)(conf->nginxModuleSegmentType).data; ++ix; // Segment Parameter - env_config[ix].name = APPD_SDK_ENV_SEGMENT_PARAMETER; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_PARAMETER; env_config[ix].value = (const char*)(conf->nginxModuleSegmentParameter).data; ++ix; @@ -1041,7 +1041,7 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) free(sd); free(et); free(es); - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { worker_conf->isInitialized = 1; ngx_writeTrace(r->connection->log, __func__, "Initializing Agent Core succceeded for process with PID: %s", worker_conf->pid); @@ -1063,7 +1063,7 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) } static void stopMonitoringRequest(ngx_http_request_t* r, - APPD_SDK_HANDLE_REQ request_handle_key) + OTEL_SDK_HANDLE_REQ request_handle_key) { ngx_http_opentelemetry_loc_conf_t *ngx_conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); if(!ngx_conf->nginxModuleEnabled) @@ -1072,7 +1072,7 @@ static void stopMonitoringRequest(ngx_http_request_t* r, return; } - APPD_SDK_HANDLE_REQ otel_req_handle_key = APPD_SDK_NO_HANDLE; + OTEL_SDK_HANDLE_REQ otel_req_handle_key = OTEL_SDK_NO_HANDLE; ngx_http_otel_handles_t* ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); if (r->pool == NULL && request_handle_key != NULL) { @@ -1100,7 +1100,7 @@ static void stopMonitoringRequest(ngx_http_request_t* r, fillResponsePayload(res_payload, r); } - APPD_SDK_STATUS_CODE res; + OTEL_SDK_STATUS_CODE res; char* msg = NULL; if (otel_requestHasErrors(r)) @@ -1116,7 +1116,7 @@ static void stopMonitoringRequest(ngx_http_request_t* r, res = endRequest(otel_req_handle_key, msg, res_payload); } - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { ngx_writeError(r->connection->log, __func__, "Request Ends with result code: %d", res); } @@ -1154,8 +1154,8 @@ static void startMonitoringRequest(ngx_http_request_t* r){ // Handle request for static contents (Nginx is used for habdling static contents) - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; - APPD_SDK_HANDLE_REQ reqHandle = APPD_SDK_NO_HANDLE; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; + OTEL_SDK_HANDLE_REQ reqHandle = OTEL_SDK_NO_HANDLE; const char* wscontext = NULL; @@ -1185,7 +1185,7 @@ static void startMonitoringRequest(ngx_http_request_t* r){ res = startRequest(wscontext, req_payload, &reqHandle); - if (APPD_ISSUCCESS(res)) + if (OTEL_ISSUCCESS(res)) { if (ctx == NULL) { @@ -1197,7 +1197,7 @@ static void startMonitoringRequest(ngx_http_request_t* r){ return; } // Store the Request Handle on the request object - APPD_SDK_HANDLE_REQ reqHandleValue = ngx_pcalloc(r->pool, sizeof(APPD_SDK_HANDLE_REQ)); + OTEL_SDK_HANDLE_REQ reqHandleValue = ngx_pcalloc(r->pool, sizeof(OTEL_SDK_HANDLE_REQ)); if (reqHandleValue) { reqHandleValue = reqHandle; @@ -1207,7 +1207,7 @@ static void startMonitoringRequest(ngx_http_request_t* r){ } ngx_writeTrace(r->connection->log, __func__, "Request Monitoring begins successfully "); } - else if (res == APPD_STATUS(cfg_channel_uninitialized) || res == APPD_STATUS(bt_detection_disabled)) + else if (res == OTEL_STATUS(cfg_channel_uninitialized) || res == OTEL_STATUS(bt_detection_disabled)) { ngx_writeTrace(r->connection->log, __func__, "Request begin detection disabled, result code: %d", res); } @@ -1220,7 +1220,7 @@ static void startMonitoringRequest(ngx_http_request_t* r){ static ngx_int_t ngx_http_otel_rewrite_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_rewrite_module"); ngx_int_t rvalue = h[NGX_HTTP_REWRITE_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_rewrite_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_rewrite_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1228,7 +1228,7 @@ static ngx_int_t ngx_http_otel_rewrite_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_limit_conn_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_limit_conn_module"); ngx_int_t rvalue = h[NGX_HTTP_LIMIT_CONN_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_limit_conn_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_limit_conn_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1236,7 +1236,7 @@ static ngx_int_t ngx_http_otel_limit_conn_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_limit_req_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_limit_req_module"); ngx_int_t rvalue = h[NGX_HTTP_LIMIT_REQ_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_limit_req_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_limit_req_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1252,7 +1252,7 @@ static ngx_int_t ngx_http_otel_realip_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_realip_module"); ngx_int_t rvalue = h[NGX_HTTP_REALIP_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_realip_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_realip_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1260,7 +1260,7 @@ static ngx_int_t ngx_http_otel_realip_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_auth_request_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_auth_request_module"); ngx_int_t rvalue = h[NGX_HTTP_LIMIT_AUTH_REQ_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_auth_request_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_auth_request_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1268,7 +1268,7 @@ static ngx_int_t ngx_http_otel_auth_request_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_auth_basic_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_auth_basic_module"); ngx_int_t rvalue = h[NGX_HTTP_AUTH_BASIC_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_auth_basic_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_auth_basic_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1276,7 +1276,7 @@ static ngx_int_t ngx_http_otel_auth_basic_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_access_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_access_module"); ngx_int_t rvalue = h[NGX_HTTP_ACCESS_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_access_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_access_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1284,7 +1284,7 @@ static ngx_int_t ngx_http_otel_access_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_static_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_static_module"); ngx_int_t rvalue = h[NGX_HTTP_STATIC_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_static_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_static_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1292,7 +1292,7 @@ static ngx_int_t ngx_http_otel_static_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_gzip_static_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_gzip_static_module"); ngx_int_t rvalue = h[NGX_HTTP_GZIP_STATIC_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_gzip_static_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_gzip_static_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1300,7 +1300,7 @@ static ngx_int_t ngx_http_otel_gzip_static_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_dav_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_dav_module"); ngx_int_t rvalue = h[NGX_HTTP_DAV_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_dav_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_dav_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1308,7 +1308,7 @@ static ngx_int_t ngx_http_otel_dav_handler(ngx_http_request_t *r){ static ngx_int_t ngx_http_otel_autoindex_handler(ngx_http_request_t *r){ otel_startInteraction(r, "ngx_http_autoindex_module"); ngx_int_t rvalue = h[NGX_HTTP_AUTO_INDEX_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_autoindex_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_autoindex_module", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1337,10 +1337,10 @@ static ngx_int_t ngx_http_otel_index_handler(ngx_http_request_t *r){ if (new_internal == true && new_internal != old_internal) { ngx_http_set_ctx(r, old_ctx, ngx_http_opentelemetry_module); r->internal = 0; - otel_stopInteraction(r, "ngx_http_index_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_index_module", OTEL_SDK_NO_HANDLE); r->internal = 1; } else { - otel_stopInteraction(r, "ngx_http_index_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_index_module", OTEL_SDK_NO_HANDLE); } return rvalue; @@ -1357,11 +1357,11 @@ static ngx_int_t ngx_http_otel_random_index_handler(ngx_http_request_t *r){ if (new_internal == true && new_internal != old_internal) { ngx_http_set_ctx(r, old_ctx, ngx_http_opentelemetry_module); r->internal = 0; - otel_stopInteraction(r, "ngx_http_random_index_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_random_index_module", OTEL_SDK_NO_HANDLE); r->internal = 1; } else { - otel_stopInteraction(r, "ngx_http_random_index_module", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_random_index_module", OTEL_SDK_NO_HANDLE); } return rvalue; @@ -1381,7 +1381,7 @@ static ngx_int_t ngx_http_otel_try_files_handler(ngx_http_request_t *r) { bool old_internal = r->internal; ngx_http_otel_handles_t* old_ctx; - APPD_SDK_HANDLE_REQ request_handle = APPD_SDK_NO_HANDLE; + OTEL_SDK_HANDLE_REQ request_handle = OTEL_SDK_NO_HANDLE; old_ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); if (old_ctx && old_ctx->otel_req_handle_key) { request_handle = old_ctx->otel_req_handle_key; @@ -1395,7 +1395,7 @@ static ngx_int_t ngx_http_otel_try_files_handler(ngx_http_request_t *r) { otel_stopInteraction(r, "ngx_http_otel_try_files_handler", request_handle); r->internal = 1; } else { - otel_stopInteraction(r, "ngx_http_otel_try_files_handler", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_otel_try_files_handler", OTEL_SDK_NO_HANDLE); } if (!r->pool) { @@ -1407,7 +1407,7 @@ static ngx_int_t ngx_http_otel_try_files_handler(ngx_http_request_t *r) { static ngx_int_t ngx_http_otel_mirror_handler(ngx_http_request_t *r) { otel_startInteraction(r, "ngx_http_otel_mirror_handler"); ngx_int_t rvalue = h[NGX_HTTP_MIRROR_MODULE_INDEX](r); - otel_stopInteraction(r, "ngx_http_otel_mirror_handler", APPD_SDK_NO_HANDLE); + otel_stopInteraction(r, "ngx_http_otel_mirror_handler", OTEL_SDK_NO_HANDLE); return rvalue; } @@ -1416,7 +1416,7 @@ static ngx_int_t ngx_http_otel_log_handler(ngx_http_request_t *r){ //This will be last handler to be be encountered before a request ends and response is finally sent back to client // Here, End the main trace, span created by Webserver Agent and the collected data will be passed to the backend // It will work as ngx_http_opentelemetry_log_transaction_end - stopMonitoringRequest(r, APPD_SDK_NO_HANDLE); + stopMonitoringRequest(r, OTEL_SDK_NO_HANDLE); ngx_int_t rvalue = h[NGX_HTTP_LOG_MODULE_INDEX](r); diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h index a3b749299..0ce1b0898 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -117,8 +117,8 @@ typedef struct{ }NGX_HTTP_OTEL_RECORDS; typedef struct { - APPD_SDK_HANDLE_REQ otel_req_handle_key; - APPD_SDK_ENV_RECORD* propagationHeaders; + OTEL_SDK_HANDLE_REQ otel_req_handle_key; + OTEL_SDK_ENV_RECORD* propagationHeaders; int pheaderCount; }ngx_http_otel_handles_t; @@ -142,11 +142,11 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* static void fillResponsePayload(response_payload* res_payload, ngx_http_request_t* r); static void startMonitoringRequest(ngx_http_request_t* r); static void stopMonitoringRequest(ngx_http_request_t* r, - APPD_SDK_HANDLE_REQ request_handle_key); -static APPD_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const char* module_name); + OTEL_SDK_HANDLE_REQ request_handle_key); +static OTEL_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const char* module_name); static void otel_stopInteraction(ngx_http_request_t* r, const char* module_name, - APPD_SDK_HANDLE_REQ request_handle_key); -static void otel_payload_decorator(ngx_http_request_t* r, APPD_SDK_ENV_RECORD* propagationHeaders, int count); + OTEL_SDK_HANDLE_REQ request_handle_key); +static void otel_payload_decorator(ngx_http_request_t* r, OTEL_SDK_ENV_RECORD* propagationHeaders, int count); static ngx_flag_t otel_requestHasErrors(ngx_http_request_t* r); static ngx_uint_t otel_getErrorCode(ngx_http_request_t* r); static char* ngx_otel_context_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); diff --git a/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp b/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp index e303fda02..979be39ae 100644 --- a/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/AgentCore_test.cpp @@ -20,19 +20,19 @@ #include "mocks/mock_RequestProcessingEngine.h" #include -class FakeContext : public appd::core::WebServerContext +class FakeContext : public otel::core::WebServerContext { public: - FakeContext(std::shared_ptr config) - : appd::core::WebServerContext(config) + FakeContext(std::shared_ptr config) + : otel::core::WebServerContext(config) {} - void initContext(std::shared_ptr spanNamer) + void initContext(std::shared_ptr spanNamer) { mAgentKernel.reset(new MockAgentKernel); } }; -class FakeAgentCore : public appd::core::AgentCore +class FakeAgentCore : public otel::core::AgentCore { public: FakeAgentCore( @@ -45,7 +45,7 @@ class FakeAgentCore : public appd::core::AgentCore protected: void createContext( const std::string& contextName, - std::shared_ptr config) + std::shared_ptr config) { if (contextName == COREINIT_CONTEXT) { @@ -62,15 +62,15 @@ class FakeAgentCore : public appd::core::AgentCore std::shared_ptr mDummyContext; }; -class FakeKernel : public appd::core::AgentKernel +class FakeKernel : public otel::core::AgentKernel { public: FakeKernel(MockRequestProcessingEngine* engine) : mEngine(engine) {} - void initKernel(std::shared_ptr config, - std::shared_ptr spanNamer) + void initKernel(std::shared_ptr config, + std::shared_ptr spanNamer) { mRequestProcessingEngine.reset(mEngine); } @@ -79,7 +79,7 @@ class FakeKernel : public appd::core::AgentKernel }; -void fillTenantConfig(std::shared_ptr config) +void fillTenantConfig(std::shared_ptr config) { config->setServiceNamespace("serviceNamespace"); config->setServiceName("serviceName"); @@ -99,14 +99,14 @@ using testing::_; TEST(WebserverContext, webserver_context_creation_success) { - auto tenantConfig = std::make_shared(); + auto tenantConfig = std::make_shared(); fillTenantConfig(tenantConfig); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeContext context(tenantConfig); context.initContext(spanNamer); - appd::core::IKernel* kernel = context.getKernel(); + otel::core::IKernel* kernel = context.getKernel(); EXPECT_NE(nullptr, kernel); MockAgentKernel* mockKernel = dynamic_cast(kernel); @@ -119,30 +119,30 @@ TEST(WebserverContext, webserver_context_creation_success) TEST(AgentCore, agent_core_start_returns_true) { - auto initConfig = std::make_shared(); + auto initConfig = std::make_shared(); fillTenantConfig(initConfig); - auto dummyConfig = std::make_shared(); + auto dummyConfig = std::make_shared(); fillTenantConfig(dummyConfig); dummyConfig->setServiceInstanceId("dummyInstanceId"); std::unordered_map< std::string, - std::shared_ptr> mapTenantConfig; + std::shared_ptr> mapTenantConfig; mapTenantConfig["dummyConfig"] = dummyConfig; auto initContext = std::make_shared(); auto dummyContext = std::make_shared(); EXPECT_CALL(*initContext, getConfig()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return initConfig; })); EXPECT_CALL(*initContext, initContext(_)).Times(1); EXPECT_CALL(*dummyContext, initContext(_)).Times(1); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeAgentCore agentCore(initContext, dummyContext); bool ret = agentCore.start(initConfig, spanNamer, mapTenantConfig); EXPECT_EQ(ret, true); @@ -150,30 +150,30 @@ TEST(AgentCore, agent_core_start_returns_true) TEST(AgentCore, get_request_processor_returns_valid_object) { - auto initConfig = std::make_shared(); + auto initConfig = std::make_shared(); fillTenantConfig(initConfig); - auto dummyConfig = std::make_shared(); + auto dummyConfig = std::make_shared(); fillTenantConfig(dummyConfig); dummyConfig->setServiceInstanceId("dummyInstanceId"); std::unordered_map< std::string, - std::shared_ptr> mapTenantConfig; + std::shared_ptr> mapTenantConfig; mapTenantConfig["dummyConfig"] = dummyConfig; auto initContext = std::make_shared(); auto dummyContext = std::make_shared(); EXPECT_CALL(*initContext, getConfig()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return initConfig; })); EXPECT_CALL(*initContext, initContext(_)).Times(1); EXPECT_CALL(*dummyContext, initContext(_)).Times(1); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeAgentCore agentCore(initContext, dummyContext); bool ret = agentCore.start(initConfig, spanNamer, mapTenantConfig); EXPECT_EQ(ret, true); @@ -181,12 +181,12 @@ TEST(AgentCore, get_request_processor_returns_valid_object) MockAgentKernel mockKernel; MockRequestProcessingEngine mockEngine; EXPECT_CALL(*dummyContext, getKernel()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IKernel*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IKernel*{ return &mockKernel; })); EXPECT_CALL(mockKernel, getRequestProcessingEngine()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockEngine; })); @@ -197,30 +197,30 @@ TEST(AgentCore, get_request_processor_returns_valid_object) TEST(AgentCore, get_request_processor_returns_nullptr) { - auto initConfig = std::make_shared(); + auto initConfig = std::make_shared(); fillTenantConfig(initConfig); - auto dummyConfig = std::make_shared(); + auto dummyConfig = std::make_shared(); fillTenantConfig(dummyConfig); dummyConfig->setServiceInstanceId("dummyInstanceId"); std::unordered_map< std::string, - std::shared_ptr> mapTenantConfig; + std::shared_ptr> mapTenantConfig; mapTenantConfig["dummyConfig"] = dummyConfig; auto initContext = std::make_shared(); auto dummyContext = std::make_shared(); EXPECT_CALL(*initContext, getConfig()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return initConfig; })); EXPECT_CALL(*initContext, initContext(_)).Times(1); EXPECT_CALL(*dummyContext, initContext(_)).Times(1); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeAgentCore agentCore(initContext, dummyContext); bool ret = agentCore.start(initConfig, spanNamer, mapTenantConfig); EXPECT_EQ(ret, true); @@ -232,30 +232,30 @@ TEST(AgentCore, get_request_processor_returns_nullptr) TEST(AgentCore, get_webserver_context_returns_valid_object) { - auto initConfig = std::make_shared(); + auto initConfig = std::make_shared(); fillTenantConfig(initConfig); - auto dummyConfig = std::make_shared(); + auto dummyConfig = std::make_shared(); fillTenantConfig(dummyConfig); dummyConfig->setServiceInstanceId("dummyInstanceId"); std::unordered_map< std::string, - std::shared_ptr> mapTenantConfig; + std::shared_ptr> mapTenantConfig; mapTenantConfig["dummyConfig"] = dummyConfig; auto initContext = std::make_shared(); auto dummyContext = std::make_shared(); EXPECT_CALL(*initContext, getConfig()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return initConfig; })); EXPECT_CALL(*initContext, initContext(_)).Times(1); EXPECT_CALL(*dummyContext, initContext(_)).Times(1); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeAgentCore agentCore(initContext, dummyContext); bool ret = agentCore.start(initConfig, spanNamer, mapTenantConfig); EXPECT_EQ(ret, true); @@ -273,30 +273,30 @@ TEST(AgentCore, get_webserver_context_returns_valid_object) TEST(AgentCore, get_webserver_context_returns_nullptr) { - auto initConfig = std::make_shared(); + auto initConfig = std::make_shared(); fillTenantConfig(initConfig); - auto dummyConfig = std::make_shared(); + auto dummyConfig = std::make_shared(); fillTenantConfig(dummyConfig); dummyConfig->setServiceInstanceId("dummyInstanceId"); std::unordered_map< std::string, - std::shared_ptr> mapTenantConfig; + std::shared_ptr> mapTenantConfig; mapTenantConfig["dummyConfig"] = dummyConfig; auto initContext = std::make_shared(); auto dummyContext = std::make_shared(); EXPECT_CALL(*initContext, getConfig()).Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return initConfig; })); EXPECT_CALL(*initContext, initContext(_)).Times(1); EXPECT_CALL(*dummyContext, initContext(_)).Times(1); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeAgentCore agentCore(initContext, dummyContext); bool ret = agentCore.start(initConfig, spanNamer, mapTenantConfig); EXPECT_EQ(ret, true); @@ -308,13 +308,13 @@ TEST(AgentCore, get_webserver_context_returns_nullptr) TEST(AgentKernel, agent_kernel_creation_success) { - auto initConfig = std::make_shared(); + auto initConfig = std::make_shared(); fillTenantConfig(initConfig); MockRequestProcessingEngine *engine = new MockRequestProcessingEngine(); testing::Mock::AllowLeak(engine); - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); FakeKernel agentKernel(engine); agentKernel.initKernel(initConfig, spanNamer); auto *rEngine = dynamic_cast diff --git a/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp b/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp index db8867808..b420dda32 100644 --- a/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/ApiUtils_test.cpp @@ -20,406 +20,406 @@ TEST(PassedEnvironmentReader, Init_Invalid_env_records) { - appd::core::PassedEnvinronmentReader reader; + otel::core::PassedEnvinronmentReader reader; auto status = reader.Init(nullptr, 0); - EXPECT_EQ(status, APPD_STATUS(environment_records_are_invalid)); + EXPECT_EQ(status, OTEL_STATUS(environment_records_are_invalid)); - APPD_SDK_ENV_RECORD* env_config = - new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{"", "dummy_value"}; + OTEL_SDK_ENV_RECORD* env_config = + new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{"", "dummy_value"}; status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_STATUS(environment_record_name_is_not_specified_or_empty)); + EXPECT_EQ(status, OTEL_STATUS(environment_record_name_is_not_specified_or_empty)); delete env_config; - env_config = new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{nullptr, "dummy_value"}; + env_config = new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{nullptr, "dummy_value"}; status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_STATUS(environment_record_name_is_not_specified_or_empty)); + EXPECT_EQ(status, OTEL_STATUS(environment_record_name_is_not_specified_or_empty)); delete env_config; - env_config = new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", nullptr}; + env_config = new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", nullptr}; status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_STATUS(environment_record_value_is_not_specified)); + EXPECT_EQ(status, OTEL_STATUS(environment_record_value_is_not_specified)); delete env_config; } TEST(PassedEnvironmentReader, Init_Valid_env_records) { - appd::core::PassedEnvinronmentReader reader; - APPD_SDK_ENV_RECORD* env_config = - new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", ""}; + otel::core::PassedEnvinronmentReader reader; + OTEL_SDK_ENV_RECORD* env_config = + new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", ""}; auto status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); delete env_config; - env_config = new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", "dummy_value"}; + env_config = new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", "dummy_value"}; status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); delete env_config; } TEST(PassedEnvironmentReader, ReadMandatory) { - appd::core::ApiUtils::apiLogger = getLogger("api"); - appd::core::PassedEnvinronmentReader reader; - APPD_SDK_ENV_RECORD* env_config = new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", "dummy_value"}; + otel::core::ApiUtils::apiLogger = getLogger("api"); + otel::core::PassedEnvinronmentReader reader; + OTEL_SDK_ENV_RECORD* env_config = new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", "dummy_value"}; auto status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); std::string key = {"dummy_key"}; std::string value; status = reader.ReadMandatory(key, value); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); EXPECT_EQ(value, "dummy_value"); key = "unknown_key"; std::string value1; status = reader.ReadMandatory(key, value1); - EXPECT_EQ(status, APPD_STATUS(unspecified_environment_variable)); + EXPECT_EQ(status, OTEL_STATUS(unspecified_environment_variable)); delete env_config; - appd::core::PassedEnvinronmentReader reader2; - env_config = new APPD_SDK_ENV_RECORD[1]; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", ""}; + otel::core::PassedEnvinronmentReader reader2; + env_config = new OTEL_SDK_ENV_RECORD[1]; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", ""}; status = reader2.Init(env_config, 1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); key = "dummy_key"; value = ""; status = reader2.ReadMandatory(key, value); - EXPECT_EQ(status, APPD_STATUS(environment_variable_invalid_value)); + EXPECT_EQ(status, OTEL_STATUS(environment_variable_invalid_value)); } TEST(PassedEnvironmentReader, ReadOptional) { - appd::core::ApiUtils::apiLogger = getLogger("api"); - appd::core::PassedEnvinronmentReader reader; - APPD_SDK_ENV_RECORD* env_config = new APPD_SDK_ENV_RECORD[1] ; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", "dummy_value"}; + otel::core::ApiUtils::apiLogger = getLogger("api"); + otel::core::PassedEnvinronmentReader reader; + OTEL_SDK_ENV_RECORD* env_config = new OTEL_SDK_ENV_RECORD[1] ; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", "dummy_value"}; auto status = reader.Init(env_config, 1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); std::string key = {"dummy_key"}; std::string value; status = reader.ReadOptional(key, value); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); EXPECT_EQ(value, "dummy_value"); key = "unknown_key"; std::string value1; status = reader.ReadOptional(key, value1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); delete env_config; - appd::core::PassedEnvinronmentReader reader2; - env_config = new APPD_SDK_ENV_RECORD[1]; - env_config[0] = APPD_SDK_ENV_RECORD{"dummy_key", ""}; + otel::core::PassedEnvinronmentReader reader2; + env_config = new OTEL_SDK_ENV_RECORD[1]; + env_config[0] = OTEL_SDK_ENV_RECORD{"dummy_key", ""}; status = reader2.Init(env_config, 1); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); key = "dummy_key"; value = ""; status = reader2.ReadOptional(key, value); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); } TEST(ApiUtils, ReadFromPassedSettings_Success) { - APPD_SDK_ENV_RECORD* env_config = new APPD_SDK_ENV_RECORD[16]; + OTEL_SDK_ENV_RECORD* env_config = new OTEL_SDK_ENV_RECORD[16]; int ix = 0; // Otel Exporter Type - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_TYPE; env_config[ix].value = "dummy_exporter"; ++ix; // Otel Exporter Endpoint - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT; env_config[ix].value = "dummy_endpoint"; ++ix; // Otel SSL Enabled - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_ENABLED; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = "1"; ++ix; // Otel Certificate Path - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; env_config[ix].value = "dummy_path"; ++ix; // sdk libaray name - env_config[ix].name = APPD_SDK_ENV_OTEL_LIBRARY_NAME; + env_config[ix].name = OTEL_SDK_ENV_OTEL_LIBRARY_NAME; env_config[ix].value = "Apache"; ++ix; // Otel Processor Type - env_config[ix].name = APPD_SDK_ENV_OTEL_PROCESSOR_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE; env_config[ix].value = "dummy_processor"; ++ix; // Otel Sampler Type - env_config[ix].name = APPD_SDK_ENV_OTEL_SAMPLER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SAMPLER_TYPE; env_config[ix].value = "dummy_sampler"; ++ix; // Service Namespace - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAMESPACE; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAMESPACE; env_config[ix].value = "dummy_service_namespace"; ++ix; // Service Name - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAME; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAME; env_config[ix].value = "dummy_service"; ++ix; // Service Instance ID - env_config[ix].name = APPD_SDK_ENV_SERVICE_INSTANCE_ID; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_INSTANCE_ID; env_config[ix].value = "dummy_instance_id"; ++ix; // Otel Max Queue Size - env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; + env_config[ix].name = OTEL_SDK_ENV_MAX_QUEUE_SIZE; env_config[ix].value = "2048"; ++ix; // Otel Scheduled Delay - env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; + env_config[ix].name = OTEL_SDK_ENV_SCHEDULED_DELAY; env_config[ix].value = "500"; ++ix; // Otel Max Export Batch Size - env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_BATCH_SIZE; env_config[ix].value = "2048"; ++ix; // Otel Export Timeout - env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_TIMEOUT; env_config[ix].value = "50000"; ++ix; // Segment Type - env_config[ix].name = APPD_SDK_ENV_SEGMENT_TYPE; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_TYPE; env_config[ix].value = "first"; ++ix; // Segment Parameter - env_config[ix].name = APPD_SDK_ENV_SEGMENT_PARAMETER; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_PARAMETER; env_config[ix].value = "2"; ++ix; - appd::core::SpanNamer spanNamer; - appd::core::TenantConfig tenantConfig; - appd::core::ApiUtils apiUtils; + otel::core::SpanNamer spanNamer; + otel::core::TenantConfig tenantConfig; + otel::core::ApiUtils apiUtils; auto status = apiUtils.ReadFromPassedSettings(env_config, 16, tenantConfig, spanNamer); - EXPECT_EQ(status, APPD_SUCCESS); + EXPECT_EQ(status, OTEL_SUCCESS); delete env_config; } TEST(ApiUtils, ReadFromPassedSettings_Fails_On_null_env) { - appd::core::SpanNamer spanNamer; - appd::core::TenantConfig tenantConfig; - appd::core::ApiUtils apiUtils; + otel::core::SpanNamer spanNamer; + otel::core::TenantConfig tenantConfig; + otel::core::ApiUtils apiUtils; auto status = apiUtils.ReadFromPassedSettings(nullptr, 0, tenantConfig, spanNamer); - EXPECT_NE(status, APPD_SUCCESS); + EXPECT_NE(status, OTEL_SUCCESS); } TEST(ApiUtils, ReadFromPassedSettings_Failure_On_Invalid_Int) { - APPD_SDK_ENV_RECORD* env_config = new APPD_SDK_ENV_RECORD[16]; + OTEL_SDK_ENV_RECORD* env_config = new OTEL_SDK_ENV_RECORD[16]; int ix = 0; // Otel Exporter Type - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_TYPE; env_config[ix].value = "dummy_exporter"; ++ix; // Otel Exporter Endpoint - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT; env_config[ix].value = "dummy_endpoint"; ++ix; // Otel SSL Enabled - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_ENABLED; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = "1"; ++ix; // Otel Certificate Path - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; env_config[ix].value = "dummy_path"; ++ix; // sdk libaray name - env_config[ix].name = APPD_SDK_ENV_OTEL_LIBRARY_NAME; + env_config[ix].name = OTEL_SDK_ENV_OTEL_LIBRARY_NAME; env_config[ix].value = "Apache"; ++ix; // Otel Processor Type - env_config[ix].name = APPD_SDK_ENV_OTEL_PROCESSOR_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE; env_config[ix].value = "dummy_processor"; ++ix; // Otel Sampler Type - env_config[ix].name = APPD_SDK_ENV_OTEL_SAMPLER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SAMPLER_TYPE; env_config[ix].value = "dummy_sampler"; ++ix; // Service Namespace - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAMESPACE; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAMESPACE; env_config[ix].value = "dummy_service_namespace"; ++ix; // Service Name - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAME; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAME; env_config[ix].value = "dummy_service"; ++ix; // Service Instance ID - env_config[ix].name = APPD_SDK_ENV_SERVICE_INSTANCE_ID; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_INSTANCE_ID; env_config[ix].value = "dummy_instance_id"; ++ix; // Otel Max Queue Size - env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; + env_config[ix].name = OTEL_SDK_ENV_MAX_QUEUE_SIZE; env_config[ix].value = "2048"; ++ix; // Otel Scheduled Delay - env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; + env_config[ix].name = OTEL_SDK_ENV_SCHEDULED_DELAY; env_config[ix].value = "500"; ++ix; // Otel Max Export Batch Size - env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_BATCH_SIZE; env_config[ix].value = "abcd"; ++ix; // Otel Export Timeout - env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_TIMEOUT; env_config[ix].value = "50000"; ++ix; // Segment Type - env_config[ix].name = APPD_SDK_ENV_SEGMENT_TYPE; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_TYPE; env_config[ix].value = "first"; ++ix; // Segment Parameter - env_config[ix].name = APPD_SDK_ENV_SEGMENT_PARAMETER; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_PARAMETER; env_config[ix].value = "2"; ++ix; - appd::core::SpanNamer spanNamer; - appd::core::TenantConfig tenantConfig; - appd::core::ApiUtils apiUtils; + otel::core::SpanNamer spanNamer; + otel::core::TenantConfig tenantConfig; + otel::core::ApiUtils apiUtils; auto status = apiUtils.ReadFromPassedSettings(env_config, 16, tenantConfig, spanNamer); - EXPECT_EQ(status, APPD_STATUS(environment_variable_invalid_value)); + EXPECT_EQ(status, OTEL_STATUS(environment_variable_invalid_value)); delete env_config; } TEST(ApiUtils, ReadFromPassedSettings_Failure_On_Invalid_Bool) { - APPD_SDK_ENV_RECORD* env_config = new APPD_SDK_ENV_RECORD[16]; + OTEL_SDK_ENV_RECORD* env_config = new OTEL_SDK_ENV_RECORD[16]; int ix = 0; // Otel Exporter Type - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_TYPE; env_config[ix].value = "dummy_exporter"; ++ix; // Otel Exporter Endpoint - env_config[ix].name = APPD_SDK_ENV_OTEL_EXPORTER_ENDPOINT; + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT; env_config[ix].value = "dummy_endpoint"; ++ix; // Otel SSL Enabled - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_ENABLED; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = "abcd"; ++ix; // Otel Certificate Path - env_config[ix].name = APPD_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH; env_config[ix].value = "dummy_path"; ++ix; // sdk libaray name - env_config[ix].name = APPD_SDK_ENV_OTEL_LIBRARY_NAME; + env_config[ix].name = OTEL_SDK_ENV_OTEL_LIBRARY_NAME; env_config[ix].value = "Apache"; ++ix; // Otel Processor Type - env_config[ix].name = APPD_SDK_ENV_OTEL_PROCESSOR_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE; env_config[ix].value = "dummy_processor"; ++ix; // Otel Sampler Type - env_config[ix].name = APPD_SDK_ENV_OTEL_SAMPLER_TYPE; + env_config[ix].name = OTEL_SDK_ENV_OTEL_SAMPLER_TYPE; env_config[ix].value = "dummy_sampler"; ++ix; // Service Namespace - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAMESPACE; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAMESPACE; env_config[ix].value = "dummy_service_namespace"; ++ix; // Service Name - env_config[ix].name = APPD_SDK_ENV_SERVICE_NAME; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_NAME; env_config[ix].value = "dummy_service"; ++ix; // Service Instance ID - env_config[ix].name = APPD_SDK_ENV_SERVICE_INSTANCE_ID; + env_config[ix].name = OTEL_SDK_ENV_SERVICE_INSTANCE_ID; env_config[ix].value = "dummy_instance_id"; ++ix; // Otel Max Queue Size - env_config[ix].name = APPD_SDK_ENV_MAX_QUEUE_SIZE; + env_config[ix].name = OTEL_SDK_ENV_MAX_QUEUE_SIZE; env_config[ix].value = "2048"; ++ix; // Otel Scheduled Delay - env_config[ix].name = APPD_SDK_ENV_SCHEDULED_DELAY; + env_config[ix].name = OTEL_SDK_ENV_SCHEDULED_DELAY; env_config[ix].value = "500"; ++ix; // Otel Max Export Batch Size - env_config[ix].name = APPD_SDK_ENV_EXPORT_BATCH_SIZE; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_BATCH_SIZE; env_config[ix].value = "2048"; ++ix; // Otel Export Timeout - env_config[ix].name = APPD_SDK_ENV_EXPORT_TIMEOUT; + env_config[ix].name = OTEL_SDK_ENV_EXPORT_TIMEOUT; env_config[ix].value = "50000"; ++ix; // Segment Type - env_config[ix].name = APPD_SDK_ENV_SEGMENT_TYPE; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_TYPE; env_config[ix].value = "first"; ++ix; // Segment Parameter - env_config[ix].name = APPD_SDK_ENV_SEGMENT_PARAMETER; + env_config[ix].name = OTEL_SDK_ENV_SEGMENT_PARAMETER; env_config[ix].value = "2"; ++ix; - appd::core::SpanNamer spanNamer; - appd::core::TenantConfig tenantConfig; - appd::core::ApiUtils apiUtils; + otel::core::SpanNamer spanNamer; + otel::core::TenantConfig tenantConfig; + otel::core::ApiUtils apiUtils; auto status = apiUtils.ReadFromPassedSettings(env_config, 16, tenantConfig, spanNamer); - EXPECT_EQ(status, APPD_STATUS(environment_variable_invalid_value)); + EXPECT_EQ(status, OTEL_STATUS(environment_variable_invalid_value)); delete env_config; } TEST(ApiUtils, getSDKInstallPath) { - appd::core::ApiUtils apiUtils; + otel::core::ApiUtils apiUtils; auto path = apiUtils.getSDKInstallPath(); EXPECT_THAT(path.string(), testing::EndsWith("build/linux-x64/opentelemetry-webserver-sdk")); } diff --git a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp index 4fb0e48eb..6b382018a 100644 --- a/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/RequestProcessingEngine_test.cpp @@ -23,18 +23,18 @@ #include -using namespace appd::core::sdkwrapper; +using namespace otel::core::sdkwrapper; -class FakeRequestProcessingEngine : appd::core::RequestProcessingEngine { +class FakeRequestProcessingEngine : otel::core::RequestProcessingEngine { public: - using Base = appd::core::RequestProcessingEngine; + using Base = otel::core::RequestProcessingEngine; using Base::startRequest; using Base::endRequest; using Base::startInteraction; using Base::endInteraction; FakeRequestProcessingEngine() = default; - void init(std::shared_ptr& config, - std::shared_ptr spanNamer) override { + void init(std::shared_ptr& config, + std::shared_ptr spanNamer) override { m_sdkWrapper.reset(new MockSdkWrapper); m_spanNamer = spanNamer; } @@ -54,7 +54,7 @@ MATCHER_P(HasStringVal, value, "") { MATCHER_P(HasMapVal, value, "") { using namespace opentelemetry; - appd::core::sdkwrapper::OtelKeyValueMap argkeyValueMap = arg; + otel::core::sdkwrapper::OtelKeyValueMap argkeyValueMap = arg; bool valueMatches = true; for(auto &argKey:argkeyValueMap){ @@ -125,13 +125,13 @@ MATCHER_P(HasBoolValue, value, "") { TEST(TestRequestProcessingEngine, StartRequest) { FakeRequestProcessingEngine engine; - std::shared_ptr config; - auto spanNamer = std::make_shared(); + std::shared_ptr config; + auto spanNamer = std::make_shared(); engine.init(config, spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); std::string wscontext = "ws_context"; - appd::core::RequestPayload payload; + otel::core::RequestPayload payload; payload.set_http_headers("key", "value"); payload.set_request_protocol("GET"); payload.set_uri("dummy_span"); @@ -145,7 +145,7 @@ TEST(TestRequestProcessingEngine, StartRequest) payload.set_port(80); - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + otel::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"; @@ -155,12 +155,12 @@ TEST(TestRequestProcessingEngine, StartRequest) 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; + std::shared_ptr span; span.reset(new MockScopedSpan); // sdkwrapper's create span function should be called EXPECT_CALL(*sdkWrapper, CreateSpan("dummy_span", - appd::core::sdkwrapper::SpanKind::SERVER, + otel::core::sdkwrapper::SpanKind::SERVER, HasMapVal(keyValueMap), payload.get_http_headers())). WillOnce(Return(span)); @@ -168,9 +168,9 @@ TEST(TestRequestProcessingEngine, StartRequest) int* dummy = new int(2); void* reqHandle = dummy; auto res = engine.startRequest("ws_context", &payload, &reqHandle); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); - auto* reqContext = (appd::core::RequestContext*)(reqHandle); + auto* reqContext = (otel::core::RequestContext*)(reqHandle); ASSERT_TRUE(reqContext); EXPECT_TRUE(reqContext->rootSpan().get() != nullptr); EXPECT_EQ(reqContext->getContextName(), "ws_context"); @@ -183,21 +183,21 @@ TEST(TestRequestProcessingEngine, StartRequest) TEST(TestRequestProcessingEngine, StartRequestInvalidParams) { FakeRequestProcessingEngine engine; - auto spanNamer = std::make_shared(); - std::shared_ptr config; + auto spanNamer = std::make_shared(); + std::shared_ptr config; engine.init(config, spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); std::string wscontext = "ws_context"; - appd::core::RequestPayload payload; + otel::core::RequestPayload payload; auto res = engine.startRequest("ws_context", &payload, nullptr); - EXPECT_EQ(res, APPD_STATUS(handle_pointer_is_null)); + EXPECT_EQ(res, OTEL_STATUS(handle_pointer_is_null)); int* intPtr = new int(2); void* reqHandle = intPtr; res = engine.startRequest("ws_context", nullptr, &reqHandle); - EXPECT_EQ(res, APPD_STATUS(payload_reflector_is_null)); + EXPECT_EQ(res, OTEL_STATUS(payload_reflector_is_null)); delete(intPtr); } @@ -205,23 +205,23 @@ TEST(TestRequestProcessingEngine, StartRequestInvalidParams) TEST(TestRequestProcessingEngine, EndRequest) { FakeRequestProcessingEngine engine; - auto spanNamer = std::make_shared(); - std::shared_ptr config; + auto spanNamer = std::make_shared(); + std::shared_ptr config; engine.init(config, spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); - std::shared_ptr rootSpan; + std::shared_ptr rootSpan; rootSpan.reset(new MockScopedSpan); - auto* rContext = new appd::core::RequestContext(rootSpan); + auto* rContext = new otel::core::RequestContext(rootSpan); // adding some unfinished interactions - std::shared_ptr interactionSpan1, interactionSpan2; + std::shared_ptr interactionSpan1, interactionSpan2; interactionSpan1.reset(new MockScopedSpan); interactionSpan2.reset(new MockScopedSpan); rContext->addInteraction(interactionSpan1); rContext->addInteraction(interactionSpan2); - auto getMockSpan = [](std::shared_ptr span) { + auto getMockSpan = [](std::shared_ptr span) { return (MockScopedSpan*)(span.get()); }; @@ -233,7 +233,7 @@ TEST(TestRequestProcessingEngine, EndRequest) Times(1); unsigned int status_code = 403; - EXPECT_CALL(*getMockSpan(rootSpan), SetStatus(appd::core::sdkwrapper::StatusCode::Error, "HTTP ERROR CODE:403")).Times(1); + EXPECT_CALL(*getMockSpan(rootSpan), SetStatus(otel::core::sdkwrapper::StatusCode::Error, "HTTP ERROR CODE:403")).Times(1); EXPECT_CALL(*getMockSpan(rootSpan), AddAttribute(kAttrHTTPStatusCode, HasUnsignedIntValue(status_code))).Times(1); @@ -241,43 +241,43 @@ TEST(TestRequestProcessingEngine, EndRequest) EXPECT_CALL(*getMockSpan(rootSpan), End()). Times(1); - std::unique_ptr responsePayload - (new appd::core::ResponsePayload); + std::unique_ptr responsePayload + (new otel::core::ResponsePayload); responsePayload->status_code = status_code; auto res = engine.endRequest(rContext, "403", responsePayload.get()); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); } TEST(TestRequestProcessingEngine, EndRequestInvalidParams) { FakeRequestProcessingEngine engine; - std::shared_ptr config; - auto spanNamer = std::make_shared(); + std::shared_ptr config; + auto spanNamer = std::make_shared(); engine.init(config,spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); auto res = engine.endRequest(nullptr, "403"); - EXPECT_EQ(res, APPD_STATUS(fail)); + EXPECT_EQ(res, OTEL_STATUS(fail)); } TEST(TestRequestProcessingEngine, StartInteraction) { FakeRequestProcessingEngine engine; - std::shared_ptr config; - auto spanNamer = std::make_shared(); + std::shared_ptr config; + auto spanNamer = std::make_shared(); engine.init(config,spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); - appd::core::InteractionPayload payload; + otel::core::InteractionPayload payload; payload.moduleName = "module"; payload.phaseName = "phase"; - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + otel::core::sdkwrapper::OtelKeyValueMap keyValueMap; keyValueMap["interactionType"] = "EXIT_CALL"; - std::shared_ptr span; + std::shared_ptr span; span.reset(new MockScopedSpan); std::unordered_map propagationHeaders; @@ -286,7 +286,7 @@ TEST(TestRequestProcessingEngine, StartInteraction) // sdkwrapper's create span function should be called using testing::_; EXPECT_CALL(*sdkWrapper, CreateSpan("module_phase", - appd::core::sdkwrapper::SpanKind::CLIENT, + otel::core::sdkwrapper::SpanKind::CLIENT, HasMapVal(keyValueMap), emptyHeaders)). WillOnce(Return(span)); @@ -294,12 +294,12 @@ TEST(TestRequestProcessingEngine, StartInteraction) EXPECT_CALL(*sdkWrapper, PopulatePropagationHeaders(propagationHeaders)). Times(1); - std::shared_ptr rootSpan; + std::shared_ptr rootSpan; rootSpan.reset(new MockScopedSpan); - auto* rContext = new appd::core::RequestContext(rootSpan); + auto* rContext = new otel::core::RequestContext(rootSpan); auto res = engine.startInteraction((void*)(rContext), &payload, propagationHeaders); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); // Interaction will be added in requestContext EXPECT_TRUE(rContext->hasActiveInteraction()); @@ -308,54 +308,54 @@ TEST(TestRequestProcessingEngine, StartInteraction) TEST(TestRequestProcessingEngine, StartInteractionInvalidParams) { FakeRequestProcessingEngine engine; - std::shared_ptr config; - auto spanNamer = std::make_shared(); + std::shared_ptr config; + auto spanNamer = std::make_shared(); engine.init(config,spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); - appd::core::InteractionPayload payload; + otel::core::InteractionPayload payload; std::unordered_map propagationHeaders; // invalid request context auto res = engine.startInteraction(nullptr, &payload, propagationHeaders); - EXPECT_EQ(res, APPD_STATUS(handle_pointer_is_null)); + EXPECT_EQ(res, OTEL_STATUS(handle_pointer_is_null)); - std::shared_ptr rootSpan; + std::shared_ptr rootSpan; rootSpan.reset(new MockScopedSpan); - auto* rContext = new appd::core::RequestContext(rootSpan); + auto* rContext = new otel::core::RequestContext(rootSpan); // invalid payload res = engine.startInteraction((void*)(rContext), nullptr, propagationHeaders); - EXPECT_EQ(res, APPD_STATUS(payload_reflector_is_null)); + EXPECT_EQ(res, OTEL_STATUS(payload_reflector_is_null)); } TEST(TestRequestProcessingEngine, EndInteraction) { FakeRequestProcessingEngine engine; - std::shared_ptr config; - auto spanNamer = std::make_shared(); + std::shared_ptr config; + auto spanNamer = std::make_shared(); engine.init(config,spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); std::unordered_map propagationHeaders; - appd::core::InteractionPayload startPayload; - std::shared_ptr rootSpan; + otel::core::InteractionPayload startPayload; + std::shared_ptr rootSpan; rootSpan.reset(new MockScopedSpan); - auto* rContext = new appd::core::RequestContext(rootSpan); - std::shared_ptr interactionSpan; + auto* rContext = new otel::core::RequestContext(rootSpan); + std::shared_ptr interactionSpan; interactionSpan.reset(new MockScopedSpan); rContext->addInteraction(interactionSpan); - appd::core::EndInteractionPayload payload; + otel::core::EndInteractionPayload payload; payload.errorCode = 403; payload.errorMsg = "error_msg"; payload.backendName = "backend_one"; payload.backendType = "backend_type"; auto span = rContext->lastActiveInteraction(); - EXPECT_CALL(*(MockScopedSpan*)(span.get()), SetStatus(appd::core::sdkwrapper::StatusCode::Error, "error_msg")). + EXPECT_CALL(*(MockScopedSpan*)(span.get()), SetStatus(otel::core::sdkwrapper::StatusCode::Error, "error_msg")). Times(1); EXPECT_CALL(*(MockScopedSpan*)(span.get()), AddAttribute("error_code", HasLongIntValue(403))). Times(1); @@ -370,33 +370,33 @@ TEST(TestRequestProcessingEngine, EndInteraction) Times(1); auto res = engine.endInteraction(rContext, false, &payload); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); } TEST(TestRequestProcessingEngine, EndInteractionInvalidParams) { FakeRequestProcessingEngine engine; - std::shared_ptr config; - auto spanNamer = std::make_shared(); + std::shared_ptr config; + auto spanNamer = std::make_shared(); engine.init(config, spanNamer); auto* sdkWrapper = engine.getMockSdkWrapper(); ASSERT_TRUE(sdkWrapper); // invalid handle auto res = engine.endInteraction(nullptr, true, nullptr); - EXPECT_EQ(res, APPD_STATUS(handle_pointer_is_null)); + EXPECT_EQ(res, OTEL_STATUS(handle_pointer_is_null)); // invalid payload case - std::shared_ptr rootSpan; + std::shared_ptr rootSpan; rootSpan.reset(new MockScopedSpan); - auto* rContext = new appd::core::RequestContext(rootSpan); + auto* rContext = new otel::core::RequestContext(rootSpan); res = engine.endInteraction((void*)(rContext), true, nullptr); - EXPECT_EQ(res, APPD_STATUS(payload_reflector_is_null)); + EXPECT_EQ(res, OTEL_STATUS(payload_reflector_is_null)); // no interaction in the context - appd::core::EndInteractionPayload payload; + otel::core::EndInteractionPayload payload; res = engine.endInteraction(rContext, true, &payload); - EXPECT_EQ(res, APPD_STATUS(invalid_context)); + EXPECT_EQ(res, OTEL_STATUS(invalid_context)); } diff --git a/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp b/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp index 955913b61..418a460c1 100644 --- a/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/ScopedSpan_test.cpp @@ -26,7 +26,7 @@ #include using ::testing::Return; -using namespace appd::core::sdkwrapper; +using namespace otel::core::sdkwrapper; const std::string kTestSpanName{"TestSpanName"}; diff --git a/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp b/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp index 31f87c719..bd8bdb72d 100644 --- a/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/SdkUtils_test.cpp @@ -21,7 +21,7 @@ TEST(Get, ReturnsExpectedValueWhenKeyFound) std::unordered_map carrier {{"TestKey", "TestValue"}}; opentelemetry::nostd::string_view key = "TestKey"; - appd::core::sdkwrapper::OtelCarrier otelCarrier(carrier); + otel::core::sdkwrapper::OtelCarrier otelCarrier(carrier); auto value = otelCarrier.Get(key); EXPECT_EQ(value, "TestValue"); } @@ -31,7 +31,7 @@ TEST(Get, ReturnsEmptyWhenKeyNotFound) std::unordered_map carrier {{"TestKey", "TestValue"}}; opentelemetry::nostd::string_view key = "TestKey1"; - appd::core::sdkwrapper::OtelCarrier otelCarrier(carrier); + otel::core::sdkwrapper::OtelCarrier otelCarrier(carrier); auto value = otelCarrier.Get(key); EXPECT_EQ(value, ""); } @@ -41,7 +41,7 @@ TEST(Set, InsertsExpectedKeyAndValue) std::unordered_map carrier; opentelemetry::nostd::string_view key = "TestKey"; opentelemetry::nostd::string_view value = "TestValue"; - appd::core::sdkwrapper::OtelCarrier otelCarrier; + otel::core::sdkwrapper::OtelCarrier otelCarrier; otelCarrier.Set(key, value); EXPECT_EQ(otelCarrier.Get(key), value); } diff --git a/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp b/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp index 9828e929f..2fd7cd598 100644 --- a/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/SdkWrapper_test.cpp @@ -25,7 +25,7 @@ #include using ::testing::Return; -using namespace appd::core::sdkwrapper; +using namespace otel::core::sdkwrapper; using::testing::_; using ::testing::Args; @@ -35,7 +35,7 @@ MATCHER_P(HasLongIntValue, value, "") { TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Server) { - auto config = std::shared_ptr(new appd::core::TenantConfig); + auto config = std::shared_ptr(new otel::core::TenantConfig); FakeSdkWrapper sdkWrapper; sdkWrapper.Init(config); @@ -43,7 +43,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Server) dynamic_cast(sdkWrapper.GetMockSdkHelperFactory()); testing::Mock::AllowLeak(mockSdkHelperFactory); - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -56,7 +56,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Server) nostd::string_view testkey1 = "TestKey1"; nostd::string_view testSpanName = "TestSpanName"; auto kind = trace::SpanKind::kServer; - auto spanKind = appd::core::sdkwrapper::SpanKind::SERVER; + auto spanKind = otel::core::sdkwrapper::SpanKind::SERVER; std::unordered_map carrier {{"TestKey", "TestValue"}}; int64_t testvalue = 100; @@ -68,7 +68,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Server) EXPECT_CALL(*mockPropagator, ExtractImpl(_)).Times(1); EXPECT_CALL(*mockSdkHelperFactory, GetPropagators()). Times(1). - WillOnce(InvokeWithoutArgs([&]()-> appd::core::OtelPropagators&{ + WillOnce(InvokeWithoutArgs([&]()-> otel::core::OtelPropagators&{ return testOtelPropagators; })); @@ -92,7 +92,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Server) TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Client) { - auto config = std::shared_ptr(new appd::core::TenantConfig); + auto config = std::shared_ptr(new otel::core::TenantConfig); FakeSdkWrapper sdkWrapper; sdkWrapper.Init(config); @@ -100,7 +100,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Client) dynamic_cast(sdkWrapper.GetMockSdkHelperFactory()); testing::Mock::AllowLeak(mockSdkHelperFactory); - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -113,7 +113,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Client) nostd::string_view testkey1 = "TestKey1"; nostd::string_view testSpanName = "TestSpanName"; auto kind = trace::SpanKind::kClient; - auto spanKind = appd::core::sdkwrapper::SpanKind::CLIENT; + auto spanKind = otel::core::sdkwrapper::SpanKind::CLIENT; std::unordered_map carrier {{"TestKey", "TestValue"}}; int64_t testvalue = 100; @@ -142,7 +142,7 @@ TEST(SdkWrapper, SdkWrapper_CreateSpan_Kind_Client) TEST(SdkWrapper, SdkWrapper_PopulatePropagationHeaders) { - auto config = std::shared_ptr(new appd::core::TenantConfig); + auto config = std::shared_ptr(new otel::core::TenantConfig); FakeSdkWrapper sdkWrapper; sdkWrapper.Init(config); @@ -150,7 +150,7 @@ TEST(SdkWrapper, SdkWrapper_PopulatePropagationHeaders) dynamic_cast(sdkWrapper.GetMockSdkHelperFactory()); testing::Mock::AllowLeak(mockSdkHelperFactory); - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -163,7 +163,7 @@ TEST(SdkWrapper, SdkWrapper_PopulatePropagationHeaders) nostd::string_view testkey1 = "TestKey1"; nostd::string_view testSpanName = "TestSpanName"; auto kind = trace::SpanKind::kInternal; - auto spanKind = appd::core::sdkwrapper::SpanKind::INTERNAL; + auto spanKind = otel::core::sdkwrapper::SpanKind::INTERNAL; std::unordered_map carrier {{"TestKey", "TestValue"}}; int64_t testvalue = 100; @@ -191,7 +191,7 @@ TEST(SdkWrapper, SdkWrapper_PopulatePropagationHeaders) using ::testing::Invoke; EXPECT_CALL(*mockSdkHelperFactory, GetPropagators()). Times(1). - WillOnce(InvokeWithoutArgs([&]()-> appd::core::OtelPropagators&{ + WillOnce(InvokeWithoutArgs([&]()-> otel::core::OtelPropagators&{ return testOtelPropagators; })); EXPECT_CALL(*mockPropagator, InjectImpl(_)).Times(1); diff --git a/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp b/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp index d910e9182..a60d73c9e 100644 --- a/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/ServerSpan_test.cpp @@ -22,7 +22,7 @@ #include using ::testing::Return; -using namespace appd::core::sdkwrapper; +using namespace otel::core::sdkwrapper; using ::testing::_; MATCHER_P(HasLongIntValue, value, "") { @@ -32,7 +32,7 @@ MATCHER_P(HasLongIntValue, value, "") { TEST(ServerSpan, ServerSpan_Create) { MockSdkHelperFactory mockSdkHelperFactory; - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -56,7 +56,7 @@ TEST(ServerSpan, ServerSpan_Create) EXPECT_CALL(*mockPropagator, ExtractImpl(_)).Times(1); EXPECT_CALL(mockSdkHelperFactory, GetPropagators()). Times(1). - WillOnce(InvokeWithoutArgs([&]()-> appd::core::OtelPropagators&{ + WillOnce(InvokeWithoutArgs([&]()-> otel::core::OtelPropagators&{ return testOtelPropagators; })); @@ -81,7 +81,7 @@ TEST(ServerSpan, ServerSpan_Create) TEST(ServerSpan, ServerSpan_End) { MockSdkHelperFactory mockSdkHelperFactory; - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -105,7 +105,7 @@ TEST(ServerSpan, ServerSpan_End) EXPECT_CALL(*mockPropagator, ExtractImpl(_)).Times(1); EXPECT_CALL(mockSdkHelperFactory, GetPropagators()). Times(1). - WillOnce(InvokeWithoutArgs([&]()-> appd::core::OtelPropagators&{ + WillOnce(InvokeWithoutArgs([&]()-> otel::core::OtelPropagators&{ return testOtelPropagators; })); @@ -133,7 +133,7 @@ TEST(ServerSpan, ServerSpan_End) TEST(ServerSpan, ServerSpan_AddEvent) { MockSdkHelperFactory mockSdkHelperFactory; - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -157,7 +157,7 @@ TEST(ServerSpan, ServerSpan_AddEvent) EXPECT_CALL(*mockPropagator, ExtractImpl(_)).Times(1); EXPECT_CALL(mockSdkHelperFactory, GetPropagators()). Times(1). - WillOnce(InvokeWithoutArgs([&]()-> appd::core::OtelPropagators&{ + WillOnce(InvokeWithoutArgs([&]()-> otel::core::OtelPropagators&{ return testOtelPropagators; })); @@ -193,7 +193,7 @@ TEST(ServerSpan, ServerSpan_AddEvent) TEST(ServerSpan, ServerSpan_AddAttribute) { MockSdkHelperFactory mockSdkHelperFactory; - appd::core::OtelPropagators testOtelPropagators; + otel::core::OtelPropagators testOtelPropagators; testOtelPropagators.push_back(std::unique_ptr( new MockPropagator())); MockPropagator* mockPropagator = dynamic_cast @@ -217,7 +217,7 @@ TEST(ServerSpan, ServerSpan_AddAttribute) EXPECT_CALL(*mockPropagator, ExtractImpl(_)).Times(1); EXPECT_CALL(mockSdkHelperFactory, GetPropagators()). Times(1). - WillOnce(InvokeWithoutArgs([&]()-> appd::core::OtelPropagators&{ + WillOnce(InvokeWithoutArgs([&]()-> otel::core::OtelPropagators&{ return testOtelPropagators; })); diff --git a/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp b/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp index 6d83bef3e..8f69ef535 100644 --- a/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/SpanNamer_test.cpp @@ -19,7 +19,7 @@ TEST(SpanNamer, SpanNamerCreatedWithDefaultValues) { - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); auto spanName = spanNamer->getSpanName("/one/two/three/index.html"); EXPECT_EQ(spanName, "/one/two"); @@ -35,7 +35,7 @@ TEST(SpanNamer, SpanNamerCreatedWithDefaultValues) TEST(SpanNamer, SpanNamerCreatedWithFirstNSegments) { - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); spanNamer->setSegmentRules("First", "2"); auto spanName = spanNamer->getSpanName("/one/two/three/index.html"); @@ -60,7 +60,7 @@ TEST(SpanNamer, SpanNamerCreatedWithFirstNSegments) TEST(SpanNamer, SpanNamerCreatedWithLastNSegments) { - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); spanNamer->setSegmentRules("Last", "2"); auto spanName = spanNamer->getSpanName("/one/two/three/index.html"); @@ -89,7 +89,7 @@ TEST(SpanNamer, SpanNamerCreatedWithLastNSegments) TEST(SpanNamer, SpanNamerCreatedWithCustomSegments) { - auto spanNamer = std::make_shared(); + auto spanNamer = std::make_shared(); spanNamer->setSegmentRules("Custom", "2"); auto spanName = spanNamer->getSpanName("/one/two/three/index.html"); diff --git a/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp b/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp index 8fb9aaeb1..99406d1ca 100644 --- a/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/WSAgent_test.cpp @@ -23,7 +23,7 @@ #include "api/Payload.h" #include -class FakeWSAgent : public appd::core::WSAgent +class FakeWSAgent : public otel::core::WSAgent { public: MockAgentCore* getMockAgentCore() { return dynamic_cast(mAgentCore.get());} @@ -40,7 +40,7 @@ class FakeWSAgent : public appd::core::WSAgent } void addUserTenant( - const std::string& context, std::shared_ptr tenantConfig) + const std::string& context, std::shared_ptr tenantConfig) { mUserAddedTenant[context] = tenantConfig; } @@ -61,24 +61,24 @@ TEST(WSAgent, initialise_WSAgent_returns_success) bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, false); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(2, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(2, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; env[1].name = "Key2"; env[1].value = "Value2"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -86,7 +86,7 @@ TEST(WSAgent, initialise_WSAgent_returns_success) .WillOnce(Return(true)); res = agent.init(env, 2); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); @@ -104,24 +104,24 @@ TEST(WSAgent, initialise_WSAgent_returns_success_if_already_initialised) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(2, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(2, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; env[1].name = "Key2"; env[1].value = "Value2"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -129,13 +129,13 @@ TEST(WSAgent, initialise_WSAgent_returns_success_if_already_initialised) .WillOnce(Return(true)); res = agent.init(env, 2); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); res = agent.init(env, 2); - EXPECT_EQ(res, APPD_STATUS(already_initialized)); + EXPECT_EQ(res, OTEL_STATUS(already_initialized)); isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); @@ -153,24 +153,24 @@ TEST(WSAgent, initialise_WSAgent_returns_fail_on_init_boilerplate_failure) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(2, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(2, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; env[1].name = "Key2"; env[1].value = "Value2"; - APPD_SDK_STATUS_CODE res = APPD_STATUS(fail); + OTEL_SDK_STATUS_CODE res = OTEL_STATUS(fail); using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); res = agent.init(env, 2); - EXPECT_EQ(res, APPD_STATUS(fail)); + EXPECT_EQ(res, OTEL_STATUS(fail)); free(env); } @@ -185,29 +185,29 @@ TEST(WSAgent, initialise_WSAgent_returns_fail_on_agentcore_start_failure) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(2, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(2, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; env[1].name = "Key2"; env[1].value = "Value2"; - APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; - APPD_SDK_STATUS_CODE res2 = APPD_STATUS(fail); + OTEL_SDK_STATUS_CODE res1 = OTEL_SUCCESS; + OTEL_SDK_STATUS_CODE res2 = OTEL_STATUS(fail); using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res2; })); - APPD_SDK_STATUS_CODE res = agent.init(env, 2); - EXPECT_EQ(res, APPD_STATUS(fail)); + OTEL_SDK_STATUS_CODE res = agent.init(env, 2); + EXPECT_EQ(res, OTEL_STATUS(fail)); free(env); } @@ -222,31 +222,31 @@ TEST(WSAgent, initialise_WSAgent_returns_agent_failed_to_start_on_read_config_fa testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(2, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(2, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; env[1].name = "Key2"; env[1].value = "Value2"; - APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res1 = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); EXPECT_CALL(*agentCore, start(_,_,_)) .Times(1) .WillOnce(Return(false)); - APPD_SDK_STATUS_CODE res = agent.init(env, 2); - EXPECT_EQ(res, APPD_STATUS(agent_failed_to_start)); + OTEL_SDK_STATUS_CODE res = agent.init(env, 2); + EXPECT_EQ(res, OTEL_STATUS(agent_failed_to_start)); free(env); } @@ -261,26 +261,26 @@ TEST(WSAgent, initialise_WSAgent_returns_agent_failed_to_start_on_read_config_fa testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = NULL; + OTEL_SDK_ENV_RECORD* env = NULL; - APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res1 = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); EXPECT_CALL(*apiUtils, ReadFromEnvinronment(_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); EXPECT_CALL(*agentCore, start(_,_,_)) .Times(1) .WillOnce(Return(true)); - APPD_SDK_STATUS_CODE res = agent.init(env, 0); - EXPECT_EQ(res, APPD_STATUS(success)); + OTEL_SDK_STATUS_CODE res = agent.init(env, 0); + EXPECT_EQ(res, OTEL_STATUS(success)); }*/ TEST(WSAgent, start_request_executes_successfully) @@ -293,21 +293,21 @@ TEST(WSAgent, start_request_executes_successfully) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -315,31 +315,31 @@ TEST(WSAgent, start_request_executes_successfully) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); MockRequestProcessingEngine mockProcessor; - auto payload = std::unique_ptr(new appd::core::RequestPayload()); + auto payload = std::unique_ptr(new otel::core::RequestPayload()); std::string contextName {"contextName"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockProcessor; })); EXPECT_CALL(mockProcessor, startRequest(_,_,_)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); void* reqHandle = nullptr; const char* wscontext = "contextName"; res = agent.startRequest(wscontext, payload.get(), &reqHandle); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); free(env); } @@ -354,21 +354,21 @@ TEST(WSAgent, start_request_returns_fail) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -376,45 +376,45 @@ TEST(WSAgent, start_request_returns_fail) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); MockRequestProcessingEngine mockProcessor; - auto payload = std::unique_ptr(new appd::core::RequestPayload()); + auto payload = std::unique_ptr(new otel::core::RequestPayload()); std::string contextName {"contextName"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return nullptr; })); void* reqHandle = nullptr; const char* wscontext = "contextName"; res = agent.startRequest(wscontext, payload.get(), &reqHandle); - EXPECT_EQ(res, APPD_STATUS(fail)); + EXPECT_EQ(res, OTEL_STATUS(fail)); std::string contextName1 {"contextName1"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName1)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockProcessor; })); - APPD_SDK_STATUS_CODE res1 = APPD_STATUS(fail); + OTEL_SDK_STATUS_CODE res1 = OTEL_STATUS(fail); EXPECT_CALL(mockProcessor, startRequest(_,_,_)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); const char* wscontext1 = "contextName1"; res = agent.startRequest(wscontext1, payload.get(), &reqHandle); - EXPECT_EQ(res, APPD_STATUS(fail)); + EXPECT_EQ(res, OTEL_STATUS(fail)); free(env); } @@ -430,21 +430,21 @@ TEST(WSAgent, end_request_returns_success) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -452,7 +452,7 @@ TEST(WSAgent, end_request_returns_success) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); @@ -463,23 +463,23 @@ TEST(WSAgent, end_request_returns_success) std::string contextName1 {"contextName1"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName1)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockProcessor; })); - APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res1 = OTEL_SUCCESS; EXPECT_CALL(mockProcessor, endRequest(_,_,_)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); - auto reqCtx = new appd::core::RequestContext(); + auto reqCtx = new otel::core::RequestContext(); reqCtx->setContextName(contextName1); reqHandle = static_cast(reqCtx); const char* err = nullptr; res = agent.endRequest(reqHandle, err); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); free(env); delete reqCtx; @@ -495,21 +495,21 @@ TEST(WSAgent, start_interaction_returns_success) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -517,7 +517,7 @@ TEST(WSAgent, start_interaction_returns_success) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); @@ -528,26 +528,26 @@ TEST(WSAgent, start_interaction_returns_success) std::string contextName1 {"contextName1"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName1)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockProcessor; })); - APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res1 = OTEL_SUCCESS; EXPECT_CALL(mockProcessor, startInteractionImpl(_,_)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); - appd::core::InteractionPayload* payload = nullptr; + otel::core::InteractionPayload* payload = nullptr; std::unordered_map propagationHeaders; - auto reqCtx = new appd::core::RequestContext(); + auto reqCtx = new otel::core::RequestContext(); reqCtx->setContextName(contextName1); reqHandle = static_cast(reqCtx); res = agent.startInteraction(reqHandle, payload, propagationHeaders); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); free(env); delete reqCtx; @@ -563,21 +563,21 @@ TEST(WSAgent, end_interaction_returns_success) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -585,7 +585,7 @@ TEST(WSAgent, end_interaction_returns_success) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); @@ -596,25 +596,25 @@ TEST(WSAgent, end_interaction_returns_success) std::string contextName1 {"contextName1"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName1)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockProcessor; })); - APPD_SDK_STATUS_CODE res1 = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res1 = OTEL_SUCCESS; EXPECT_CALL(mockProcessor, endInteraction(_,_,_)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res1; })); - appd::core::EndInteractionPayload* payload = nullptr; + otel::core::EndInteractionPayload* payload = nullptr; - auto reqCtx = new appd::core::RequestContext(); + auto reqCtx = new otel::core::RequestContext(); reqCtx->setContextName(contextName1); reqHandle = static_cast(reqCtx); res = agent.endInteraction(reqHandle, true, payload); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); free(env); delete reqCtx; @@ -630,21 +630,21 @@ TEST(WSAgent, end_interaction_returns_failure) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -652,7 +652,7 @@ TEST(WSAgent, end_interaction_returns_failure) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); @@ -663,38 +663,38 @@ TEST(WSAgent, end_interaction_returns_failure) std::string contextName1 {"contextName1"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName1)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return nullptr; })); - appd::core::EndInteractionPayload* payload = nullptr; - auto reqCtx = new appd::core::RequestContext(); + otel::core::EndInteractionPayload* payload = nullptr; + auto reqCtx = new otel::core::RequestContext(); reqCtx->setContextName(contextName1); reqHandle = static_cast(reqCtx); res = agent.endInteraction(reqHandle, true, payload); - EXPECT_EQ(res, APPD_STATUS(fail)); + EXPECT_EQ(res, OTEL_STATUS(fail)); delete reqCtx; std::string contextName2 {"contextName2"}; EXPECT_CALL(*agentCore, getRequestProcessor(contextName2)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->appd::core::IRequestProcessingEngine*{ + .WillOnce(InvokeWithoutArgs([&]()->otel::core::IRequestProcessingEngine*{ return &mockProcessor; })); - APPD_SDK_STATUS_CODE res2 = APPD_STATUS(fail); + OTEL_SDK_STATUS_CODE res2 = OTEL_STATUS(fail); EXPECT_CALL(mockProcessor, endInteraction(_,_,_)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res2; })); - reqCtx = new appd::core::RequestContext(); + reqCtx = new otel::core::RequestContext(); reqCtx->setContextName(contextName2); reqHandle = static_cast(reqCtx); res = agent.endInteraction(reqHandle, true, payload); - EXPECT_EQ(res, APPD_STATUS(fail)); + EXPECT_EQ(res, OTEL_STATUS(fail)); free(env); @@ -712,7 +712,7 @@ TEST(WSAgent, add_wscontext_to_core_returns_failure_with_core_uninitialised) using ::testing::InvokeWithoutArgs; std::string contextName = ""; - appd::core::WSContextConfig contextConfig; + otel::core::WSContextConfig contextConfig; int res = agent.addWSContextToCore(contextName.c_str(), &contextConfig); // contextName is NULL EXPECT_EQ(res, -1); @@ -748,7 +748,7 @@ TEST(WSAgent, add_wscontext_to_core_returns_failure_with_core_uninitialised) contextConfig.serviceInstanceId = "testId"; - std::shared_ptr tenant = std::make_shared(); + std::shared_ptr tenant = std::make_shared(); tenant->setServiceNamespace(contextConfig.serviceNamespace); tenant->setServiceName(contextConfig.serviceName); tenant->setServiceInstanceId(contextConfig.serviceInstanceId); @@ -769,21 +769,21 @@ TEST(WSAgent, add_wscontext_to_core_returns_failure_with_core_initialised) testing::Mock::AllowLeak(agentCore); testing::Mock::AllowLeak(apiUtils); - APPD_SDK_ENV_RECORD* env = (APPD_SDK_ENV_RECORD*)calloc(1, sizeof(APPD_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env = (OTEL_SDK_ENV_RECORD*)calloc(1, sizeof(OTEL_SDK_ENV_RECORD)); env[0].name = "Key1"; env[0].value = "Value1"; - APPD_SDK_STATUS_CODE res = APPD_SUCCESS; + OTEL_SDK_STATUS_CODE res = OTEL_SUCCESS; using testing::_; using ::testing::InvokeWithoutArgs; EXPECT_CALL(*apiUtils, init_boilerplate()) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*apiUtils, ReadFromPassedSettings(_,_,_,_)) - .WillOnce(InvokeWithoutArgs([&]()->APPD_SDK_STATUS_CODE{ + .WillOnce(InvokeWithoutArgs([&]()->OTEL_SDK_STATUS_CODE{ return res; })); EXPECT_CALL(*agentCore, start(_,_,_)) @@ -791,13 +791,13 @@ TEST(WSAgent, add_wscontext_to_core_returns_failure_with_core_initialised) .WillOnce(Return(true)); res = agent.init(env, 1); - EXPECT_EQ(res, APPD_SUCCESS); + EXPECT_EQ(res, OTEL_SUCCESS); bool isInit = agent.isInitialised(); EXPECT_EQ(isInit, true); std::string contextName1 = "testContextName1"; - appd::core::WSContextConfig contextConfig; + otel::core::WSContextConfig contextConfig; contextConfig.serviceNamespace = "testNamespace"; contextConfig.serviceName = "testName"; @@ -807,14 +807,14 @@ TEST(WSAgent, add_wscontext_to_core_returns_failure_with_core_initialised) EXPECT_CALL(*agentCore, getWebServerContext(contextName1)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return mockContext; })); - std::shared_ptr tenant = std::make_shared (); + std::shared_ptr tenant = std::make_shared (); EXPECT_CALL(*mockContext, getConfig()) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return tenant; })); @@ -824,7 +824,7 @@ TEST(WSAgent, add_wscontext_to_core_returns_failure_with_core_initialised) std::string contextName2 = "testContextName2"; EXPECT_CALL(*agentCore, getWebServerContext(contextName2)) .Times(1) - .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ + .WillOnce(InvokeWithoutArgs([&]()->std::shared_ptr{ return nullptr; })); diff --git a/instrumentation/otel-webserver-module/test/unit/integration_test.cpp b/instrumentation/otel-webserver-module/test/unit/integration_test.cpp index 88ef49232..f901db2d0 100644 --- a/instrumentation/otel-webserver-module/test/unit/integration_test.cpp +++ b/instrumentation/otel-webserver-module/test/unit/integration_test.cpp @@ -22,8 +22,8 @@ #include -std::shared_ptr getConfig() { - auto config = std::shared_ptr(new appd::core::TenantConfig()); +std::shared_ptr getConfig() { + auto config = std::shared_ptr(new otel::core::TenantConfig()); config->setServiceName("dummy_webserver"); config->setServiceNamespace("dummy_service_namespace"); config->setServiceInstanceId("dummy_instance_id"); @@ -35,20 +35,20 @@ std::shared_ptr getConfig() { TEST(IntegrationTest, StartRequest) { - appd::core::RequestProcessingEngine engine; - auto spanNamer = std::make_shared(); + otel::core::RequestProcessingEngine engine; + auto spanNamer = std::make_shared(); auto config = getConfig(); engine.init(config, spanNamer); std::string wscontext = "ws_context"; - appd::core::RequestPayload payload; + otel::core::RequestPayload payload; payload.set_http_headers("key", "value"); payload.set_uri("dummy_span"); payload.set_request_protocol("GET"); - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + otel::core::sdkwrapper::OtelKeyValueMap keyValueMap; keyValueMap["request_protocol"] = "GET"; - std::shared_ptr span; + std::shared_ptr span; span.reset(new MockScopedSpan); int* dummy = new int(2); @@ -56,12 +56,12 @@ TEST(IntegrationTest, StartRequest) std::cout << "calling startReq" << std::endl; for (int i = 0; i < 20; i++) { auto res = engine.startRequest("ws_context", &payload, &reqHandle); - EXPECT_EQ(res, APPD_SUCCESS); - appd::core::InteractionPayload iPayload; + EXPECT_EQ(res, OTEL_SUCCESS); + otel::core::InteractionPayload iPayload; iPayload.moduleName = "module"; iPayload.phaseName = "phase"; - appd::core::sdkwrapper::OtelKeyValueMap keyValueMap; + otel::core::sdkwrapper::OtelKeyValueMap keyValueMap; keyValueMap["interactionType"] = "EXIT_CALL"; diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_OpenTelemetry.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_OpenTelemetry.h index 3b4629516..519bce667 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_OpenTelemetry.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_OpenTelemetry.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h index cb8c376c8..44153dad3 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_RequestProcessingEngine.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,36 +18,36 @@ #include "api/Payload.h" #include "api/TenantConfig.h" -class MockRequestProcessingEngine : public appd::core::IRequestProcessingEngine +class MockRequestProcessingEngine : public otel::core::IRequestProcessingEngine { public: - MOCK_METHOD(void, init, (std::shared_ptr& config, - std::shared_ptr spanNamer), (override)); + MOCK_METHOD(void, init, (std::shared_ptr& config, + std::shared_ptr spanNamer), (override)); - MOCK_METHOD(APPD_SDK_STATUS_CODE, startRequest, ( + MOCK_METHOD(OTEL_SDK_STATUS_CODE, startRequest, ( const std::string& wscontext, - appd::core::RequestPayload* payload, - APPD_SDK_HANDLE_REQ* reqHandle), (override)); + otel::core::RequestPayload* payload, + OTEL_SDK_HANDLE_REQ* reqHandle), (override)); - MOCK_METHOD(APPD_SDK_STATUS_CODE, endRequest, ( - APPD_SDK_HANDLE_REQ reqHandle, + MOCK_METHOD(OTEL_SDK_STATUS_CODE, endRequest, ( + OTEL_SDK_HANDLE_REQ reqHandle, const char* error, - const appd::core::ResponsePayload* payload), (override)); + const otel::core::ResponsePayload* payload), (override)); - APPD_SDK_STATUS_CODE startInteraction( - APPD_SDK_HANDLE_REQ reqHandle, - const appd::core::InteractionPayload* payload, + OTEL_SDK_STATUS_CODE startInteraction( + OTEL_SDK_HANDLE_REQ reqHandle, + const otel::core::InteractionPayload* payload, std::unordered_map& propagationHeaders) override { return startInteractionImpl(reqHandle, payload); }; - MOCK_METHOD(APPD_SDK_STATUS_CODE, startInteractionImpl, ( - APPD_SDK_HANDLE_REQ reqHandle, - const appd::core::InteractionPayload* payload)); + MOCK_METHOD(OTEL_SDK_STATUS_CODE, startInteractionImpl, ( + OTEL_SDK_HANDLE_REQ reqHandle, + const otel::core::InteractionPayload* payload)); - MOCK_METHOD(APPD_SDK_STATUS_CODE, endInteraction, ( - APPD_SDK_HANDLE_REQ reqHandle, + MOCK_METHOD(OTEL_SDK_STATUS_CODE, endInteraction, ( + OTEL_SDK_HANDLE_REQ reqHandle, bool ignoreBackend, - appd::core::EndInteractionPayload *payload), (override)); + otel::core::EndInteractionPayload *payload), (override)); }; diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_SdkHelperFactory.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_SdkHelperFactory.h index f46981d7a..cb40cc92f 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_SdkHelperFactory.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_SdkHelperFactory.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,10 +19,10 @@ #include #include "sdkwrapper/ISdkHelperFactory.h" -class MockSdkHelperFactory : public appd::core::sdkwrapper::ISdkHelperFactory +class MockSdkHelperFactory : public otel::core::sdkwrapper::ISdkHelperFactory { public: - MOCK_METHOD(appd::core::OtelTracer, GetTracer, (), (override)); - MOCK_METHOD(appd::core::OtelPropagators&, GetPropagators, (), (override)); + MOCK_METHOD(otel::core::OtelTracer, GetTracer, (), (override)); + MOCK_METHOD(otel::core::OtelPropagators&, GetPropagators, (), (override)); }; #endif \ No newline at end of file diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_core.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_core.h index 9e7973153..7869bce0d 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_core.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_core.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,73 +18,73 @@ #include "api/ApiUtils.h" #include "api/RequestProcessingEngine.h" -class MockAgentCore : public appd::core::ICore +class MockAgentCore : public otel::core::ICore { public: MOCK_METHOD(bool, start, - (std::shared_ptr initConfig, - std::shared_ptr spanNamer, + (std::shared_ptr initConfig, + std::shared_ptr spanNamer, userAddedTenantMap& userAddedTenants), (override)); MOCK_METHOD(void, stop, (), (override)); - MOCK_METHOD(appd::core::IRequestProcessingEngine*, getRequestProcessor, + MOCK_METHOD(otel::core::IRequestProcessingEngine*, getRequestProcessor, (std::string& name), (override)); MOCK_METHOD(void, addContext, (const std::string& contextName, - std::shared_ptr newConfig), + std::shared_ptr newConfig), (override)); - MOCK_METHOD(std::shared_ptr, + MOCK_METHOD(std::shared_ptr, getWebServerContext, (std::string& name), (override)); }; -class MockApiUtils : public appd::core::IApiUtils +class MockApiUtils : public otel::core::IApiUtils { public: - MOCK_METHOD(APPD_SDK_STATUS_CODE, init_boilerplate, (), (override)); + MOCK_METHOD(OTEL_SDK_STATUS_CODE, init_boilerplate, (), (override)); - MOCK_METHOD(APPD_SDK_STATUS_CODE, ReadFromPassedSettings, - (APPD_SDK_ENV_RECORD* env, + MOCK_METHOD(OTEL_SDK_STATUS_CODE, ReadFromPassedSettings, + (OTEL_SDK_ENV_RECORD* env, unsigned numberOfRecords, - appd::core::TenantConfig& tenantConfig, - appd::core::SpanNamer& spanNamer), (override)); - /*MOCK_METHOD(APPD_SDK_STATUS_CODE, ReadFromEnvinronment, - (appd::core::TenantConfig& tenantConfig), (override));*/ - MOCK_METHOD(APPD_SDK_STATUS_CODE, ReadSettingsFromReader, - (appd::core::IEnvReader& reader, appd::core::TenantConfig& tenantConfig, - appd::core::SpanNamer& spanNamer), (override)); - /*MOCK_METHOD(APPD_SDK_STATUS_CODE, ReadMandatoryFromReader, - (appd::core::IEnvReader& reader, const std::string& varName, unsigned short& result), + otel::core::TenantConfig& tenantConfig, + otel::core::SpanNamer& spanNamer), (override)); + /*MOCK_METHOD(OTEL_SDK_STATUS_CODE, ReadFromEnvinronment, + (otel::core::TenantConfig& tenantConfig), (override));*/ + MOCK_METHOD(OTEL_SDK_STATUS_CODE, ReadSettingsFromReader, + (otel::core::IEnvReader& reader, otel::core::TenantConfig& tenantConfig, + otel::core::SpanNamer& spanNamer), (override)); + /*MOCK_METHOD(OTEL_SDK_STATUS_CODE, ReadMandatoryFromReader, + (otel::core::IEnvReader& reader, const std::string& varName, unsigned short& result), (override));*/ - MOCK_METHOD(APPD_SDK_STATUS_CODE, ReadOptionalFromReader, - (appd::core::IEnvReader& reader, const std::string& varName, bool& result), + MOCK_METHOD(OTEL_SDK_STATUS_CODE, ReadOptionalFromReader, + (otel::core::IEnvReader& reader, const std::string& varName, bool& result), (override)); - MOCK_METHOD(APPD_SDK_STATUS_CODE, ReadOptionalFromReader, - (appd::core::IEnvReader& reader, const std::string& varName, unsigned int& result), + MOCK_METHOD(OTEL_SDK_STATUS_CODE, ReadOptionalFromReader, + (otel::core::IEnvReader& reader, const std::string& varName, unsigned int& result), (override)); }; -class MockAgentKernel : public appd::core::IKernel +class MockAgentKernel : public otel::core::IKernel { public: MOCK_METHOD(void, initKernel, - (std::shared_ptr config, - std::shared_ptr spanNamer), (override)); + (std::shared_ptr config, + std::shared_ptr spanNamer), (override)); - MOCK_METHOD(appd::core::IRequestProcessingEngine*, getRequestProcessingEngine, + MOCK_METHOD(otel::core::IRequestProcessingEngine*, getRequestProcessingEngine, (), (override)); }; -class MockContext : public appd::core::IContext +class MockContext : public otel::core::IContext { public: MOCK_METHOD(void, initContext, - (std::shared_ptr spanNamer), (override)); + (std::shared_ptr spanNamer), (override)); - MOCK_METHOD(appd::core::IKernel*, getKernel, (), (const, override)); + MOCK_METHOD(otel::core::IKernel*, getKernel, (), (const, override)); - MOCK_METHOD(std::shared_ptr, getConfig, (), (override)); + MOCK_METHOD(std::shared_ptr, getConfig, (), (override)); }; diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_dummy.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_dummy.h index 140f68243..f45c261fa 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_dummy.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_dummy.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h index 7f9ee9dc5..f1a664b3c 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h @@ -1,5 +1,5 @@ /* -* Copyright 2021 AppDynamics LLC. +* Copyright 2022, OpenTelemetry Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ #include "sdkwrapper/SdkWrapper.h" #include "mock_SdkHelperFactory.h" -class MockScopedSpan : public appd::core::sdkwrapper::IScopedSpan +class MockScopedSpan : public otel::core::sdkwrapper::IScopedSpan { public: MOCK_METHOD(void, End, @@ -29,46 +29,46 @@ class MockScopedSpan : public appd::core::sdkwrapper::IScopedSpan MOCK_METHOD(void, AddEvent, (const std::string& name, const std::chrono::system_clock::time_point &timePoint, - const appd::core::sdkwrapper::OtelKeyValueMap& attributes), + const otel::core::sdkwrapper::OtelKeyValueMap& attributes), (override)); MOCK_METHOD(void, AddAttribute, (const std::string& key, - const appd::core::sdkwrapper::SpanAttributeValue& value), + const otel::core::sdkwrapper::SpanAttributeValue& value), (override, noexcept)); MOCK_METHOD(void, SetStatus, - (const appd::core::sdkwrapper::StatusCode code, + (const otel::core::sdkwrapper::StatusCode code, const std::string& desc), (override)); - MOCK_METHOD(appd::core::sdkwrapper::SpanKind, GetSpanKind, + MOCK_METHOD(otel::core::sdkwrapper::SpanKind, GetSpanKind, (), (override)); }; // TODO : General MOCK_METHOD command is giving some unexpected errors. Revisit later -class MockSdkWrapper : public appd::core::sdkwrapper::ISdkWrapper +class MockSdkWrapper : public otel::core::sdkwrapper::ISdkWrapper { public: - void Init(std::shared_ptr) override {} + void Init(std::shared_ptr) override {} MOCK_METHOD1(PopulatePropagationHeaders, void(std::unordered_map& carrier)); - MOCK_METHOD4(CreateSpan, std::shared_ptr( + MOCK_METHOD4(CreateSpan, std::shared_ptr( const std::string& name, - const appd::core::sdkwrapper::SpanKind& kind, - const appd::core::sdkwrapper::OtelKeyValueMap& attributes, + const otel::core::sdkwrapper::SpanKind& kind, + const otel::core::sdkwrapper::OtelKeyValueMap& attributes, const std::unordered_map& carrier)); }; -class FakeSdkWrapper : public appd::core::sdkwrapper::SdkWrapper +class FakeSdkWrapper : public otel::core::sdkwrapper::SdkWrapper { public: - void Init(std::shared_ptr config) + void Init(std::shared_ptr config) { mSdkHelperFactory = std::unique_ptr(new MockSdkHelperFactory); } - appd::core::sdkwrapper::ISdkHelperFactory* GetMockSdkHelperFactory() + otel::core::sdkwrapper::ISdkHelperFactory* GetMockSdkHelperFactory() { return mSdkHelperFactory.get(); } From 79138f3cffc8bd6d0b29e1b783c933d26e4c88b3 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Mon, 5 Dec 2022 16:02:22 +0530 Subject: [PATCH 38/77] Web engine (#217) * Changing to webEngine * Removing error * Adding CPP * Adding Otel CPP Version * Rectifying TestCase * cpp add * changing to cpp --- instrumentation/otel-webserver-module/build.gradle | 3 +++ .../include/core/sdkwrapper/SdkConstants.h | 5 +++-- .../src/core/sdkwrapper/SdkHelperFactory.cpp | 13 +++++++++---- .../src/module_version_template.h | 4 ++++ .../src/test/java/restutils/ValidationUtils.java | 2 +- .../otel-webserver-module/version.properties | 1 + 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/instrumentation/otel-webserver-module/build.gradle b/instrumentation/otel-webserver-module/build.gradle index c07d8500d..350325dd9 100644 --- a/instrumentation/otel-webserver-module/build.gradle +++ b/instrumentation/otel-webserver-module/build.gradle @@ -39,6 +39,7 @@ project.ext { props.load(new FileInputStream(file("version.properties"))) moduleVersion = props.get("server-module-version") moduleRelease = props.get("release") + cppSDKVersion = props.get("CPP-SDK-version") moduleName = "WebServer Module" buildType = "Release Build" fullVersion = "${moduleName} ${moduleVersion} ${moduleRelease} ${headSHA1}: ${buildType}" @@ -87,6 +88,7 @@ task generateModuleVersionHeader(type: Copy) { headSHA1: headSHA1, moduleVersion: moduleVersion, moduleRelease: moduleRelease, + cppSDKVersion: cppSDKVersion, fullVersion: fullVersion) } @@ -100,6 +102,7 @@ task generateVersionFile(type: Copy) { headSHA1: headSHA1, moduleVersion: moduleVersion, moduleRelease: moduleRelease, + cppSDKVersion: cppSDKVersion, fullVersion: fullVersion) } diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h index 99cc237d9..bd8092939 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkConstants.h @@ -22,8 +22,9 @@ namespace sdkwrapper { const std::string kServiceName = "service.name"; const std::string kServiceNamespace = "service.namespace"; const std::string kServiceInstanceId = "service.instance.id"; -const std::string kOtelLibraryName = "telemetry.sdk.language"; -const std::string kOtelLibraryVersion = "telemetry.sdk.version"; +const std::string kOtelWebEngineName = "webengine.name"; +const std::string kOtelWebEngineVersion = "webengine.version"; +const std::string kOtelWebEngineDescription = "webengine.description"; const std::string kHttpErrorCode = "HTTP ERROR CODE:"; const std::string kAttrHTTPServerName = "http.server_name"; const std::string kAttrHTTPMethod = "http.method"; diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp index 2962bb375..f22ac7844 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp @@ -66,12 +66,17 @@ SdkHelperFactory::SdkHelperFactory( // NOTE : resource attribute values are nostd::variant and so we need to explicitely set it to std::string std::string libraryVersion = MODULE_VERSION; + std::string cppSDKVersion = CPP_SDK_VERSION; // NOTE : InstrumentationLibrary code is incomplete for the otlp exporter in sdk. // So, we need to pass libraryName and libraryVersion as resource attributes. // Ref : https://github.com/open-telemetry/opentelemetry-cpp/blob/main/exporters/otlp/src/otlp_recordable.cc - attributes[kOtelLibraryName] = config->getOtelLibraryName(); - attributes[kOtelLibraryVersion] = libraryVersion; + + //Library was changed to webengine to comply with specs https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/webengine.md + attributes[kOtelWebEngineName] = config->getOtelLibraryName(); + //attributes[kOtelWebEngineVersion] = libraryVersion; + + //attributes[kOtelWebEngineDescription] = config->getOtelLibraryName() + " Instrumentation"; auto exporter = GetExporter(config); auto processor = GetSpanProcessor(config, std::move(exporter)); @@ -84,9 +89,9 @@ SdkHelperFactory::SdkHelperFactory( std::move(sampler) )); - mTracer = mTracerProvider->GetTracer(config->getOtelLibraryName(), libraryVersion); + mTracer = mTracerProvider->GetTracer("cpp", cppSDKVersion); LOG4CXX_INFO(mLogger, - "Tracer created with LibraryName: " << config->getOtelLibraryName() << + "Tracer created with LibraryName: " << "cpp" << " and LibraryVersion " << libraryVersion); // Adding trace propagator diff --git a/instrumentation/otel-webserver-module/src/module_version_template.h b/instrumentation/otel-webserver-module/src/module_version_template.h index 8c019325d..3c0da13ca 100644 --- a/instrumentation/otel-webserver-module/src/module_version_template.h +++ b/instrumentation/otel-webserver-module/src/module_version_template.h @@ -5,6 +5,7 @@ #define MODULE_VERSION_ "$moduleVersion" #define RELEASE_ "$moduleRelease" #define FULL_MODULE_VERSION_ "$fullVersion" +#define CPP_SDK_VERSION_ "$cppSDKVersion" static const char MODULE_VERSION[] = MODULE_VERSION_ RELEASE_ MODULE_SHA1; @@ -12,5 +13,8 @@ static const char MODULE_VERSION[] = static const char FULL_MODULE_VERSION[] = FULL_MODULE_VERSION_; +static const char CPP_SDK_VERSION[] = + CPP_SDK_VERSION_; + #endif diff --git a/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java index 24020d64d..7fd310c9f 100644 --- a/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java +++ b/instrumentation/otel-webserver-module/test/integration/src/test/java/restutils/ValidationUtils.java @@ -33,7 +33,7 @@ public void verifyAllTraces() { } Assert.assertTrue(span.getJSONObject("tags").get("service.namespace").toString().contentEquals("sample_namespace")); Assert.assertTrue(span.getJSONObject("localEndpoint").get("serviceName").toString().contentEquals("demoservice")); - Assert.assertTrue(span.getJSONObject("tags").get("telemetry.sdk.language").toString().contentEquals("Apache")); + Assert.assertTrue(span.getJSONObject("tags").get("telemetry.sdk.language").toString().contentEquals("cpp")); } } diff --git a/instrumentation/otel-webserver-module/version.properties b/instrumentation/otel-webserver-module/version.properties index cc32e12eb..9bb77a709 100644 --- a/instrumentation/otel-webserver-module/version.properties +++ b/instrumentation/otel-webserver-module/version.properties @@ -1,3 +1,4 @@ server-module-version=1.0.0 release=GA nginxSupportedVersions=1.22.0,1.23.0,1.23.1 +CPP-SDK-version=1.2.0 From 5c0cc9c88b60ec48d0f6f8a11523c97d9079a9f8 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Tue, 6 Dec 2022 14:22:28 +0530 Subject: [PATCH 39/77] Update version.properties (#244) --- instrumentation/otel-webserver-module/version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/otel-webserver-module/version.properties b/instrumentation/otel-webserver-module/version.properties index 9bb77a709..8e477b32d 100644 --- a/instrumentation/otel-webserver-module/version.properties +++ b/instrumentation/otel-webserver-module/version.properties @@ -1,4 +1,4 @@ -server-module-version=1.0.0 +server-module-version=1.0.3 release=GA nginxSupportedVersions=1.22.0,1.23.0,1.23.1 CPP-SDK-version=1.2.0 From 6344bb827991d16af4c37c4b4196e7d8937bf244 Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Wed, 14 Dec 2022 12:05:15 +0530 Subject: [PATCH 40/77] Removed unwanted logs even if NginxModuleTraceAsError is set as false (#246) --- .../src/nginx/ngx_http_opentelemetry_module.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index aef0c5105..bbcf7ad0b 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -1118,7 +1118,7 @@ static void stopMonitoringRequest(ngx_http_request_t* r, if (OTEL_ISSUCCESS(res)) { - ngx_writeError(r->connection->log, __func__, "Request Ends with result code: %d", res); + ngx_writeTrace(r->connection->log, __func__, "Request Ends with result code: %d", res); } else { @@ -1150,7 +1150,7 @@ static void startMonitoringRequest(ngx_http_request_t* r){ return; } - ngx_writeError(r->connection->log, __func__, "Starting Request Monitoring for: %s", r->uri.data); + ngx_writeTrace(r->connection->log, __func__, "Starting Request Monitoring for: %s", r->uri.data); // Handle request for static contents (Nginx is used for habdling static contents) @@ -1193,7 +1193,6 @@ static void startMonitoringRequest(ngx_http_request_t* r){ if (ctx == NULL) { ngx_writeError(r->connection->log, __func__, "Cannot allocate memory for handles"); - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Cannot allocate memory for handles"); return; } // Store the Request Handle on the request object From ba0094b43428a7020777848c1218143098f1221d Mon Sep 17 00:00:00 2001 From: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> Date: Thu, 15 Dec 2022 13:24:20 +0530 Subject: [PATCH 41/77] Removed appd related terminology (#245) --- .../otel-webserver-module/build.gradle | 25 ++++---- .../dist/Install_Native.txt | 27 -------- .../otel-webserver-module/dist/install.sh | 18 +++--- ...=> opentelemetry_sdk_log4cxx.xml.template} | 6 +- .../include/apache/ApacheHooks.h | 3 +- .../include/core/api/ApiUtils.h | 2 +- .../include/core/api/Interface.h | 2 +- .../{AppdynamicsSdk.h => OpentelemetrySdk.h} | 6 +- .../core/api/RequestProcessingEngine.h | 2 +- .../include/core/api/WSAgent.h | 2 +- .../src/apache/HookContainer.cpp | 1 - .../src/apache/apache.gyp | 4 +- .../otel-webserver-module/src/build.gyp | 30 ++++----- .../src/core/api/ApiUtils.cpp | 4 +- .../src/core/api/WSAgent.cpp | 2 +- .../src/core/api/opentelemetry_ngx_api.cpp | 2 +- .../src/nginx/ngx_http_opentelemetry_module.c | 2 +- .../src/nginx/ngx_http_opentelemetry_module.h | 4 +- .../test/NginxTesting.sh | 64 +++++++++---------- .../test/unit/unit_test.gyp | 16 ++--- 20 files changed, 97 insertions(+), 125 deletions(-) delete mode 100644 instrumentation/otel-webserver-module/dist/Install_Native.txt rename instrumentation/otel-webserver-module/dist/{appdynamics_sdk_log4cxx.xml.template => opentelemetry_sdk_log4cxx.xml.template} (87%) rename instrumentation/otel-webserver-module/include/core/api/{AppdynamicsSdk.h => OpentelemetrySdk.h} (98%) diff --git a/instrumentation/otel-webserver-module/build.gradle b/instrumentation/otel-webserver-module/build.gradle index 350325dd9..5f8ea4a41 100644 --- a/instrumentation/otel-webserver-module/build.gradle +++ b/instrumentation/otel-webserver-module/build.gradle @@ -145,6 +145,7 @@ task gypLibrary(type: Exec) { BOOST_LIB: BOOST_LIB, BOOST_INCLUDE: BOOST_INCLUDE, LIBRARY_FLAGS: libraryFlags, + CPP_SDK_VERSION: cppSDKVersion, ] environment libraryBuildEnvironment @@ -181,15 +182,14 @@ task stageLibrary(type: Copy) { from("dist/runSDKProxy.sh") { it.fileMode 0770 } - from("src/sdk_lib/src/api/include/appdynamics.h") { it.into "sdk_lib" } from(buildLibrary) { it.into "sdk_lib/lib" } - from("${modDepDir}/opentelemetry/1.2.0/lib/libopentelemetry_common.so") { it.into "sdk_lib/lib" } - from("${modDepDir}/opentelemetry/1.2.0/lib/libopentelemetry_resources.so") { it.into "sdk_lib/lib" } - from("${modDepDir}/opentelemetry/1.2.0/lib/libopentelemetry_trace.so") { it.into "sdk_lib/lib" } - from("${modDepDir}/opentelemetry/1.2.0/lib/libopentelemetry_otlp_recordable.so") { it.into "sdk_lib/lib" } - from("${modDepDir}/opentelemetry/1.2.0/lib/libopentelemetry_exporter_ostream_span.so") { it.into "sdk_lib/lib" } - from("${modDepDir}/opentelemetry/1.2.0/lib/libopentelemetry_exporter_otlp_grpc.so") { it.into "sdk_lib/lib" } - from("dist/appdynamics_sdk_log4cxx.xml.template") { it.into "conf" } + from("${modDepDir}/opentelemetry/${cppSDKVersion}/lib/libopentelemetry_common.so") { it.into "sdk_lib/lib" } + from("${modDepDir}/opentelemetry/${cppSDKVersion}/lib/libopentelemetry_resources.so") { it.into "sdk_lib/lib" } + from("${modDepDir}/opentelemetry/${cppSDKVersion}/lib/libopentelemetry_trace.so") { it.into "sdk_lib/lib" } + from("${modDepDir}/opentelemetry/${cppSDKVersion}/lib/libopentelemetry_otlp_recordable.so") { it.into "sdk_lib/lib" } + from("${modDepDir}/opentelemetry/${cppSDKVersion}/lib/libopentelemetry_exporter_ostream_span.so") { it.into "sdk_lib/lib" } + from("${modDepDir}/opentelemetry/${cppSDKVersion}/lib/libopentelemetry_exporter_otlp_grpc.so") { it.into "sdk_lib/lib" } + from("dist/opentelemetry_sdk_log4cxx.xml.template") { it.into "conf" } from("dist/install.${scriptExt}") { it.fileMode 0700 } into libraryStageDir @@ -295,7 +295,7 @@ task gypApacheModule(type: Exec) { ARCH_FLAG: gccArchFlag, APACHE22_INCLUDE_DIR: "${platBuildDir}/httpd-${apache22Version}/include", APACHE24_INCLUDE_DIR: "${platBuildDir}/httpd-${apache24Version}/include", - APPD_SDK_LIB_DIR: "${libraryStageDir}/sdk_lib", + OTEL_SDK_LIB_DIR: "${libraryStageDir}/sdk_lib", ANSDK_DIR: modDepDir, COMPILER_FLAGS: (coverageEnabled) ? coverageCompilerFlags : '', LINKER_FLAGS: (coverageEnabled) ? coverageLinkerFlags : '', @@ -495,13 +495,14 @@ task gypUnitTest(type: Exec) { outputs.file "${platBuildDir}/unit_test/Makefile" ext.testBuildEnvironment = [ - APPD_SDK_LIB_DIR: "${libraryStageDir}/sdk_lib", + OTEL_SDK_LIB_DIR: "${libraryStageDir}/sdk_lib", ANSDK_DIR: modDepDir, BOOST_LIB: BOOST_LIB, BOOST_INCLUDE: BOOST_INCLUDE, GTEST_LIB_DIR: target_system == "ubuntu" ? "${modDepDir}/googletest/1.10.0/lib" : "${modDepDir}/googletest/1.10.0/lib64", LIBRARY_FLAGS: libraryFlags, + CPP_SDK_VERSION: cppSDKVersion, ] environment testBuildEnvironment @@ -634,9 +635,9 @@ model { repositories { libs(PrebuiltLibraries) { libs -> - appd { + otel { headers.srcDirs "${libraryStageDir}/sdk_lib" - // See FIXME on sources.cpp.lib library: 'appd' above + // See FIXME on sources.cpp.lib library: 'otel' above // binaries.withType(SharedLibraryBinary) { // sharedLibraryFile = file("${libraryStageDir}/sdk_lib/lib/libopentelemetry_webserver_sdk.so") // } diff --git a/instrumentation/otel-webserver-module/dist/Install_Native.txt b/instrumentation/otel-webserver-module/dist/Install_Native.txt deleted file mode 100644 index 65fdbfbd6..000000000 --- a/instrumentation/otel-webserver-module/dist/Install_Native.txt +++ /dev/null @@ -1,27 +0,0 @@ -Install the AppDynamics C/C++ Agent SDK ---------------------------------------- - -The AppDynamics C/C++ Agent SDK tarball from the download zone extracts to a directory named "appdynamics-sdk-native" that contains this file. AppDynamics recommends you extract the tarball to the /opt/appdynamics directory. - -For up-to date instructions, go to https://docs.appdynamics.com/ - -1. Download the the C/C++ Agent SDK from https://download.appdynamics.com/ - -2. Extract the agent SDK. - - mkdir /opt/appdynamics - sudo tar -xzvf appdynamics-sdk-native-.tar.gz -C /opt/appdynamics - - The agent SDK installs to /opt/appdynamics/appdynamics-sdk-native. - -3. Run the install.sh script to install the agent proxy. The agent SDK reports performance metrics to the proxy, which processes the data and passes it to the Controller. - - sudo /opt/appdynamics/appdynamics-sdk-native/install.sh - -4. Run runSDKProxy.sh to start the proxy as a root user. - - sudo /opt/appdynamics/appdynamics-sdk-native/runSDKProxy.sh - - Note: Eventually you will want to set up the agent proxy as service set to automatically restart. - -After you install the C/C++ Agent SDK, you are ready to instrument your C/C++ application using the API. diff --git a/instrumentation/otel-webserver-module/dist/install.sh b/instrumentation/otel-webserver-module/dist/install.sh index 16c157b1d..9450e947f 100755 --- a/instrumentation/otel-webserver-module/dist/install.sh +++ b/instrumentation/otel-webserver-module/dist/install.sh @@ -51,7 +51,7 @@ fi log() { echo "$@" >> ${install_log} - if [ -z "${APPD_AUTO_MODE}" ]; then + if [ -z "${OTEL_AUTO_MODE}" ]; then echo "$@" fi } @@ -96,15 +96,15 @@ checkPathIsAccessible() { eval $__resultVarName="$__result" } -if [ -z "${APPD_LOCATION}" ]; then - APPD_LOCATION=$containingDir - APPD_PACKAGE=0 +if [ -z "${OTEL_LOCATION}" ]; then + OTEL_LOCATION=$containingDir + OTEL_PACKAGE=0 else - APPD_PACKAGE=1 + OTEL_PACKAGE=1 fi datestamp=`date +%Y_%m_%d_%H_%M_%S 2>/dev/null` -install_log=/tmp/appd_install_${datestamp}.log +install_log=/tmp/otel_install_${datestamp}.log rm -f $install_log > /dev/null 2>&1 cat > $install_log </dev/null` Hostname: `hostname` -Location: ${APPD_LOCATION} +Location: ${OTEL_LOCATION} System: `uname -a 2>/dev/null` User: `id` Environment: @@ -128,12 +128,12 @@ getenforce=`which getenforce 2>/dev/null` if [ -f "${getenforce}" ]; then selStatus=`$getenforce` if [ "$selStatus" = "Enforcing" ] ; then - log "Warning: You may encounter issues with SELinux and AppDynamics. Please refer to the AppDynamics documentation at https://docs.appdynamics.com for information on creating an SELinux policy for AppDynamics support." + log "Warning: You may encounter issues with SELinux and Opentelemetry. Please refer to https://github.com/open-telemetry/opentelemetry-cpp-contrib/tree/main/instrumentation/otel-webserver-module for more details" fi fi ## Installed files locations -log4cxxFile="${containingDir}/conf/appdynamics_sdk_log4cxx.xml" +log4cxxFile="${containingDir}/conf/opentelemetry_sdk_log4cxx.xml" rootDirCheck= checkPathIsAccessible rootDirCheck "${containingDir}" diff --git a/instrumentation/otel-webserver-module/dist/appdynamics_sdk_log4cxx.xml.template b/instrumentation/otel-webserver-module/dist/opentelemetry_sdk_log4cxx.xml.template similarity index 87% rename from instrumentation/otel-webserver-module/dist/appdynamics_sdk_log4cxx.xml.template rename to instrumentation/otel-webserver-module/dist/opentelemetry_sdk_log4cxx.xml.template index 345f38c4b..62a77a040 100755 --- a/instrumentation/otel-webserver-module/dist/appdynamics_sdk_log4cxx.xml.template +++ b/instrumentation/otel-webserver-module/dist/opentelemetry_sdk_log4cxx.xml.template @@ -8,7 +8,7 @@ - + @@ -19,7 +19,7 @@ - + @@ -30,7 +30,7 @@ - + diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h index eedc6a212..15f5da806 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h @@ -18,7 +18,7 @@ #ifndef APACHEHOOKS_H #define APACHEHOOKS_H -#include +#include #include #include "HookContainer.h" #include "ExcludedModules.h" @@ -116,7 +116,6 @@ class ApacheHooksForStage Hooks to occur before a module to start an interaction for a stage. These hooks are stage specific and each hook corresponds to a particular module. The number of hooks are proportional to the number of modules instrumented for a stage. - See "AppDynamicsReportAllInstrumentedModules" flag for more details. TODO: Decide among the following stages at what all we need the modules to be instrumented, and define the hooks handlers for the same to start an interaction before module callback. */ diff --git a/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h b/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h index a17d79cb5..8481d432f 100644 --- a/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h +++ b/instrumentation/otel-webserver-module/include/core/api/ApiUtils.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include "AgentLogger.h" #include diff --git a/instrumentation/otel-webserver-module/include/core/api/Interface.h b/instrumentation/otel-webserver-module/include/core/api/Interface.h index 990ea07c6..d945eb090 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Interface.h +++ b/instrumentation/otel-webserver-module/include/core/api/Interface.h @@ -16,7 +16,7 @@ #pragma once #include -#include +#include #include #include diff --git a/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h b/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h similarity index 98% rename from instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h rename to instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h index 3e98132b1..98dc4193c 100755 --- a/instrumentation/otel-webserver-module/include/core/api/AppdynamicsSdk.h +++ b/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef APPDYNAMICS_SDK_H -#define APPDYNAMICS_SDK_H +#ifndef OPENTELEMETRY_SDK_H +#define OPENTELEMETRY_SDK_H #include @@ -135,4 +135,4 @@ typedef struct _OTEL_SDK_ENV_RECORD } OTEL_SDK_ENV_RECORD; /* }}} */ -#endif /* APPDYNAMICS_SDK_H */ +#endif /* OPENTELEMETRY_SDK_H */ diff --git a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h index 68706c02a..ebad560d0 100644 --- a/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h +++ b/instrumentation/otel-webserver-module/include/core/api/RequestProcessingEngine.h @@ -17,7 +17,7 @@ #ifndef REQUEST_PROCESSOR_ENGINE_H #define REQUEST_PROCESSOR_ENGINE_H -#include "api/AppdynamicsSdk.h" +#include "api/OpentelemetrySdk.h" #include "api/SpanNamer.h" #include "RequestContext.h" #include "AgentLogger.h" diff --git a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h index e4563c43c..608a31c66 100644 --- a/instrumentation/otel-webserver-module/include/core/api/WSAgent.h +++ b/instrumentation/otel-webserver-module/include/core/api/WSAgent.h @@ -17,7 +17,7 @@ #ifndef OTEL_WS_AGENT_H #define OTEL_WS_AGENT_H -#include "api/AppdynamicsSdk.h" +#include "api/OpentelemetrySdk.h" #include #include #include diff --git a/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp b/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp index 124ab1bb1..ee2a124a3 100644 --- a/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp +++ b/instrumentation/otel-webserver-module/src/apache/HookContainer.cpp @@ -71,5 +71,4 @@ void HookContainer::traceHooks(request_rec* r) const modules += ":"; modules += ii->second.module; } - //AppdTracing::writeTrace(r->server, __func__, "%s", modules.c_str()); } diff --git a/instrumentation/otel-webserver-module/src/apache/apache.gyp b/instrumentation/otel-webserver-module/src/apache/apache.gyp index af07ae291..19daef2a4 100644 --- a/instrumentation/otel-webserver-module/src/apache/apache.gyp +++ b/instrumentation/otel-webserver-module/src/apache/apache.gyp @@ -28,7 +28,7 @@ [ 'OS=="linux"', { 'libraries': [ - '$(APPD_SDK_LIB_DIR)/lib/libopentelemetry_webserver_sdk.so', + '$(OTEL_SDK_LIB_DIR)/lib/libopentelemetry_webserver_sdk.so', ], 'library_dirs': [ @@ -58,7 +58,7 @@ 'dependencies': [ ], 'libraries': [ - '$(APPD_SDK_LIB_DIR)/lib/libopentelemetry_webserver_sdk.so', + '$(OTEL_SDK_LIB_DIR)/lib/libopentelemetry_webserver_sdk.so', ], 'defines': [ ], diff --git a/instrumentation/otel-webserver-module/src/build.gyp b/instrumentation/otel-webserver-module/src/build.gyp index de085b370..ac31bd3e3 100644 --- a/instrumentation/otel-webserver-module/src/build.gyp +++ b/instrumentation/otel-webserver-module/src/build.gyp @@ -48,12 +48,12 @@ '$(ANSDK_DIR)/apr-util/1.6.1/lib/libaprutil-1.a', '$(ANSDK_DIR)/expat/2.3.0/lib/libexpat.a', '$(ANSDK_DIR)/apache-log4cxx/0.11.0/lib/liblog4cxx.a', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_common.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_resources.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_trace.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_otlp_recordable.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_exporter_ostream_span.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_exporter_otlp_grpc.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_common.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_resources.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_trace.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_otlp_recordable.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_exporter_ostream_span.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_exporter_otlp_grpc.so', '$(BOOST_LIB)', '$(LINKER_FLAGS)', '$(LIBRARY_FLAGS)', @@ -64,7 +64,7 @@ '$(ANSDK_DIR)/apache-log4cxx/0.11.0/include', '../include/util', '../include/core', - '$(ANSDK_DIR)/opentelemetry/1.2.0/include/', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/include/', '$(BOOST_INCLUDE)' ], @@ -145,14 +145,14 @@ '$(ANSDK_DIR)/protobuf/2.5.0/lib/libprotoc.lib', '$(ANSDK_DIR)/protobuf/2.5.0/lib/libprotobuf.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_filesystem-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_atomic-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_system-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_thread-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_chrono-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_atomic-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_date_time-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', - '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_regex-vc120-$(APPD_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_filesystem-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_atomic-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_system-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_thread-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_chrono-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_atomic-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_date_time-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', + '$(ANSDK_DIR)/boost/1.55.0/lib/libboost_regex-vc120-$(OTEL_BOOST_LIB_FLAGS)-1_55.lib', 'Ws2_32.lib', 'advapi32.lib', diff --git a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp index c428f6309..68e1d86ef 100755 --- a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp @@ -16,7 +16,7 @@ // file header #include "api/ApiUtils.h" -#include "api/AppdynamicsSdk.h" +#include "api/OpentelemetrySdk.h" #include "AgentLogger.h" #include #include @@ -52,7 +52,7 @@ OTEL_SDK_STATUS_CODE ApiUtils::init_boilerplate() logConfigPath = getSDKInstallPath() / boost::filesystem::path("conf") - / boost::filesystem::path("appdynamics_sdk_log4cxx.xml"); + / boost::filesystem::path("opentelemetry_sdk_log4cxx.xml"); } boost::system::error_code ec; diff --git a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp index e32ffe5d2..1cc9b1cf7 100644 --- a/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/WSAgent.cpp @@ -16,7 +16,7 @@ #include "api/WSAgent.h" #include "api/RequestProcessingEngine.h" -#include "api/AppdynamicsSdk.h" +#include "api/OpentelemetrySdk.h" #include "api/ApiUtils.h" #include "RequestContext.h" #include diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index 38d514385..872a10045 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "api/AppdynamicsSdk.h" +#include "api/OpentelemetrySdk.h" #include "api/opentelemetry_ngx_api.h" #include "api/WSAgent.h" #include "api/Payload.h" diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index bbcf7ad0b..33d30d948 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -1138,7 +1138,7 @@ static void startMonitoringRequest(ngx_http_request_t* r){ ngx_writeTrace(r->connection->log, __func__, "Not a Main Request(sub-request or internal redirect)"); return; } - else if (!ngx_initialize_opentelemetry(r)) /* check if Appd Agent Core is initialized */ + else if (!ngx_initialize_opentelemetry(r)) /* check if Otel Agent Core is initialized */ { ngx_writeError(r->connection->log, __func__, "Opentelemetry Agent Core did not get initialized"); return; diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h index 0ce1b0898..b192494ae 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -18,7 +18,7 @@ #include #include #include -#include "../../include/core/api/AppdynamicsSdk.h" +#include "../../include/core/api/OpentelemetrySdk.h" #include "../../include/core/api/opentelemetry_ngx_api.h" #define LOWEST_HTTP_ERROR_CODE 400 @@ -174,7 +174,7 @@ static ngx_int_t ngx_http_otel_mirror_handler(ngx_http_request_t *r); /* - Utility fuction to check if the given module is monitored by Appd Agent + Utility fuction to check if the given module is monitored by Opentelemetry Agent */ static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t* conf); diff --git a/instrumentation/otel-webserver-module/test/NginxTesting.sh b/instrumentation/otel-webserver-module/test/NginxTesting.sh index 689ed5a88..5bc8cf437 100755 --- a/instrumentation/otel-webserver-module/test/NginxTesting.sh +++ b/instrumentation/otel-webserver-module/test/NginxTesting.sh @@ -3,53 +3,53 @@ # Bash script for testing Apache Server # Extract the agent -tar -xf ../build/appdynamics-webserver-sdk-x64-linux.tgz -C /opt +tar -xf ../build/opentelemetry-webserver-sdk-x64-linux.tgz -C /opt -cd /opt/appdynamics-sdk-native +cd /opt/opentelemetry-sdk-native echo "Installing Apache Agent" ./install.sh -# Create a appdynamics_agent.conf file -echo "Copying agent config to appdynamics_agent file" +# Create a opentelemetry_agent.conf file +echo "Copying agent config to opentelemetry_agent file" echo ' -AppDynamicsEnabled ON; +NginxModuleEnabled ON; -#AppDynamics Otel Exporter details -AppDynamicsOtelSpanExporter OTLP; -AppDynamicsOtelExporterEndpoint example.com:14250; +# Otel Exporter details +NginxModuleOtelSpanExporter OTLP; +NginxModuleOtelExporterEndpoint example.com:14250; -AppDynamicsOtelSpanProcessor Batch; -AppDynamicsOtelSampler AlwaysOn; +NginxModuleOtelSpanProcessor Batch; +NginxModuleOtelSampler AlwaysOn; -AppDynamicsServiceName cart; -AppDynamicsServiceNamespace e-commerce; -AppDynamicsServiceInstanceId 71410b7dec09; +NginxModuleServiceName cart; +NginxModuleServiceNamespace e-commerce; +NginxModuleServiceInstanceId 71410b7dec09; -AppDynamicsOtelMaxQueueSize 1024; -AppDynamicsOtelScheduledDelayMillis 3000; -AppDynamicsOtelExportTimeoutMillis 30000; -AppDynamicsOtelMaxExportBatchSize 1024; +NginxModuleOtelMaxQueueSize 1024; +NginxModuleOtelScheduledDelayMillis 3000; +NginxModuleOtelExportTimeoutMillis 30000; +NginxModuleOtelMaxExportBatchSize 1024; -AppDynamicsResolveBackends ON; +NginxModuleResolveBackends ON; -AppDynamicsTraceAsError ON; +NginxModuleTraceAsError ON; -AppDynamicsReportAllInstrumentedModules OFF; +NginxModuleReportAllInstrumentedModules OFF; -#AppDynamicsWebserverContext electronics e-commerce 71410b7jan13; +#NginxModuleWebserverContext electronics e-commerce 71410b7jan13; -AppDynamicsMaskCookie ON; -AppDynamicsCookieMatchPattern PHPSESSID; -AppDynamicsMaskSmUser ON; +NginxModuleMaskCookie ON; +NginxModuleCookieMatchPattern PHPSESSID; +NginxModuleMaskSmUser ON; -AppDynamicsDelimiter /; -AppDynamicsSegment 2,3; -AppDynamicsMatchfilter CONTAINS; -AppDynamicsMatchpattern myapp; -' > /opt/appdynamics_agent.conf +NginxModuleDelimiter /; +NginxModuleSegment 2,3; +NginxModuleMatchfilter CONTAINS; +NginxModuleMatchpattern myapp; +' > /opt/opentelemetry_agent.conf -# Overwrite nginx.conf file and include appdynamics_agent.conf and ngx_http_appdynamics_module.so in it +# Overwrite nginx.conf file and include opentelemetry_agent.conf and ngx_http_opentelemetry_module.so in it echo ' user nobody; worker_processes 1; @@ -57,7 +57,7 @@ worker_processes 1; error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid; -load_module /opt/appdynamics-sdk-native/WebServerAgent/Nginx/ngx_http_appdynamics_module.so; +load_module /opt/opentelemetry-sdk-native/WebServerAgent/Nginx/ngx_http_opentelemetry_module.so; events { worker_connections 1024; @@ -74,7 +74,7 @@ http { sendfile on; keepalive_timeout 65; - include /opt/appdynamics_agent.conf; + include /opt/opentelemetry_agent.conf; server { listen 8080; diff --git a/instrumentation/otel-webserver-module/test/unit/unit_test.gyp b/instrumentation/otel-webserver-module/test/unit/unit_test.gyp index 15ec36566..fd8b4e2d1 100755 --- a/instrumentation/otel-webserver-module/test/unit/unit_test.gyp +++ b/instrumentation/otel-webserver-module/test/unit/unit_test.gyp @@ -8,7 +8,7 @@ '../../include/util/', '$(ANSDK_DIR)/googletest/1.10.0/include', '$(ANSDK_DIR)/googletest/1.10.0/include', - '$(ANSDK_DIR)/opentelemetry/1.2.0/include/', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/include/', '$(ANSDK_DIR)/apache-log4cxx/0.11.0/include', '$(ANSDK_DIR)/apr/1.7.0/include', '$(ANSDK_DIR)/apr-util/1.6.1/include', @@ -39,7 +39,7 @@ 'libraries': [ # TODO: Following is the sdk library path of the agent. Replace with the actual library to be tested. - '$(APPD_SDK_LIB_DIR)/lib/libopentelemetry_webserver_sdk.so', + '$(OTEL_SDK_LIB_DIR)/lib/libopentelemetry_webserver_sdk.so', '$(GTEST_LIB_DIR)/libgmock.a', '$(GTEST_LIB_DIR)/libgmock_main.a', '$(GTEST_LIB_DIR)/libgtest.a', @@ -48,12 +48,12 @@ '$(ANSDK_DIR)/apr/1.7.0/lib/libapr-1.a', '$(ANSDK_DIR)/apr-util/1.6.1/lib/libaprutil-1.a', '$(ANSDK_DIR)/expat/2.3.0/lib/libexpat.a', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_common.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_resources.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_trace.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_otlp_recordable.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_exporter_ostream_span.so', - '$(ANSDK_DIR)/opentelemetry/1.2.0/lib/libopentelemetry_exporter_otlp_grpc.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_common.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_resources.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_trace.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_otlp_recordable.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_exporter_ostream_span.so', + '$(ANSDK_DIR)/opentelemetry/$(CPP_SDK_VERSION)/lib/libopentelemetry_exporter_otlp_grpc.so', '$(BOOST_LIB)', '$(LIBRARY_FLAGS)', ], From 5313411337e7d4cf1973660ef86d3aec57c87919 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Mon, 26 Dec 2022 19:51:27 +0530 Subject: [PATCH 42/77] Showing Attribute Values properly for Nginx Module (#248) * Attributes parsed values * Removing Comments * Fixing comments --- .../src/nginx/ngx_http_opentelemetry_module.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 33d30d948..37dd4d60b 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -1565,11 +1565,19 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* #endif - req_payload->protocol = (const char*)(r->http_protocol).data; - req_payload->request_method = (const char*)(r->method_name).data; + // TODO - use strncpy function to just create memory of size (r->http_protocol.len) + char *temp_http_protocol = ngx_pcalloc(r->pool, (strlen((r->http_protocol).data))+1); + strcpy(temp_http_protocol,(const char*)(r->http_protocol).data); + temp_http_protocol[(r->http_protocol).len]='\0'; + req_payload->protocol = temp_http_protocol; + + char *temp_request_method = ngx_pcalloc(r->pool, (strlen((r->method_name).data))+1); + strcpy(temp_request_method,(const char*)(r->method_name).data); + temp_request_method[(r->method_name).len]='\0'; + req_payload->request_method = temp_request_method; // flavor has to be scraped from protocol in future - req_payload->flavor = (const char*)(r->http_protocol).data; + req_payload->flavor = temp_http_protocol; char *temp_hostname = ngx_pcalloc(r->pool, (strlen(hostname.data))+1); strcpy(temp_hostname,(const char*)hostname.data); From 715bab89e061b23ad95856d5a50e72f3ac9a42cb Mon Sep 17 00:00:00 2001 From: Narasimha Date: Wed, 4 Jan 2023 11:39:19 +0530 Subject: [PATCH 43/77] Apache and Ngnix OtelExporterOtlpHeaders changes (#240) * Apache OtelExporterHeaders changes commit -1 Apache OtelExporterHeaders changes commit -1 * Update ApacheConfig.cpp Added OTLP headers in getProcessConfig * OtelExportHeader config count changes config count added , env_config added * appd_set_otelExporterOtlpHeaders correction appd_set_otelExporterOtlpHeaders ApacheModuleOtelExporterHeaders are added * Changes related OTLP headers Added Tenant config changes * Merge conflicts resolved regarding appd namespace Merge conflicts resolved regarding appd namespace * updating comments updating comments * Removed space Removed extra space * headers variable is correctly added Added metadata asper the structure * Adding otlp headers Added Otlp headers instead of string * Correcting typo Correcting mistake in declaration * Export headers tokenization Export headers tokens parsing * Changes for tokenization Changes for tokenization * appd to otel name change appd to otel name change * appd to otel name change * appd name change appd name change * corrections in name space appd to otel * Ngnix changes for OTEL Http Headers Ngnix changes for OTEL Http Headers * Declaration of ngx_str_t ngx_str_t * Updating variable variable name * Disabling OTEL headers This is only for production not for dev * Review comments addressed Review comments added, name changes done * Review comments -2 Changes in naming * Api Utils change Changes in ApiUtils to read from env * Reverted unwanted space Reverted unwanted space in Integration test * Enabling the otel headers config Enabling the otel headers config * Checking for empty strings Empty headers * Disable OTLP headers Disable OTLP headers * Adding a check to fix IT Integration test * Reverting the check Reverting some changes * Initializaing the otelExporterEndpoint otelExporterEndpoint initialization * Updating README updated the new about the new directive ApacheModuleOtelExporterHeaders * Read me updated for OTEL exporter headers directive Added Read me info on OTEL exporter headers Co-authored-by: DEBAJIT DAS <85024550+DebajitDas@users.noreply.github.com> --- .../otel-webserver-module/README.md | 2 ++ .../conf/nginx/opentelemetry_module.conf | 1 + .../include/apache/ApacheConfig.h | 7 +++++ .../include/apache/ApacheHooks.h | 1 + .../include/core/api/OpentelemetrySdk.h | 2 ++ .../include/core/api/TenantConfig.h | 4 +++ .../opentelemetry_module.conf | 1 + .../src/apache/ApacheConfig.cpp | 15 +++++++++++ .../src/apache/ApacheHooks.cpp | 12 ++++++--- .../src/apache/mod_apache_otel.cpp | 6 +++++ .../src/core/api/ApiUtils.cpp | 5 ++++ .../src/core/sdkwrapper/SdkHelperFactory.cpp | 27 +++++++++++++++++++ .../src/nginx/ngx_http_opentelemetry_module.c | 17 +++++++++++- .../src/nginx/ngx_http_opentelemetry_module.h | 2 ++ 14 files changed, 98 insertions(+), 4 deletions(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 9b59ccfd8..b1626c07a 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -58,6 +58,7 @@ Monitoring individual modules is crucial to the instrumentation of Apache web se |*ApacheModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| |*ApacheModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation| |*ApacheModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| +|*ApacheModuleOtelExporterHeaders* | | OPTIONAL: OTEL Exporter header info or Metadata like API key for OTLP endpoint. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2. | A sample configuration is mentioned in [opentelemetry_module.conf](https://github.com/cisco-open/otel-webserver-module/blob/main/opentelemetry_module.conf) @@ -174,6 +175,7 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get |*NginxModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| |*NginxModuleRequestHeaders* | | OPTIONAL: Specify the request headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleRequestHeaders Accept-Charset,Accept-Encoding,User-Agent;```| |*NginxModuleResponseHeaders* | | OPTIONAL: Specify the response headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleResponseHeaders Content-Length,Content-Type;```| +|*NginxModuleOtelExporterOtlpHeaders* | | OPTIONAL: OTEL exporter headers like Meta data related exposrted end point. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2.| ### Build and Installation #### Prerequisites diff --git a/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf b/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf index 27532995d..e3eb6ed2d 100644 --- a/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf +++ b/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf @@ -2,6 +2,7 @@ NginxModuleEnabled ON; #NginxModule Otel Exporter details NginxModuleOtelSpanExporter otlp; NginxModuleOtelExporterEndpoint docker.for.mac.localhost:4317; +#NginxModuleOtelExporterOtlpHeaders Authorization=AuthorizationToken; # SSL Certificates #NginxModuleOtelSslEnabled ON #NginxModuleOtelSslCertificatePath diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h index 912cd1d6c..ebef128e4 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h @@ -39,6 +39,9 @@ class otel_cfg const char* getOtelExporterEndpoint() { return otelExporterEndpoint; } int getOtelExporterEndpointInitialized() { return otelExporterEndpoint_initialized; } + const char* getOtelExporterOtlpHeaders() { return otelExporterOtlpHeaders; } + int otelExporterOtlpHeadersInitialized() { return otelExporterOtlpHeaders_initialized; } + int getOtelSslEnabled() { return otelSslEnabled; } int getOtelSslEnabledInitialized() { return otelSslEnabled_initialized; } @@ -123,6 +126,9 @@ class otel_cfg const char *otelExporterEndpoint; // REQUIRED: Collector endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces int otelExporterEndpoint_initialized; + const char *otelExporterOtlpHeaders; // OPTIONAL: AppDynamics Custom metadata for OTEL Exporter EX: OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value" + int otelExporterOtlpHeaders_initialized; + int otelSslEnabled; // OPTIONAL: Decision whether connection to the Exporter endpoint is secured int otelSslEnabled_initialized; @@ -224,6 +230,7 @@ class ApacheConfigHandlers static const char* otel_set_enabled(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelExporterType(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelExporterEndpoint(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelExporterOtlpHeaders(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelSslCertificatePath(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelProcessorType(cmd_parms *cmd, void *conf, const char *arg); diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h index 15f5da806..0b3f13198 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h @@ -33,6 +33,7 @@ class ApacheHooks static const char* OTEL_INTERACTION_HANDLE_KEY; static const char* OTEL_REQ_HANDLE_KEY; static const int LOWEST_HTTP_ERROR_CODE = 400; + static const int CONFIG_COUNT = 17; // Number of key value pairs in config static const std::initializer_list httpHeaders; static void registerHooks(apr_pool_t *p); diff --git a/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h b/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h index 98dc4193c..b7dfec358 100755 --- a/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h +++ b/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h @@ -27,6 +27,7 @@ /* {{{ For API user: environment variables to specify Controller connectivity */ #define OTEL_SDK_ENV_OTEL_EXPORTER_TYPE "OTEL_SDK_ENV_OTEL_EXPORTER_TYPE" #define OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT "OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT" /*required*/ +#define OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS "OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS" /*optional*/ #define OTEL_SDK_ENV_OTEL_SSL_ENABLED "OTEL_SDK_ENV_OTEL_SSL_ENABLED" /*optional*/ #define OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH "OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH" /*optional*/ #define OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE "OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE" @@ -53,6 +54,7 @@ #define OTEL_SDK_ENV_SEGMENT_TYPE "OTEL_SDK_ENV_SEGMENT_TYPE" #define OTEL_SDK_ENV_SEGMENT_PARAMETER "OTEL_SDK_ENV_SEGMENT_PARAMETER" + /* {{{ For API user: API User logger */ #define OTEL_LOG_API_USER_LOGGER "api_user" /*logging at the level of sdk function call*/ #define OTEL_LOG_API_LOGGER "api" /*logging at the level of sdk core functionality*/ diff --git a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h index a51c8a00a..a32016e5e 100644 --- a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h +++ b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h @@ -45,6 +45,7 @@ class TenantConfig const std::string& getOtelLibraryVersion() const {return otelLibraryVersion;} const std::string& getOtelExporterType() const {return otelExporterType;} const std::string& getOtelExporterEndpoint() const {return otelExporterEndpoint;} + const std::string& getOtelExporterOtlpHeaders() const {return otelExporterOtlpHeaders;} const std::string& getOtelProcessorType() const {return otelProcessorType;} const unsigned getOtelMaxQueueSize() const {return otelMaxQueueSize;} const unsigned getOtelScheduledDelayMillis() const {return otelScheduledDelayMillis;} @@ -61,6 +62,7 @@ class TenantConfig void setServiceInstanceId(const std::string& serviceInstanceId) { this->serviceInstanceId = serviceInstanceId; } void setOtelExporterType(const std::string& otelExporterType) { this->otelExporterType = otelExporterType; } void setOtelExporterEndpoint(const std::string& otelExporterEndpoint) { this->otelExporterEndpoint = otelExporterEndpoint; } + void setOtelExporterOtlpHeaders(const std::string& otelExporterOtlpHeaders) { this->otelExporterOtlpHeaders = otelExporterOtlpHeaders; } void setOtelProcessorType(const std::string& otelProcessorType) { this->otelProcessorType = otelProcessorType; } void setOtelMaxQueueSize(const unsigned int otelMaxQueueSize) { this->otelMaxQueueSize = otelMaxQueueSize; } void setOtelScheduledDelayMillis(const unsigned int otelScheduledDelayMillis) { this->otelScheduledDelayMillis = otelScheduledDelayMillis; } @@ -80,6 +82,7 @@ class TenantConfig std::string otelExporterType; std::string otelExporterEndpoint; + std::string otelExporterOtlpHeaders; bool otelSslEnabled; std::string otelSslCertPath; @@ -108,6 +111,7 @@ inline std::ostream& operator<< (std::ostream &os, const otel::core::TenantConfi << "\n OtelSamplerType " << config.getOtelSamplerType() << "\n OtelSslEnabled " << config.getOtelSslEnabled() << "\n OtelSslCertPath " << config.getOtelSslCertPath() + << "\n OtelExportOtlpHeaders " << config.getOtelExporterOtlpHeaders() << ""; return os; } diff --git a/instrumentation/otel-webserver-module/opentelemetry_module.conf b/instrumentation/otel-webserver-module/opentelemetry_module.conf index efdc21d5d..b5b0a9194 100755 --- a/instrumentation/otel-webserver-module/opentelemetry_module.conf +++ b/instrumentation/otel-webserver-module/opentelemetry_module.conf @@ -14,6 +14,7 @@ ApacheModuleEnabled ON #ApacheModule Otel Exporter details ApacheModuleOtelSpanExporter otlp ApacheModuleOtelExporterEndpoint collector:4317 +#ApacheModuleOtelExporterHeaders api-key=abc123 # SSL Certificates #ApacheModuleOtelSslEnabled ON diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp index 1f22cb2ab..92c59e875 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp @@ -121,6 +121,14 @@ const char* ApacheConfigHandlers::otel_set_otelExporterEndpoint(cmd_parms *cmd, return helperChar(cmd, cfg, arg, cfg->otelExporterEndpoint, cfg->otelExporterEndpoint_initialized, "otel_set_otelExporterEndpoint"); } +// char *otelExporterOtlpHeaders; +// int otelExporterOtlpHeaders_initialized; +const char* ApacheConfigHandlers::otel_set_otelExporterOtlpHeaders(cmd_parms *cmd, void *conf, const char *arg) +{ + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelExporterOtlpHeaders, cfg->otelExporterOtlpHeaders_initialized, "otel_set_otelExporterOtlpHeaders"); +} + // char *otelSslEnabled; // int otelSslEnabled_initialized; const char* ApacheConfigHandlers::otel_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg) @@ -432,6 +440,10 @@ void otel_cfg::init() otelExporterEndpoint = ""; otelExporterEndpoint_initialized = 0; + // otelExporterOtlpHeaders Optional: OTLP headers as key value pairs + otelExporterOtlpHeaders = ""; + otelExporterOtlpHeaders_initialized = 0; + // otelSslEnabled OPTIONAL: Decides whether the connection to the endpoint is secured otelSslEnabled = 0; otelSslEnabled_initialized = 0; @@ -771,6 +783,9 @@ otel_cfg* ApacheConfigHandlers::getProcessConfig(const request_rec* r) process_cfg->otelExporterEndpoint = apr_pstrdup(r->server->process->pool, our_config->otelExporterEndpoint); process_cfg->otelExporterEndpoint_initialized = our_config->otelExporterEndpoint_initialized; + process_cfg->otelExporterOtlpHeaders = apr_pstrdup(r->server->process->pool, our_config->otelExporterOtlpHeaders); + process_cfg->otelExporterOtlpHeaders_initialized = our_config->otelExporterOtlpHeaders_initialized; + process_cfg->otelSslEnabled = our_config->otelSslEnabled; process_cfg->otelSslEnabled_initialized = our_config->otelSslEnabled_initialized; diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index 346795a43..1bb575575 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -339,10 +339,11 @@ bool ApacheHooks::initialize_opentelemetry(const request_rec *r) wsAgent.initDependency(); // ENV RECORDS SIZE TO INCLUDE THE LOG PATH AND THE AGGREGATOR DIRECTORY - // - // Update the apr_pcalloc if we add another parameter to the input array! + // Update the CONFIG_COUNT in apr_pcalloc if we add another parameter to the input array! + OTEL_SDK_ENV_RECORD* env_config = - (OTEL_SDK_ENV_RECORD*) apr_pcalloc(r->pool, 16 * sizeof(OTEL_SDK_ENV_RECORD)); + (OTEL_SDK_ENV_RECORD*) apr_pcalloc(r->pool, CONFIG_COUNT * sizeof(OTEL_SDK_ENV_RECORD)); + int ix = 0; // Otel Exporter Type @@ -425,6 +426,11 @@ bool ApacheHooks::initialize_opentelemetry(const request_rec *r) env_config[ix].value = our_config->getSegmentParameter(); ++ix; + // Segment Parameter + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS; + env_config[ix].value = our_config->getOtelExporterOtlpHeaders(); + ++ix; + // !!! // Remember to update the apr_pcalloc call size if we add another parameter to the input array! // !!! diff --git a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp index e27595bff..f01fdd550 100644 --- a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp +++ b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp @@ -64,6 +64,12 @@ static const command_rec otel_cmds[] = NULL, OR_ALL, "Collector Endpoint where the OpenTelemetry Exporter inside OTel SDK sends traces"), + AP_INIT_TAKE1( + "apacheModuleOtelExporterHeaders", + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelExporterOtlpHeaders, + NULL, + OR_ALL, + "AppDynamics Otel export Headers key value pairs"), AP_INIT_TAKE1( "apacheModuleOtelSslEnabled", (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelSslEnabled, diff --git a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp index 68e1d86ef..1a2931e06 100755 --- a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp @@ -167,6 +167,7 @@ OTEL_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( std::string otelExporterType; std::string otelExporterEndpoint; + std::string otelExporterOtlpHeaders; bool otelSslEnabled; std::string otelSslCertPath; std::string otelLibraryName; @@ -255,12 +256,16 @@ OTEL_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( reader.ReadOptional( std::string(OTEL_SDK_ENV_SEGMENT_PARAMETER), segmentParameter); + reader.ReadOptional( + std::string(OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS), otelExporterOtlpHeaders); + tenantConfig.setServiceNamespace(serviceNamespace); tenantConfig.setServiceName(serviceName); tenantConfig.setServiceInstanceId(serviceInstanceId); tenantConfig.setOtelExporterType(otelExporterType); tenantConfig.setOtelExporterEndpoint(otelExporterEndpoint); + tenantConfig.setOtelExporterOtlpHeaders(otelExporterOtlpHeaders); tenantConfig.setOtelLibraryName(otelLibraryName); tenantConfig.setOtelProcessorType(otelProcessorType); tenantConfig.setOtelSamplerType(otelSamplerType); diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp index f22ac7844..0082276c3 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp @@ -26,6 +26,7 @@ #include "opentelemetry/sdk/trace/samplers/trace_id_ratio.h" #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/exporters/otlp/otlp_grpc_exporter.h" +#include "opentelemetry/exporters/otlp/otlp_environment.h" #include "opentelemetry/baggage/propagation/baggage_propagator.h" #include #include @@ -132,6 +133,32 @@ OtelSpanExporter SdkHelperFactory::GetExporter( LOG4CXX_TRACE(mLogger, "Ssl Credentials are enabled for exporter, path: " << opts.ssl_credentials_cacert_path); } + + opentelemetry::common::KeyValueStringTokenizer tokenizer{config->getOtelExporterOtlpHeaders()}; + opentelemetry::nostd::string_view header_key; + opentelemetry::nostd::string_view header_value; + bool header_valid = true; + std::unordered_set remove_cache; + + while (tokenizer.next(header_valid, header_key, header_value)) + { + if (header_valid) + { + std::string key = static_cast(header_key); + if (remove_cache.end() == remove_cache.find(key)) + { + remove_cache.insert(key); + auto range = opts.metadata.equal_range(key); + if (range.first != range.second) + { + opts.metadata.erase(range.first, range.second); + } + } + + opts.metadata.emplace(std::make_pair(std::move(key), static_cast(header_value))); + } + } + exporter.reset(new opentelemetry::exporter::otlp::OtlpGrpcExporter(opts)); } diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 37dd4d60b..e882ead10 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -202,6 +202,13 @@ static ngx_command_t ngx_http_opentelemetry_commands[] = { offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelExporterEndpoint), NULL}, + { ngx_string("NginxModuleOtelExporterOtlpHeaders"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelExporterOtlpHeaders), + NULL}, + { ngx_string("NginxModuleOtelSpanProcessor"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -449,6 +456,7 @@ static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, ngx_conf_merge_str_value(conf->nginxModuleOtelSpanExporter, prev->nginxModuleOtelSpanExporter, ""); ngx_conf_merge_str_value(conf->nginxModuleOtelExporterEndpoint, prev->nginxModuleOtelExporterEndpoint, ""); + ngx_conf_merge_str_value(conf->nginxModuleOtelExporterOtlpHeaders, prev->nginxModuleOtelExporterOtlpHeaders, ""); ngx_conf_merge_value(conf->nginxModuleOtelSslEnabled, prev->nginxModuleOtelSslEnabled, 0); ngx_conf_merge_str_value(conf->nginxModuleOtelSslCertificatePath, prev->nginxModuleOtelSslCertificatePath, ""); ngx_conf_merge_str_value(conf->nginxModuleOtelSpanProcessor, prev->nginxModuleOtelSpanProcessor, ""); @@ -913,7 +921,7 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) // Update the apr_pcalloc if we add another parameter to the input array! - OTEL_SDK_ENV_RECORD* env_config = ngx_pcalloc(r->pool, 16 * sizeof(OTEL_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* env_config = ngx_pcalloc(r->pool, CONFIG_COUNT * sizeof(OTEL_SDK_ENV_RECORD)); if(env_config == NULL) { ngx_writeError(r->connection->log, __func__, "Not Able to allocate memory for the Env Config"); @@ -936,6 +944,11 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) env_config[ix].value = (const char*)(conf->nginxModuleOtelExporterEndpoint).data; ++ix; + // Otel Exporter OTEL headers + env_config[ix].name = OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS; + env_config[ix].value = (const char*)(conf->nginxModuleOtelExporterOtlpHeaders).data; + ++ix; + // Otel SSL Enabled env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = conf->nginxModuleOtelSslEnabled == 1 ? "1" : "0"; @@ -1446,6 +1459,7 @@ static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t ngx_writeTrace(r->connection->log, __func__, " Config { :" "(Enabled=\"%ld\")" "(OtelExporterEndpoint=\"%s\")" + "(OtelExporterOtlpHeader=\"%s\")" "(OtelSslEnabled=\"%ld\")" "(OtelSslCertificatePath=\"%s\")" "(OtelSpanExporter=\"%s\")" @@ -1468,6 +1482,7 @@ static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t " }", conf->nginxModuleEnabled, (conf->nginxModuleOtelExporterEndpoint).data, + (conf->nginxModuleOtelExporterOtlpHeaders).data, conf->nginxModuleOtelSslEnabled, (conf->nginxModuleOtelSslCertificatePath).data, (conf->nginxModuleOtelSpanExporter).data, diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h index b192494ae..1d73d70eb 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -23,6 +23,7 @@ #define LOWEST_HTTP_ERROR_CODE 400 #define STATUS_CODE_BYTE_COUNT 6 +static const int CONFIG_COUNT = 17; // Number of key value pairs in config /* The following enum has one-to-one mapping with otel_monitored_modules[] defined in .c file. @@ -101,6 +102,7 @@ typedef struct { ngx_str_t nginxModuleSegmentParameter; ngx_str_t nginxModuleRequestHeaders; ngx_str_t nginxModuleResponseHeaders; + ngx_str_t nginxModuleOtelExporterOtlpHeaders; } ngx_http_opentelemetry_loc_conf_t; /* From 7034585e3ceb9e856303b95bd895da431ab043f3 Mon Sep 17 00:00:00 2001 From: Kumar Pratyush <95214718+kpratyus@users.noreply.github.com> Date: Wed, 4 Jan 2023 14:31:40 +0530 Subject: [PATCH 44/77] Changing address (#249) --- .../src/nginx/ngx_http_opentelemetry_module.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index e882ead10..2ba03510b 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -1619,6 +1619,10 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t* } req_payload->client_ip = (const char*)(r->connection->addr_text).data; + char *temp_client_ip = ngx_pcalloc(r->pool, (strlen((r->connection->addr_text).data))+1); + strcpy(temp_client_ip,(const char*)(r->connection->addr_text).data); + temp_client_ip[(r->connection->addr_text).len]='\0'; + req_payload->client_ip = temp_client_ip; ngx_http_opentelemetry_loc_conf_t *conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); From 1ec94c82095bab61f06c7393b6f3272469d285af Mon Sep 17 00:00:00 2001 From: Ehsan Saei <71217171+esigo@users.noreply.github.com> Date: Thu, 5 Jan 2023 20:13:03 +0100 Subject: [PATCH 45/77] upgrade nginx OpenTelemetry and gRPC (#252) --- instrumentation/nginx/src/otel_ngx_module.cpp | 8 +++++++- instrumentation/nginx/test/data/trace.json | 4 ++-- .../test/instrumentation/lib/mix/tasks/dockerfiles.ex | 8 +++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/instrumentation/nginx/src/otel_ngx_module.cpp b/instrumentation/nginx/src/otel_ngx_module.cpp index c8b24efe7..b94b9725e 100644 --- a/instrumentation/nginx/src/otel_ngx_module.cpp +++ b/instrumentation/nginx/src/otel_ngx_module.cpp @@ -1,3 +1,10 @@ +// clang-format off +// otlp_grpc_exporter header has to be included before any other API header to +// avoid conflict between Abseil library and OpenTelemetry C++ absl::variant. +// https://github.com/open-telemetry/opentelemetry-cpp/tree/main/examples/otlp#additional-notes-regarding-abseil-library +#include +// clang-format on + #include #include #include @@ -18,7 +25,6 @@ extern ngx_module_t otel_ngx_module; #include "nginx_utils.h" #include "propagate.h" #include -#include #include #include #include diff --git a/instrumentation/nginx/test/data/trace.json b/instrumentation/nginx/test/data/trace.json index e2d497509..ef94ca9de 100644 --- a/instrumentation/nginx/test/data/trace.json +++ b/instrumentation/nginx/test/data/trace.json @@ -1,2 +1,2 @@ -{"resourceSpans":[{"resource":{"attributes":[{"key":"telemetry.sdk.version","value":{"stringValue":"1.3.0"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.language","value":{"stringValue":"cpp"}},{"key":"service.name","value":{"stringValue":"nginx-proxy"}}]},"instrumentationLibrarySpans":[{"instrumentationLibrary":{"name":"nginx"},"spans":[{"traceId":"777151ac132afc1975887f8a3af71d23","spanId":"60bec6e1671cee32","parentSpanId":"","name":"otel_test","kind":"SPAN_KIND_SERVER","startTimeUnixNano":"1658331753935660143","endTimeUnixNano":"1658331753935827215","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.flavor","value":{"stringValue":"1.1"}},{"key":"http.target","value":{"stringValue":"/route_to_internal"}},{"key":"http.server_name","value":{"stringValue":"otel_test"}},{"key":"http.host","value":{"stringValue":"localhost:8000"}},{"key":"http.user_agent","value":{"stringValue":"curl/7.68.0"}},{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.host.port","value":{"intValue":"8000"}},{"key":"net.peer.ip","value":{"stringValue":"172.25.0.1"}},{"key":"net.peer.port","value":{"intValue":"51608"}},{"key":"test.attrib.global","value":{"stringValue":"global"}},{"key":"test.attrib.custom","value":{"stringValue":"global-custom"}}],"status":{}}]}]}]} -{"resourceSpans":[{"resource":{"attributes":[{"key":"telemetry.sdk.version","value":{"stringValue":"1.3.0"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.language","value":{"stringValue":"cpp"}},{"key":"service.name","value":{"stringValue":"nginx-proxy"}}]},"instrumentationLibrarySpans":[{"instrumentationLibrary":{"name":"nginx"},"spans":[{"traceId":"579d297c39ddac461fbc50febd77f16a","spanId":"fecfc6a8c9b60f03","parentSpanId":"","name":"otel_test","kind":"SPAN_KIND_SERVER","startTimeUnixNano":"1658331755134563590","endTimeUnixNano":"1658331755134700342","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.flavor","value":{"stringValue":"1.1"}},{"key":"http.target","value":{"stringValue":"/route_to_internal"}},{"key":"http.server_name","value":{"stringValue":"otel_test"}},{"key":"http.host","value":{"stringValue":"localhost:8000"}},{"key":"http.user_agent","value":{"stringValue":"curl/7.68.0"}},{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.host.port","value":{"intValue":"8000"}},{"key":"net.peer.ip","value":{"stringValue":"172.25.0.1"}},{"key":"net.peer.port","value":{"intValue":"51614"}},{"key":"test.attrib.global","value":{"stringValue":"global"}},{"key":"test.attrib.custom","value":{"stringValue":"global-custom"}}],"status":{}}]}]}]} +{"resourceSpans":[{"resource":{"attributes":[{"key":"telemetry.sdk.version","value":{"stringValue":"1.8.1"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.language","value":{"stringValue":"cpp"}},{"key":"service.name","value":{"stringValue":"nginx-proxy"}}]},"instrumentationLibrarySpans":[{"instrumentationLibrary":{"name":"nginx"},"spans":[{"traceId":"777151ac132afc1975887f8a3af71d23","spanId":"60bec6e1671cee32","parentSpanId":"","name":"otel_test","kind":"SPAN_KIND_SERVER","startTimeUnixNano":"1658331753935660143","endTimeUnixNano":"1658331753935827215","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.flavor","value":{"stringValue":"1.1"}},{"key":"http.target","value":{"stringValue":"/route_to_internal"}},{"key":"http.server_name","value":{"stringValue":"otel_test"}},{"key":"http.host","value":{"stringValue":"localhost:8000"}},{"key":"http.user_agent","value":{"stringValue":"curl/7.68.0"}},{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.host.port","value":{"intValue":"8000"}},{"key":"net.peer.ip","value":{"stringValue":"172.25.0.1"}},{"key":"net.peer.port","value":{"intValue":"51608"}},{"key":"test.attrib.global","value":{"stringValue":"global"}},{"key":"test.attrib.custom","value":{"stringValue":"global-custom"}}],"status":{}}]}]}]} +{"resourceSpans":[{"resource":{"attributes":[{"key":"telemetry.sdk.version","value":{"stringValue":"1.8.1"}},{"key":"telemetry.sdk.name","value":{"stringValue":"opentelemetry"}},{"key":"telemetry.sdk.language","value":{"stringValue":"cpp"}},{"key":"service.name","value":{"stringValue":"nginx-proxy"}}]},"instrumentationLibrarySpans":[{"instrumentationLibrary":{"name":"nginx"},"spans":[{"traceId":"579d297c39ddac461fbc50febd77f16a","spanId":"fecfc6a8c9b60f03","parentSpanId":"","name":"otel_test","kind":"SPAN_KIND_SERVER","startTimeUnixNano":"1658331755134563590","endTimeUnixNano":"1658331755134700342","attributes":[{"key":"http.method","value":{"stringValue":"GET"}},{"key":"http.flavor","value":{"stringValue":"1.1"}},{"key":"http.target","value":{"stringValue":"/route_to_internal"}},{"key":"http.server_name","value":{"stringValue":"otel_test"}},{"key":"http.host","value":{"stringValue":"localhost:8000"}},{"key":"http.user_agent","value":{"stringValue":"curl/7.68.0"}},{"key":"http.status_code","value":{"intValue":"200"}},{"key":"http.scheme","value":{"stringValue":"http"}},{"key":"net.host.port","value":{"intValue":"8000"}},{"key":"net.peer.ip","value":{"stringValue":"172.25.0.1"}},{"key":"net.peer.port","value":{"intValue":"51614"}},{"key":"test.attrib.global","value":{"stringValue":"global"}},{"key":"test.attrib.custom","value":{"stringValue":"global-custom"}}],"status":{}}]}]}]} \ No newline at end of file diff --git a/instrumentation/nginx/test/instrumentation/lib/mix/tasks/dockerfiles.ex b/instrumentation/nginx/test/instrumentation/lib/mix/tasks/dockerfiles.ex index 1c80021f7..c3300137c 100644 --- a/instrumentation/nginx/test/instrumentation/lib/mix/tasks/dockerfiles.ex +++ b/instrumentation/nginx/test/instrumentation/lib/mix/tasks/dockerfiles.ex @@ -1,8 +1,8 @@ defmodule Mix.Tasks.Dockerfiles do use Mix.Task - @grpc_version "v1.36.4" - @otel_cpp_version "v1.3.0" + @grpc_version "v1.49.2" + @otel_cpp_version "v1.8.1" def run([out_dir | combos]) do out_dir_abs = Path.expand(out_dir) @@ -178,6 +178,7 @@ defmodule Mix.Tasks.Dockerfiles do -DgRPC_BUILD_GRPC_PHP_PLUGIN=OFF \\ -DgRPC_BUILD_GRPC_PYTHON_PLUGIN=OFF \\ -DgRPC_BUILD_GRPC_RUBY_PLUGIN=OFF \\ + -DCMAKE_CXX_STANDARD=17 \\ ../.. \\ && make -j2 \\ && make install @@ -195,6 +196,7 @@ defmodule Mix.Tasks.Dockerfiles do -DWITH_OTLP_HTTP=OFF \\ -DBUILD_TESTING=OFF \\ -DWITH_EXAMPLES=OFF \\ + -DCMAKE_CXX_STANDARD=17 \\ -DCMAKE_POSITION_INDEPENDENT_CODE=ON \\ .. \\ && make -j2 \\ @@ -218,4 +220,4 @@ defmodule Mix.Tasks.Dockerfiles do CMD ["/usr/sbin/nginx", "-g", "daemon off;"] """ end -end +end \ No newline at end of file From 3cd65ccd415b4b952a1227b0296b546298315f5e Mon Sep 17 00:00:00 2001 From: Jeff Erbrecht <89024676+jefferbrecht@users.noreply.github.com> Date: Wed, 25 Jan 2023 05:57:48 -0500 Subject: [PATCH 46/77] Fix typos (#242) --- .../src/nginx/ngx_http_opentelemetry_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 2ba03510b..18bdee980 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -522,7 +522,7 @@ static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) ngx_uint_t phase_index; ngx_int_t res; - ngx_writeError(cf->cycle->log, __func__, "Starting Opentelemetry Modlue init"); + ngx_writeError(cf->cycle->log, __func__, "Starting Opentelemetry Module init"); cp = ap = pap = srp = prp = rp = lp = pcp = 0; @@ -626,7 +626,7 @@ static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) /* hostname is extracted from the nginx cycle. The attribute hostname is needed for OTEL spec and the only place it is available is cf->cycle */ - ngx_writeError(cf->cycle->log, __func__, "Opentelemetry Modlue init completed !"); + ngx_writeError(cf->cycle->log, __func__, "Opentelemetry Module init completed!"); return NGX_OK; } From 239819879e1cd99eda1ade63e581c24d2f8d850d Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 1 Feb 2023 15:51:34 -0800 Subject: [PATCH 47/77] Add deb/rpm/nuget packaging code, update histogram boundaries from list to vector (#254) --- exporters/geneva/CMakeLists.txt | 20 ++++-- exporters/geneva/cmake/ParseOsRelease.cmake | 22 ++++++ exporters/geneva/cmake/package.cmake | 71 +++++++++++++++++++ .../exporters/geneva/metrics/exporter.h | 2 +- exporters/geneva/src/exporter.cc | 2 +- .../geneva/test/common/generate_metrics.h | 6 +- 6 files changed, 114 insertions(+), 9 deletions(-) create mode 100644 exporters/geneva/cmake/ParseOsRelease.cmake create mode 100644 exporters/geneva/cmake/package.cmake diff --git a/exporters/geneva/CMakeLists.txt b/exporters/geneva/CMakeLists.txt index 57f3eba7c..b3d6a32b4 100644 --- a/exporters/geneva/CMakeLists.txt +++ b/exporters/geneva/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.12) # (using add_subdirectory) or if it is the main project # set(MAIN_PROJECT OFF) -set(MAIN_PROJECT OFF) + if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(opentelemetry-geneva-metrics) set(MAIN_PROJECT ON) @@ -13,6 +13,7 @@ endif() if(NOT WIN32) find_package(CURL REQUIRED) endif() + add_definitions(-DHAVE_CONSOLE_LOG) if(MAIN_PROJECT) find_package(opentelemetry-cpp REQUIRED) @@ -31,13 +32,18 @@ else() src/exporter.cc src/unix_domain_socket_data_transport.cc) endif() -target_include_directories(opentelemetry_exporter_geneva_metrics - PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) -target_link_libraries(opentelemetry_exporter_geneva_metrics +if(MAIN_PROJECT) + target_include_directories(opentelemetry_exporter_geneva_metrics + PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) + target_link_libraries(opentelemetry_exporter_geneva_metrics PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES}) +else() + target_link_libraries(opentelemetry_exporter_geneva_metrics + PUBLIC opentelemetry_metrics opentelemetry_resources opentelemetry_common) +endif() + set_target_properties(opentelemetry_exporter_geneva_metrics PROPERTIES EXPORT_NAME metrics) - if(BUILD_TESTING) if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) # Prefer GTest from build tree. GTest is not always working with @@ -90,3 +96,7 @@ if(BUILD_EXAMPLE) example/foo_library.cc) target_link_libraries(example_metrics opentelemetry_exporter_geneva_metrics) endif() +if(MAIN_PROJECT AND BUILD_PACKAGE) + include(cmake/package.cmake) + include(CPack) +endif() \ No newline at end of file diff --git a/exporters/geneva/cmake/ParseOsRelease.cmake b/exporters/geneva/cmake/ParseOsRelease.cmake new file mode 100644 index 000000000..fafbfd57f --- /dev/null +++ b/exporters/geneva/cmake/ParseOsRelease.cmake @@ -0,0 +1,22 @@ +# Parse /etc/os-release to determine Linux distro + +if(EXISTS /etc/os-release) +file(STRINGS /etc/os-release OS_RELEASE) +foreach(NameAndValue ${OS_RELEASE}) + # Strip leading spaces + string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue}) + # Find variable name + string(REGEX MATCH "^[^=]+" Name ${NameAndValue}) + # Find the value + string(REPLACE "${Name}=" "" Value ${NameAndValue}) + # Strip quotes from value + string(REPLACE "\"" "" Value ${Value}) + # Set the variable + message("-- /etc/os-release : ${Name}=${Value}") + set("OS_RELEASE_${Name}" "${Value}") +endforeach() +else() + set("OS_RELEASE_NAME" ${CMAKE_SYSTEM_NAME}) + set("OS_RELEASE_ID" ${CMAKE_SYSTEM_NAME}) + set("OS_RELEASE_VERSION_ID" "1.0") +endif() \ No newline at end of file diff --git a/exporters/geneva/cmake/package.cmake b/exporters/geneva/cmake/package.cmake new file mode 100644 index 000000000..3f134a4fb --- /dev/null +++ b/exporters/geneva/cmake/package.cmake @@ -0,0 +1,71 @@ +set(CPACK_PACKAGE_DESCRIPTION "OpenTelemetry C++ Geneva Exporter for Metrics") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenTelemetry C++ Geneva Exporter for Metrics - C++ Implementation of OpenTelemetry C++ Exporter to Upload Metics to Geneva") +set(CPACK_PACKAGE_VENDOR "OpenTelemetry") +set(CPACK_PACKAGE_CONTACT "OpenTelemetry-cpp") +set(CPACK_PACKAGE_HOMEPAGE_URL "https://opentelemetry.io/") +set(CMAKE_PROJECT_NAME "opentelemetry-cpp-geneva-metrics") +set(OPENTELEMETRY_GENEVA_METRICS_VERSION "1.0.0") + +option(TARBALL "Build a tarball package" OFF) + +if (UNIX AND NOT APPLE) + include(cmake/ParseOsRelease.cmake) + set(CPACK_SYSTEM_NAME "${OS_RELEASE_ID}-${OS_RELEASE_VERSION_ID}") + #set(CPACK_PACKAGING_INSTALL_PREFIX "/usr/local") + set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${OPENTELEMETRY_GENEVA_METRICS_VERSION}-${CPACK_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}") + + # Check if system is deb or rpm capable + find_program(RPMCAPABLE rpmbuild) + find_program(DEBCAPABLE dpkg-buildpackage) + if (TARBALL) + set(CPACK_GENERATOR "TGZ") + message("-- Package name: ${CPACK_PACKAGE_FILE_NAME}.tar.gz") + elseif (DEBCAPABLE MATCHES "NOTFOUND" AND RPMCAPABLE MATCHES "NOTFOUND") + message(FATAL_ERROR "Required Package generator not found for either deb or rpm." + " Install required package generation software and try again") + elseif (NOT DEBCAPABLE MATCHES "NOTFOUND") + if (NOT RPMCAPABLE MATCHES "NOTFOUND") + message(WARNING "Both deb and rpm package generator found." + "Selecting deb as default packager.") + endif() + set(CPACK_GENERATOR "DEB") + set(INSTALL_LIB_DIR + ${CMAKE_INSTALL_PREFIX}/lib/${CPACK_DEBIAN_ARCHITECTURE}-linux-gnu) + set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") + set(CPACK_DEBIAN_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) + #set(CPACK_COMPONENTS_ALL headers libraries) + set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON) + message("-- Package name: ${CPACK_PACKAGE_FILE_NAME}.deb") + elseif(NOT RPMCAPABLE MATCHES "NOTFOUND") + set(CPACK_GENERATOR "RPM") + set(INSTALL_LIB_DIR + ${CMAKE_INSTALL_PREFIX}/lib/${CMAKE_SYSTEM_PROCESSOR}-linux-gnu) + list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/lib64/cmake") + list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/usr/lib64/pkgconfig") + set(CPACK_RPM_PACKAGE_LICENSE "Apache-2.0") + message("-- Package name: ${CPACK_PACKAGE_FILE_NAME}.rpm") + endif() +elseif(APPLE) + if (TARBALL) + set(CPACK_GENERATOR "TGZ") + message("-- Package name: ${CPACK_PACKAGE_FILE_NAME}.tar.gz") + endif() +elseif(WIN32) + find_program(NUGETCAPABLE nuget) + if(NOT NUGETCAPABLE MATCHES "NOTFOUND") + set(CPACK_NUGET_PACKAGE_NAME "${CPACK_PROJECT_NAME}") + set(CPACK_NUGET_PACKAGE_VERSION "${OPENTELEMETRY_GENEVA_METRICS_VERSION}") + set(CPACK_NUGET_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}") + set(CPACK_NUGET_PACKAGE_AUTHORS "${CPACK_PACKAGE_VENDOR}") + set(CPACK_NUGET_PACKAGE_TITLE "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") + set(CPACK_NUGET_PACKAGE_OWNERS "${CPACK_PACKAGE_VENDOR}") + set(CPACK_NUGET_PACKAGE_HOMEPAGE_URL "${CPACK_PACKAGE_HOMEPAGE_URL}") + set(CPACK_NUGET_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") + set(CPACK_NUGET_PACKAGE_COPYRIGHT "${CPACK_PACKAGE_VENDOR}") + set(CPACK_NUGET_PACKAGE_LICENSEURL "https://www.apache.org/licenses/LICENSE-2.0.txt") + set(CPACK_NUGET_PACKAGE_LANGUAGE "en_US") + set(CPACK_GENERATOR NuGet) + else() + set(CPACK_GENERATOR ZIP) + endif() +endif() \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h index e780c5acd..855eb9467 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -81,7 +81,7 @@ class Exporter final : public opentelemetry::sdk::metrics::PushMetricExporter { size_t SerializeHistogramMetrics( sdk::metrics::AggregationType, MetricsEventType, uint64_t, const sdk::metrics::ValueType &, const sdk::metrics::ValueType &, - const sdk::metrics::ValueType &, const std::list &boundaries, + const sdk::metrics::ValueType &, const std::vector &boundaries, const std::vector &counts, common::SystemTimestamp, const std::string &, const sdk::metrics::PointAttributes &); }; diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc index 32a66c8d3..8bc4e91fb 100644 --- a/exporters/geneva/src/exporter.cc +++ b/exporters/geneva/src/exporter.cc @@ -275,7 +275,7 @@ size_t Exporter::SerializeHistogramMetrics( sdk::metrics::AggregationType agg_type, MetricsEventType event_type, uint64_t count, const sdk::metrics::ValueType &sum, const sdk::metrics::ValueType &min, const sdk::metrics::ValueType &max, - const std::list &boundaries, const std::vector &counts, + const std::vector &boundaries, const std::vector &counts, common::SystemTimestamp ts, const std::string &metric_name, const sdk::metrics::PointAttributes &attributes) { diff --git a/exporters/geneva/test/common/generate_metrics.h b/exporters/geneva/test/common/generate_metrics.h index ac5e1604f..588e3c26e 100644 --- a/exporters/geneva/test/common/generate_metrics.h +++ b/exporters/geneva/test/common/generate_metrics.h @@ -3,6 +3,8 @@ #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/resource/resource.h" +#include + namespace { // Instrument Scope @@ -222,7 +224,7 @@ const uint16_t kHistogramLongBucketSize = 10; const uint16_t kHistogramLongNonEmptyBucketSize = 8; const std::vector kHistogramLongCounts = {1, 2, 1, 0, 0, 1, 2, 3, 4, 1}; -const std::list kHistogramLongBoundaries = std::list{ +const std::vector kHistogramLongBoundaries = std::vector{ 0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 1000.0}; const std::string kHistogramLongAttributeKey1 = "histogram_long_key1"; @@ -269,4 +271,4 @@ GenerateHistogramDataLongMetrics() { return data; } -} // namespace \ No newline at end of file +} // namespace From 3052e97fc864077ef34deb96d34cf0e088f01300 Mon Sep 17 00:00:00 2001 From: Shoma Kokuryo Date: Wed, 15 Feb 2023 20:03:55 +0900 Subject: [PATCH 48/77] use archive.apache.org/dist instead of dlcdn.apache.org (#257) --- instrumentation/otel-webserver-module/Dockerfile | 4 ++-- instrumentation/otel-webserver-module/codeql-env.sh | 4 ++-- .../otel-webserver-module/docker/centos7/Dockerfile | 4 ++-- .../otel-webserver-module/docker/ubuntu20.04/Dockerfile | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/instrumentation/otel-webserver-module/Dockerfile b/instrumentation/otel-webserver-module/Dockerfile index 10b678861..d83f84f48 100644 --- a/instrumentation/otel-webserver-module/Dockerfile +++ b/instrumentation/otel-webserver-module/Dockerfile @@ -117,7 +117,7 @@ RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/sou #install Apr RUN mkdir -p dependencies/apr/${APR_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-${APR_VERSION}.tar.gz \ && cd apr-${APR_VERSION} \ && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ @@ -137,7 +137,7 @@ RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ # install Apr-util RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ && cd apr-util-${APRUTIL_VERSION} \ && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION} --with-expat=/dependencies/expat/${EXPAT_VERSION} && echo $? \ diff --git a/instrumentation/otel-webserver-module/codeql-env.sh b/instrumentation/otel-webserver-module/codeql-env.sh index c45b434fe..711f349fb 100755 --- a/instrumentation/otel-webserver-module/codeql-env.sh +++ b/instrumentation/otel-webserver-module/codeql-env.sh @@ -81,7 +81,7 @@ mkdir -p /dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ #install Apr mkdir -p /dependencies/apr/${APR_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-${APR_VERSION}.tar.gz \ && cd apr-${APR_VERSION} \ && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ @@ -101,7 +101,7 @@ mkdir -p /dependencies/expat/${EXPAT_VERSION} \ # install Apr-util mkdir -p /dependencies/apr-util/${APRUTIL_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ && cd apr-util-${APRUTIL_VERSION} \ && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/1.7.0 --with-expat=/dependencies/expat/2.3.0 && echo $? \ diff --git a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile index afd224ec5..a6ffe2023 100644 --- a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile @@ -123,7 +123,7 @@ RUN wget https://boostorg.jfrog.io/artifactory/main/release/${BOOST_VERSION}/sou #install Apr RUN mkdir -p dependencies/apr/${APR_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-${APR_VERSION}.tar.gz \ && cd apr-${APR_VERSION} \ && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ @@ -143,7 +143,7 @@ RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ # install Apr-util RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ && cd apr-util-${APRUTIL_VERSION} \ && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/${APR_VERSION} --with-expat=/dependencies/expat/${EXPAT_VERSION} && echo $? \ diff --git a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile index f694cd65d..81d717668 100644 --- a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile @@ -83,7 +83,7 @@ RUN mkdir -p dependencies/opentelemetry/${OPENTELEMETRY_VERSION}/lib \ #install Apr RUN mkdir -p dependencies/apr/${APR_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-${APR_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-${APR_VERSION}.tar.gz \ && cd apr-${APR_VERSION} \ && ./configure --prefix=/dependencies/apr/${APR_VERSION} --enable-static=yes --enable-shared=no --with-pic && echo $? \ @@ -103,7 +103,7 @@ RUN mkdir -p dependencies/expat/${EXPAT_VERSION} \ # install Apr-util RUN mkdir -p dependencies/apr-util/${APRUTIL_VERSION} \ - && wget https://dlcdn.apache.org//apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ + && wget https://archive.apache.org/dist/apr/apr-util-${APRUTIL_VERSION}.tar.gz --no-check-certificate \ && tar -xf apr-util-${APRUTIL_VERSION}.tar.gz \ && cd apr-util-${APRUTIL_VERSION} \ && ./configure --prefix=/dependencies/apr-util/${APRUTIL_VERSION} --enable-static=yes --enable-shared=no --with-pic --with-apr=/dependencies/apr/1.7.0 --with-expat=/dependencies/expat/2.3.0 && echo $? \ From 9855e025d2e2948184b7e91ebcfb2b73307711e7 Mon Sep 17 00:00:00 2001 From: SaschaBrechmannVHV <77098451+SaschaBrechmannVHV@users.noreply.github.com> Date: Tue, 21 Feb 2023 12:39:54 +0100 Subject: [PATCH 49/77] Link should point to OT Repository (#261) Link should point to OT Repository and not to Cisco Repository --- instrumentation/otel-webserver-module/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index b1626c07a..0b8201b12 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -60,7 +60,7 @@ Monitoring individual modules is crucial to the instrumentation of Apache web se |*ApacheModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| |*ApacheModuleOtelExporterHeaders* | | OPTIONAL: OTEL Exporter header info or Metadata like API key for OTLP endpoint. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2. | -A sample configuration is mentioned in [opentelemetry_module.conf](https://github.com/cisco-open/otel-webserver-module/blob/main/opentelemetry_module.conf) +A sample configuration is mentioned in [opentelemetry_module.conf](https://github.com/open-telemetry/opentelemetry-cpp-contrib/blob/main/instrumentation/otel-webserver-module/opentelemetry_module.conf) ### Build and Installation #### Prerequisites From 8bdab8d7129c38c81e3373bb87df4af29777aac6 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 27 Feb 2023 13:51:37 -0800 Subject: [PATCH 50/77] [Geneva Metrics] Small fix in example for Geneva metrics exporter (#263) --- .github/workflows/geneva_metrics.yml | 46 +++++++++++++++++++++ exporters/geneva/example/example_metrics.cc | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/geneva_metrics.yml diff --git a/.github/workflows/geneva_metrics.yml b/.github/workflows/geneva_metrics.yml new file mode 100644 index 000000000..a6834b8cb --- /dev/null +++ b/.github/workflows/geneva_metrics.yml @@ -0,0 +1,46 @@ +name: Geneva Metrics CI + +on: + push: + branches: "*" + paths: + - "exporters/geneva/**" + - ".github/workflows/geneva_metrics.yml" + pull_request: + branches: [main] + paths: + - "exporters/geneva/**" + - ".github/workflows/geneva_metrics.yml" + + cmake_linux: + name: CMake on Linux + runs-on: ubuntu-latest + steps: + - name: checkout otel contrib geneva metrics + uses: actions/checkout@v3 + with: + path: "otel_cpp_contrib" + - name: checkout otel cpp + uses: actions/checkout@v3 + with: + repository: "open-telemetry/opentelemetry-cpp" + ref: "v1.8.2" + path: "otel_cpp" + submodules: "recursive" + - name: setup + run: | + sudo apt update -y + sudo apt install -y --no-install-recommends --no-install-suggests build-essential\ + ca-certificates wget git valgrind lcov + - name: run tests + run: | + mkdir -p "$GITHUB_WORKSPACE/otel_cpp/build" + cd "$GITHUB_WORKSPACE/otel_cpp/build" + cmake .. -DCMAKE_BUILD_TYPE=Debug + cmake --build . -j --config Debug + cmake --install . --prefix "$HOME/prebuilt-otel" --config Debug + mkdir -p "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/geneva/build" + cd "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/geneva/build" + cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" -DCMAKE_BUILD_TYPE=Debug \ + -DBUILD_TESTING=ON -DBUILD_EXAMPLE=ON + cmake --build . -j --config Debug \ No newline at end of file diff --git a/exporters/geneva/example/example_metrics.cc b/exporters/geneva/example/example_metrics.cc index d88f84621..efbac42fa 100644 --- a/exporters/geneva/example/example_metrics.cc +++ b/exporters/geneva/example/example_metrics.cc @@ -89,7 +89,7 @@ void initMetrics(const std::string &name, const std::string &account_name) { new opentelemetry::sdk::metrics::HistogramAggregationConfig()}; static_cast( aggregation_config.get()) - ->boundaries_ = std::list{0.0, 50.0, 100.0, 250.0, 500.0, + ->boundaries_ = std::vector{0.0, 50.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 10000.0}; std::unique_ptr histogram_view{new metric_sdk::View{ name, "description", metric_sdk::AggregationType::kHistogram, From 1da270987632b818e3d8930507ff6e4cb7d1cdaa Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 2 Mar 2023 10:27:39 -0800 Subject: [PATCH 51/77] Geneva trace/log exporter include wrappers (#262) --- .github/workflows/geneva_trace.yml | 32 +++++++ .gitmodules | 3 + .../exporters/geneva/geneva_fields.h | 79 +++++++++++++++++ .../exporters/geneva/geneva_logger_exporter.h | 11 +++ .../exporters/geneva/geneva_tracer_exporter.h | 10 +++ .../third_party/opentelemetry-cpp | 1 + exporters/geneva-trace/tools/build-nuget.cmd | 24 +++++ exporters/geneva-trace/tools/build-nuget.ps1 | 82 ++++++++++++++++++ .../nuget/OpenTelemetry.Cpp.Geneva.nuspec | 24 +++++ exporters/geneva-trace/tools/nuget/README.md | 26 ++++++ .../native/OpenTelemetry.Cpp.Geneva.targets | 9 ++ .../tools/nuget/opentelemetry-icon-color.png | Bin 0 -> 47847 bytes 12 files changed, 301 insertions(+) create mode 100644 .github/workflows/geneva_trace.yml create mode 100644 .gitmodules create mode 100644 exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_fields.h create mode 100644 exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_logger_exporter.h create mode 100644 exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_tracer_exporter.h create mode 160000 exporters/geneva-trace/third_party/opentelemetry-cpp create mode 100644 exporters/geneva-trace/tools/build-nuget.cmd create mode 100644 exporters/geneva-trace/tools/build-nuget.ps1 create mode 100644 exporters/geneva-trace/tools/nuget/OpenTelemetry.Cpp.Geneva.nuspec create mode 100644 exporters/geneva-trace/tools/nuget/README.md create mode 100644 exporters/geneva-trace/tools/nuget/build/native/OpenTelemetry.Cpp.Geneva.targets create mode 100644 exporters/geneva-trace/tools/nuget/opentelemetry-icon-color.png diff --git a/.github/workflows/geneva_trace.yml b/.github/workflows/geneva_trace.yml new file mode 100644 index 000000000..65bbc184b --- /dev/null +++ b/.github/workflows/geneva_trace.yml @@ -0,0 +1,32 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +name: Geneva Trace Nuget Generation + +on: + push: + branches: "*" + paths: + - "exporters/geneva-trace/**" + - ".github/workflows/geneva_trace.yml" + pull_request: + branches: [main] + paths: + - "exporters/geneva-trace/**" + - ".github/workflows/geneva_trace.yml" + +jobs: + geneva-trace-nuget-generation: + name: Geneva Trace + runs-on: windows-latest + steps: + - name: github config + run: git config --system core.longpaths true + - uses: actions/checkout@v3 + with: + submodules: 'recursive' + - name: NuGet package generation + env: + PackageVersion: 0.0.1 + run: | + cd exporters\geneva-trace\tools && .\build-nuget.cmd diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..eabbc692f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "exporters/geneva-trace/third_party/opentelemetry-cpp"] + path = exporters/geneva-trace/third_party/opentelemetry-cpp + url = https://github.com/open-telemetry/opentelemetry-cpp diff --git a/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_fields.h b/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_fields.h new file mode 100644 index 000000000..5c64a530c --- /dev/null +++ b/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_fields.h @@ -0,0 +1,79 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +/* clang-format off */ + +/** + * List of configurable Field Name constants: + * + * - env_ver - Schema version (optional for ETW exporter). + * - env_name - Built-in ETW name at envelope level (dedicated ETW field). + * - env_time - Built-in ETW time at envelope level. + * - env_dt_spanId - OT SpanId + * - env_dt_traceId - OT TraceId + * - startTime - OT Span start time + * - kind - OT Span kind + * - name - OT Span name in ETW 'Payload["name"]' + * - parentId - OT Span parentId + * - links - OT Span links array + * + * Other standard fields (reserved names) that may be appended by ETW channel: + * + * - Level + * - ProviderGuid + * - ProviderName + * - OpcodeName + * - KeywordName + * - TaskName + * - ChannelName + * - EventMessage + * - ActivityId + * - Pid + * - Tid + * + */ +# define ETW_FIELD_VERSION "env_ver" /* Event version */ +# define ETW_FIELD_TYPE "env_type" /* Event type */ +# define ETW_FIELD_NAME "env_name" /* Event name */ + +#ifndef HAVE_FIELD_TIME +#define HAVE_FIELD_TIME +#endif +# define ETW_FIELD_TIME "env_time" /* Event time at envelope */ + +# define ETW_FIELD_OPCODE "env_opcode" /* OpCode for TraceLogging */ + +# define ETW_FIELD_TRACE_ID "env_dt_traceId" /* Trace Id */ +# define ETW_FIELD_SPAN_ID "env_dt_spanId" /* Span Id */ +# define ETW_FIELD_SPAN_PARENTID "parentId" /* Span ParentId */ +# define ETW_FIELD_SPAN_KIND "kind" /* Span Kind */ +# define ETW_FIELD_SPAN_LINKS "links" /* Span Links array */ + +# define ETW_FIELD_PAYLOAD_NAME "name" /* ETW Payload["name"] */ + +/* Span option constants */ +# define ETW_FIELD_STARTTIME "startTime" /* Operation start time */ +# define ETW_FIELD_ENDTTIME "env_time" /* Operation end time */ +# define ETW_FIELD_DURATION "duration" /* Operation duration */ +# define ETW_FIELD_STATUSCODE "statusCode" /* OT Span status code */ +# define ETW_FIELD_STATUSMESSAGE "statusMessage" /* OT Span status message */ +# define ETW_FIELD_SUCCESS "success" /* OT Span success */ +# define ETW_FIELD_TIMESTAMP "Timestamp" /* Log timestamp */ + +# define ETW_FIELD_CLIENTREQID "clientRequestId" +# define ETW_FIELD_CORRELREQID "correlationRequestId" + +/* Value constants */ +# define ETW_VALUE_SPAN "Span" /* ETW event name for Span */ +# define ETW_VALUE_LOG "Log" /* ETW event name for Log */ + +# define ETW_VALUE_SPAN_START "SpanStart" /* ETW for Span Start */ +# define ETW_VALUE_SPAN_END "SpanEnd" /* ETW for Span Start */ + +# define ETW_FIELD_LOG_BODY "body" /* Log body */ +# define ETW_FIELD_LOG_SEVERITY_TEXT "severityText" /* Sev text */ +# define ETW_FIELD_LOG_SEVERITY_NUM "severityNumber" /* Sev num */ + +/* clang-format on */ diff --git a/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_logger_exporter.h b/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_logger_exporter.h new file mode 100644 index 000000000..46cb90084 --- /dev/null +++ b/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_logger_exporter.h @@ -0,0 +1,11 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifndef CUSTOM_ETW_FIELDS_H +#define CUSTOM_ETW_FIELDS_H +#endif + +#define ENABLE_LOGS_PREVIEW +#include diff --git a/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_tracer_exporter.h b/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_tracer_exporter.h new file mode 100644 index 000000000..3ee876eaf --- /dev/null +++ b/exporters/geneva-trace/include/opentelemetry/exporters/geneva/geneva_tracer_exporter.h @@ -0,0 +1,10 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifndef CUSTOM_ETW_FIELDS_H +#define CUSTOM_ETW_FIELDS_H +#endif + +#include diff --git a/exporters/geneva-trace/third_party/opentelemetry-cpp b/exporters/geneva-trace/third_party/opentelemetry-cpp new file mode 160000 index 000000000..95f6c66de --- /dev/null +++ b/exporters/geneva-trace/third_party/opentelemetry-cpp @@ -0,0 +1 @@ +Subproject commit 95f6c66de253e46d09b232facc840b311a4a354d diff --git a/exporters/geneva-trace/tools/build-nuget.cmd b/exporters/geneva-trace/tools/build-nuget.cmd new file mode 100644 index 000000000..71c898623 --- /dev/null +++ b/exporters/geneva-trace/tools/build-nuget.cmd @@ -0,0 +1,24 @@ +Rem Copyright The OpenTelemetry Authors +Rem SPDX-License-Identifier: Apache-2.0 + +@echo off +pushd "%~dp0" +set "PATH=%CD%;%PATH%" + +if not defined PackageVersion ( + echo "Set the PackageVersion before proceeding." + exit +) +if not exist "..\packages" mkdir "..\packages" + +REM This script assumes that the main OpenTelemetry C++ repo +REM has been checked out as submodule +powershell -File .\build-nuget.ps1 %CD%\..\third_party\opentelemetry-cpp + +REM If %OUTPUTROOT% variable is defined, then copy the packages +REM to %OUTPUTROOT%\packages for subsequent deployment. +if defined OUTPUTROOT ( + if not exist "%OUTPUTROOT%\packages" mkdir "%OUTPUTROOT%\packages" + copy /Y ..\packages\*.nupkg "%OUTPUTROOT%\packages" +) +popd diff --git a/exporters/geneva-trace/tools/build-nuget.ps1 b/exporters/geneva-trace/tools/build-nuget.ps1 new file mode 100644 index 000000000..4979b3726 --- /dev/null +++ b/exporters/geneva-trace/tools/build-nuget.ps1 @@ -0,0 +1,82 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +$otel_repo_main=$args[0] + +# Function returns 4-part 'classic' version string from SemVer 2.0 string +function GenVer4Part([String] $Version) +{ + if ($Version[0] -eq 'v') + { + # If tag contains 'v' then strip it + $Version = $Version.substring(1) + } + # Converts from 1.2.3-build4 to 1.2.3.4 + $Version = $Version -replace "-build", "." + $Version = $Version -replace "-", "." + + [int32[]]$parts = $Version.Split('.'); + # Add missing tuples + $i = $parts.Count + while($i -lt 4) + { + $parts += "0" + $i++ + } + + ,$parts +} + +function New-TemporaryDirectory +{ + $parent = [System.IO.Path]::GetTempPath() + [string] $name = [System.Guid]::NewGuid() + New-Item -ItemType Directory -Path (Join-Path $parent $name) +} + +function GetGitWorkTree() +{ + # TODO: presently we assume that GIT_WORK_TREE is 1-level up. + # Uncomment the following line if this is not the case: + # $result = (git rev-parse --show-toplevel) -join '' + $result = ( Get-Item -Path .. ).Fullname + $result = $result -replace '[\\/]', '\' + return $result +} + +function CopyAll([String] $src, [String] $dest) +{ + $what = @("/E","/XD",".vs","packages","examples",".*") + $options = @("/R:0","/W:0","/NFL","/NDL","/NJH","/NJS","/NC","/NS") + $cmdArgs = @("$src","$dest",$what,$options) + robocopy @cmdArgs +} + +$tempDir = New-TemporaryDirectory +$gitWorktree = GetGitWorkTree + +$items = Get-ChildItem .\nuget -include *.nuspec -Recurse +foreach ($item in $items) +{ + $nugetName = $item.Basename + $v = GenVer4Part $env:PackageVersion + $version = [string]::Join(".", $v, 0, 3) + + Write-Output "Creating nuget $nugetName-$version ..." + # Copy all files from Git + CopyAll $otel_repo_main $tempDir.Fullname + + CopyAll $gitWorkTree\include\ $tempDir\exporters\etw\include + + # Append extra nuget package files + Copy-Item -Path ".\nuget\build" -Recurse -Destination $tempDir.Fullname + Copy-Item -Path ".\nuget\$nugetName.nuspec" -Destination $tempDir.Fullname + Copy-Item -Path ".\nuget\opentelemetry-icon-color.png" -Destination $tempDir.Fullname + # Change to temporary directory + Push-Location -Path $tempDir.Fullname + # Pack the nuget package + nuget pack $nugetName.nuspec -Version $version -NoDefaultExcludes + Pop-Location + $nupkgFileName = "$tempDir\$nugetName.$version.nupkg" + Get-Item $nupkgFileName | Copy-Item -Destination "..\packages" +} diff --git a/exporters/geneva-trace/tools/nuget/OpenTelemetry.Cpp.Geneva.nuspec b/exporters/geneva-trace/tools/nuget/OpenTelemetry.Cpp.Geneva.nuspec new file mode 100644 index 000000000..05335e709 --- /dev/null +++ b/exporters/geneva-trace/tools/nuget/OpenTelemetry.Cpp.Geneva.nuspec @@ -0,0 +1,24 @@ + + + OpenTelemetry.Cpp.Geneva + 0.0.0 + Microsoft + false + Apache-2.0 + https://licenses.nuget.org/Apache-2.0 + opentelemetry-icon-color.png + https://opentelemetry.io/ + OpenTelemetry C++ API/SDK with Geneva Exporter + Observability OpenTelemetry Monitoring Telemetry Tracing native C++ Geneva + + + + + + + + + + + + diff --git a/exporters/geneva-trace/tools/nuget/README.md b/exporters/geneva-trace/tools/nuget/README.md new file mode 100644 index 000000000..5c902709e --- /dev/null +++ b/exporters/geneva-trace/tools/nuget/README.md @@ -0,0 +1,26 @@ +# NuGet package creation process + +This directory contains NuGet specification files (.nuspec). + +Creating nuget packages: + +- Set `PackageVersion` environment variable that defines the package version. + +```console +set PackageVersion=0.4.0 +``` + +- Run `tools/build-nuget.cmd` script to create the package(s). Packages are copied to `.\packages` +directory. + +- Push selected package to nuget feed using `NuGet.exe` tool. + +Learn more about native code NuGet packages [here](https://docs.microsoft.com/en-us/nuget/guides/native-packages). + +## NuGet package flavors + +The following packages created : + +| Package Name | Desription | Notes | +|------------------------------|-------------------------------------------------------------|-------| +| OpenTelemetry.Cpp.Geneva | OpenTelemetry C++ SDK with Geneva Exporter in one package | | diff --git a/exporters/geneva-trace/tools/nuget/build/native/OpenTelemetry.Cpp.Geneva.targets b/exporters/geneva-trace/tools/nuget/build/native/OpenTelemetry.Cpp.Geneva.targets new file mode 100644 index 000000000..0db4cdf23 --- /dev/null +++ b/exporters/geneva-trace/tools/nuget/build/native/OpenTelemetry.Cpp.Geneva.targets @@ -0,0 +1,9 @@ + + + + + HAVE_TLD;HAVE_ABSEIL_VARIANT;%(PreprocessorDefinitions) + $(MSBuildThisFileDirectory)\..\..\api\include;$(MSBuildThisFileDirectory)\..\..\exporters\etw\include;$(MSBuildThisFileDirectory)\..\..\sdk\include;%(AdditionalIncludeDirectories) + + + diff --git a/exporters/geneva-trace/tools/nuget/opentelemetry-icon-color.png b/exporters/geneva-trace/tools/nuget/opentelemetry-icon-color.png new file mode 100644 index 0000000000000000000000000000000000000000..c08946be7bcc61ed9fe00258d40d41d57aa06a63 GIT binary patch literal 47847 zcma$(c|4R~_ZNjE5k*Co3ay07GMJ)GS=tvRm7-D+Y3x%eWNl9vllEN{r7)HD7%C+d zq8d9BW#@P9y^rtv@9+J5`n;Yy_ndpqx#ymHw&(dqIyo#DCO1Y7AvA2!Lfd5s$rRy# zveGbe&NSa2{%?ra!nHmKjhcx6Ni146p#>o=w8(bO3QkhPcl+JW3(jzVEGtruts18I zPa#QT%}_qRK*WlH#>G})QHgC z-f=Yz^~Q*qK4T%%2a& z^QGvYiY_CHB5eOK?Xq!nKrBDbySR19c3Q zmTRV6zLUMP;KJe7@LAfu$?g}W&`d_sv1#j;Z1f!~>i?mhm))3IEF9`@jgSSihQhsd zODg=FMb_re76jW(D$vXLweLXlFjUEGgn*ZQ3)A=IOXJTx-Hcz|a^-qRF^LkN7GAPB z;M}qeC)Ebl zg-7YZ8TV+_1d%Z_5q;;GMP_Rf%A07jNWU3<()f4A8%MMvulOj`%vUAi6-k& zXwTy3ty5NKx@Y)L@46PDfKEO&rcxVscij?EmA_x&tv=y*>lFy8B@ZKt$d$?F^i>pY zHO%_1+qExVI25V8ktW(Eu&nCTpXJ=QdRDOn_bww-4RO#49dl%8PIr>cGB^y&MB7pN zo+=BYbW)|z1u92wQGTmVWDOGNQ>E9MDt_#Np-m~Y>>}2kg8(i+0Inpwfx!LqyaT}Flc}J?w0N`U*vg=Ex~JUVks^B~pw*L3=Wnm_KVb`6HVBSmib_c-Qx zGdxd#=L$x+I*}rIHq6h}rUXA%5{`}sf`b@_=E3s;{5odT8`vAfV7s6soOBkTB`Ea*{d}Lv7~GHnHx(xx#o!SXTpqyZ zVsK{hLrTJH1e~re(8~82gTbq*aI`GMNk;&@$dC&26@bqHa1%zc(v^hUG59b>7E|+m zBte$^8Fcj`0B3{jJ($(o>{xnQuvcT4)pL}DLzdXeaHZ+$Y=e9s4DCmuy-dXFxg+3t zGxMwh&*Oo(OO&`u*D5p5iST@wdDf~jV=V@BZy09E^L)&g4Xh(q_Z*lbPi$ zl!ZTBftwXZb{I78h*CEii*@hct%v1{7qG6CRo_=bTtp) zy#ULGIc6rXx*>qq9HWXCqa@VE-~l@1RIqLGePl8CI9YP)ieUAp0A9I}u5Q9+$zWpD z=g`&PM2ZAb_?e;RC_InC&vfg!cJPd;Ej>Y(8#zLFKm)cSO@_*D@_3$9An20o0*Zfy zElWlLPOU(Jl7BUfqoBSB=y9j?I7x`rYa&59j#N5)uPU=5W1v5ic?R8!$G^uh&ra}+ zb!|8UuO(Jji-6~L=2;D%@k!C3^vLP(q{f44$Qsad>!bj`13a5U=~Dsz<+M|!6d9v9 zURikHX+#YQqsLwlk?+HI0{*orxZwz~x_%OXn^N#-0H2J(k5X|+0r(pXPBmY^1@L7U zoKk0~C|19U!CR>`)VLf4lexAs{OuH-n=Vf(2B`HoP0@{x6tORWw9ieTo2d)JF;&vw z{-)^S4{#I)!RkdSl-U3Pe*&wU*wD=!2jG}^dq#G8Rc4BK^}lrW8USyB+mBsBpH1P| zwG0FFJ1DbWgT(5UO96f*wK|pTDl-ATkgik5Pau)+!%c?uR?MU8Sw@ObAdr9c2qiyI zQ7EAR_o35ZN}t~Zo|O7LV3!eo14yq16HrVE;2hy76iopFHd6vxfB>zb@T^0h(++bK z;!nYRZ)QFylc6m9o=WA>0^&5($ME#oD-NFJFg$%OQW8qc2SYY+`2+dOfc$7`WVKjg zb-q5Z%Uu4l_AD9w;}Hr1eTPr=_fKF~R_o&QcRg{nQY!VcF8P{+PZ=Z2)h;E>!%w`8 z30CZ4Pr$D~mK?UQ4Dit|o}BeH+Q43uF9&XjS{QX&bh1YXC9ZE)*5J;eq=lugTOwR; zcgJ3XkB{S*hflHV%{5#VRr~ei`(|AQr%J#?Rx+;abVCO+fesx+f;v@1HGPZf9Vxs-*&w zzChWzSC{izG7QeW7d7eJ-=$VEvW|d2sq)YwAixAH{ zahZAYyVIW)X@@#C5g9sKjVM`yTaC&%V*}_2j%haGeZdg!+0GZ8&1_q#Df!~7)@y} zSYM&Q-VI0?vCae}0!2W=c$_=HnKOia(L&?|a?ioq@?d^F=*`P6a5*;)Nx^+EhVlAP z1NeX*Cn@$*wnNc;-Bc+PdKvIn87xuY9*e9&G4yUiNC7S~6UISArm+zUMY8m$qe>1? zB}G|5+z{a56x~ULy5K5av4or&glf)2C^$`GfcT*R#CREq%K|>$B;EYH(-?0H-|oiq zj|N%j>XTh|wZ2BqE{UVqUznH!{oJao!5={dIrGs>OK?444SHwsx7~g^n6C?%e^7FE z_-zS5E9TqE=u=;hT>xmD#w%$I_!~33Jz;_!Oo(U1j3>aY#5dHd|68^Ms6kgh?U?a* z=ybGWKUJ~5O=^NylpLo=c}o^2td}T~1bD>k^&_J>;GCsOMN=^lPiz`k z&iT~PJKcx4=)|%vx1-3!)>cN1(e|NM=X5~!Fb(t%XefeklsgLcL&^fQzfc{9i1rI7 zT{@#XgnelDa=R-Kyp?%L{7FB6qjL5X&+}46lM?}g?x4r>hl?bO43#uo8OrR>zB`>b z<(qYaE*b`EVZ@xi$Z5W49qhH6Z@SB!WCK8j3LrS0yF5Bc(*k-adAxVae7tBX{|bjfxMM}l^$DT)QoLK_(^L)Z|;|B>BlIj=7U2<=lvhrH=8t=j#y8EvbUMg6Iq5Jw!>8 zq9nbcNe=-I-GG~Piq}w!aJ&7Z0cBPlOhI4J zRoU7U)SIsAq)0$rSrk+S%p(x27ETEsOa*a-0Xb1_Jq?^DsAo^f>zsz;^{a-(AqL7jS3=$@Q6Vqk48NGh#E!eVj>*y z1AWIRXT9(b*5_x)1Zwob00@u-t z4#_Z}%rZ|X=tK(Y1)dA+qQ_y%n>qu^teQhPFQcon_fSwKs>WdifL>)*ZKFE5gIRTL z1lBW~U6gaJv2-rIbdVe6{64+9xD6DqG$jd#8-Q1zNx{j}V`9g6Plw1c317wtqLPBz zGN2HNU{FTD(F`cH7w7^5$_S!{f)1jfPB`&q>#N3?B^4X8$uAgg=202mrJ!tY0=h|_ z0i8fWnfO)(ashA>jtqbj%?dxyfQl)oECV{2fWES)uG)2K+RYewuOxG||I7Xnjrhsz z%}UBmE;IK&<;Ic0JCoq8VeIn?2n&FuE(X+|ZtE5X)R=(&P@|wlR3l8OgNjUW!cs{? zfgTKGPgf0QKr<*enhdB3S+$hW2ot)h9|NjQG~$`hAaWM8;7$V#O&%gB{!3_c^OKzr8a3W~hI!zxeH`?M@@enwzO- zC|RHRcJ|$#UG0CjN?Z}IwyUk)w*32P^ND14^b`ntT4$%9%WHJ8R_&|p&x)#5-E6*v z?0}v${W&6|^Ox>f;gpEqUp+T>%~SngeWr8NcAUM@F>j<6YRsoyiFx%;{fB(cX#W*= z^8G{i%f@u0%BajtYCJ$B^Ui;7r8DwM#BA2(5eCIo3Gn-UfSO;qNnhmfNZF_Jy3Z&fe9Q zc+^^IFrBg6`YbNPu{&W(VnJ=i^VSQ!Nz1aEc$&j=65pL}J^5ZnZz$U}G4GDctx?NE zD^l%fd@koVD=(;c!zw3a zt|TD{C)l# zTTh5)&#&?aJHyPQ&J$a=%D?r$F?Bjmy2@W|U=3sHAn@I*{K1ycb&aP|#avM3zvjO& zbvmY3<SHxP~zHAHMyBH7(e=`2*}y z#}!Hi{?jHX4fFzhP#ciY1-jbhND;WJl=?PW+u*OQGK*1W_S$kX*+P%w90!QH>9#JQ zo&eMihYT>@=0OPHPpUG5XqL)*9CeONY*>1x|E)@C*NqTC7MVF_N<<;pfAf97*<{9U zQR=QoidyssV4bOTFBu{Hv1ovlESiVCK7selVL);A(6Yvg1+4I#0b!JnA#7Yd%25FK zk=lkF>M}Y(_Os4uF9-!?toZmv7If>_o+EGK;V5!AQT+q|6^n(9fP7H zWSkjB?$Zr~!XvnWjFH<($z0in9kY@z-^ zj>5cw^O!>&O(;jIAN`M!TEd9yiYhaeMFWf+C&p0V0mZ3v0|Z{81TKvbISn2la4{wD zkg~8pCFjxWT~jPnXFd)J+;K`zt90~%ee<2JTS-_TiJ1lO1p5cQ9Q|b9e6O0zXx4hv zeb>Em%#&m1hrF6L)Bo$<7R7;2;8x&x$W(y*xw$h-XC z81?$v=CWjLeR1_)D|I-nj>STKWvs0)t`BLYE}#l>A%YahD8=LHo;=C-sgxMtf@Z`8 zbMk#$Wd_E^lT#vqx~c2%fw6ANZJ?6y0F=$C^qOhV->`%w6RX9rn`1yOlr&{1oE;bt zixow90m@Aa1`x*4FmE_i=)m8i1jbQ!w;jgV17pMKJZGrvL5x9})0|6gln`y6l+=jg zA>>NVr58X4RE?t9wtCU{`t7nJnptT9RkdRS#B88am<^RW38iF1a{WG{(Ue&I6g=&f8}LqWiai^d6`GhaP(5xSGq0Q(I}c+En6W};>;Q}< zGh?~T*d`duVa9GVV{>5a5HrSO# z^at=U^vMH0=pCSIF!ad-KK%iF5jBphZk)OWdc}oGH+yBdf#^fRw24m}e{FBqiTONA zm3t)Eev+m2!w0#ew+vZAloCz{-(0tN$d(ZrDAzI7T4T#3qWZE>UR|-6s($S}yX_~N z@6&Nme+aV4k*NLE_^bBO`7=*6ur4bC8y-h3iicD?_@afOuu7ldM~c`iM+$oJ`4 zs5USCF8tA)%F7;ty@Apb90h^Il2qjv6UgD75U#;B;N{p@YPC#w_YWpN#Wh}fjDX}`2cNXNj$QOz7JRz?+F9OGe8k)<-Y8`kTbn(&Cp75-|$sNP~K$5tYP> zhMFzk24k6?o5+)jH>0$iGPnM>om>FWo+iTwKNFwz$;1f}K^59y7@(3b`adH|iR!7nk$rig#APTk*G~ZQ)ik22GovdIIG-BZU z($!T)rcLig$(wB;5bX7$ba9ATN};EW(ryFCN2=Q&XFfo-<_{l)?5znWM@divM87&p z54S7Y7~7dg=u?9(F|?L?D~b)RGc;ZBhPj#mjc)c-!AXY}_Ydq3WK@Z+&9NHSx+&%6 zswrc^LJ9bQS--IRSCDzeF53q=tVWlM;<75qqVN+@^?EOZ)QAd#e=Eb)Va`!NTWu+I zpbSAX(NXG@^7S-hdueCjA>f`bN4XF1`q(RaO)RfG-ix{i%E^XJ&^5r`=rH|uismB@ zu{W}CoYJ})$xy<9!0DO*QvIcvJEQEP}Ncd{!E@Rrr4tHSI0j$N$4Hn%Hr|o z)O4g>*dIKN&KZ~?)6JO;<8 zskpv<9NE$Z%0db5Fv?WOpW2^QU0YJ3NFv({dIwP{qY_85f(=L&Nbm&k54glSmxaWw z6`Y4b#wX_f{%aM?BMU0v1)@r*s* z(_@ygzP2kg1aoirT#LvE~xghFr2fD`~W^P8gQCd4zbSerE5TYC30ovPwr_2@l-oG z{(QaT{-5nw%l5<07#?qb+vyvBVeNJybJb^#s1 zD6vIp*BN=g!N&$FWY`v)T+JT93f!U`DuZFyj3~ESp};M>naF@Gbv=fneU%7k6(I)% z2v*#zV-N&kvVPF1hp)#mQ^AKqhLC*%aXB4>Y$w_AKhXM#jM`@xv(EcwJ^2U+4i^w*>^P3jYg()*I9Hg$i->PIHRZ zm4zAmN6{WR$55+=x6w(Spp91&2a$4?+F3lPP6s8#K_p*b2+gF359wEM8eDCwIvue= z;vT>pJf}M|UQw7uE*oil+E!4%37q^ql1Wy?=IAO70idOqm3aycPnd4MrPXeZ@qcvUB{>fG@dzK4d+(1mGz5L-aV6{{m|AaM{5 z$V7-}hYj|$Q48d|fPQGeEGMlvl?Y?CpahJ~Z{-ocArR~&IN0PGQ51HQyaM*AQ6)8o z9_KjaqydO{)X>3$&!)|Z{8rL@Bv1flhrVU(7C_cUG>34y0876OQn#R%_KHF&avNZ0 z8p+a`kXC#`W(MM!gUCMFoXT&NAS7W28alBF_(~5E zcNry6Hb3RJ9>c`5GccP*dW6lXk)qL@^mVt^ZG?+~Kj*}ks_k~Q;9np02Z;(+iEs z?%A)Y2n_jE4g^DL8}Ex(mH!L%AD}Gvs<6D+^VCHSYA+w!=!;oCcqykGSW5R&+oNP@ z#5W=mmeuB|3UE}xF44_+4okUzfIV69j=C(6dNZJG`88v~Om-(X-g(t3f1&{Vbs&_L zcD0u@0HFjyXnK_6LW-|fzgRpPir6-UTQ8{Mun7s5D7WvLBvBDHQVsK11|Lt9>?r9P z1L4Z4gm2HyuAzq%MaEdE-xUR<30{I=o>992nlU&>V85>}0t%(jin_cBU59=y_%!x0l-Ome* zE#NgkdTo3#6+bp2 zq|Iw3jT>}u6M-I`z$qL~aprxog!jrwyqA0|LexW&phrzWK#kB_Nw2m-cpHRyLkV$% zDTWA6VGhBtqRAQ-6O+*)y1Z6mSoBMlTgbp2NK`=CmL*z>#R&g{4q|LnEtQ2|NXT}w z?qRYN;!Y*twUL~{LW&emry+VFq)C_#X@r7_yWyiHPRb!h5jJci5g(N8L|V)mMS5fn zT%coKY(j0sNhlnj?-R@Po**Rx_sxbS@*rD$eF~=d3$dlG%Hkv!q7K(EIr@jNc~71x zPAVq`7FIREO9Zq+X^+^9OWAkfAULUzQ80D^q_lRa%M;X^Z;Cgf?RSJIj3$H;SDQpM ziP}8n-{2vqX9L1xx*3NxJz(~Faya{_5xj9{+U`^NJ~R%u`&ZH=0pT*y@qqjJK2M2l zef{ka*ru(7@YM@g?uvvR(*E>@XwaP_oI+Q++xVxCbFjv{u*6AoC_Mh@YB**wXHAva zp+KF1&o#uI>w0Xv) zR7Jam{*rU#?#OaqL8u~cAl6O5W>t8aQ&{s2XA@NR7&))MbdvXF5zuj*Waip#Mu^;= z5cG$J`$6^Z`c`5hGqiaphGDyZ^?+tN9H`wyw8ik2+;d`WN2*r?LVK?yi%sexD>-pe z!&w{<@A#nx?*Lp)A@Q?j635{*5yz-zYynKpN7Y;|8ge(brawLVd@l6=FJ|ejCgdLe z6;!72qwn=@kbrWZyOHzb^b%WBh|53NFL3^*xN(^si8!VN?Os97&5o*)dN}*Boo<i?je*^0Zxs06>_s5pP zNxJ+v>D{O*_4A)3I+{buzrDTk_gJH*T)?|ZS&#tV3N99CCC}S64fw9E@6vCd;_Pto z>)Q`k>X#39SyvOdub-7`2@Ia8tv)0}EvuUx$h+)M;)QRcpTfcg@DKM4*IRUS7N^u- z^ARU)CKIodiRaov&$M3idg+QY87Y<(H#g=Nr#C$xlmY34IIC`|7AtldIs3kxZI$s1 z*pgrH(D=dMyG`GR&UTsopljo&m-j6s4(=e4{?#vI;kHBeox3!QHW}7$`R+dHQXah9 zF+2Uw2GjnRKng5hM)vsntb}P+7f-sBZ3VC3jpp0Vk4xW2SN;3b=D$D5|I&g-{UtdI z=b2pDh67D*SRKd%(zrDQY+@_f=_Z~(xn@6%_(qs zHo40s--KkLpY;vior*%~kRRb_q>5@e|pHA&hO5uZyp7f-3i((xI;iEF?!Gl=iH<^?pM%`^wT@O zL2k0SW&LhQ5LkcRSDJ$TV-rw%-}Z+&_gZ16!mPnRo8ml7FugBsr6fXQOzLCz-V@_r z&H%!Px1?QF@wq8V0$NTitJ8JLEenR-c=~RZR2r%Kdb|fsx0{q4h4pz5bn+(?NoAaF zt#yYo1v=N_Y2=*rWd|BZ?oxYb3_|?Tmy0AgB$H#}7?vxzJxr2gN#6Vv+S6vB=vRrO;&y{uo#Y!67UJZb}4D;dHA44#RNLMUhER zIGp(MbVd{UwisKE2jLjYO7o0c=o=}bad5vYDuMYANVf?@2|)LCxK+GJtq>=7z|*Tf zd}~mp6&8jd))w2>XKtB>hZO{?$Pj*K7+rn3{Hv^B78$_3-AKRu;j}@nW3hRwL>LQV z2NOc2A~B&;_w$+ecf4?GBs%(2!Iyb)I2OMnj4eAR87ibe;k+5}Rt#B<4IL?f{KZh` z!E`lt93DVi+FE3ZWsJ}p;-(D35`YIH{Xvj@#Si4h90Xl%NNaJfwT$Z&OraKj;Shc4 z^jwTeiTKrsU{Jg@{?%2B(qB&Km%#ML4~A?#eg6n@_%LVw{w+fXUsGPtID&RJvfPvUM?^ zY7l%1h^xYl#v88KbYY@2-5T~bJVAD=qy{$-UxjEiVKV;=sPES85)VlKbNnPsY=Ef4 z4~-)-a>E_wT$kXqBu24b!TW`falitniY1BH@w$gkOU%|mmD+?DZM>H0(dw^^E|cbS z^5%JqJ{B1t+#+yCu}|4R^i?0f*o^`coTno{G29$$^AkB4q{=u!A*_EE; znBqJJ`EA1fINudYNvLw^WvB#^+`5w~CVpI7;UAPnwv8`|SMmG{>E`k^07j&{0=J5D zH$J{U0X2|DrmOhvQdF_;gJ|_>DQ+-q14Iy58!E?wquxNW30Eu-%D~7?lMH- zq`puDwIl$miiwe~BweuV@mPA3+l7DIA4499)O}2F84RtcA%<^@gz0H)sktwp`UO$g z_xAgDJST&{h-(gG@bPduhHu&Q^QeuS5)a&N&K}%%KgrR$bRp`hg2M#R50y1Q$ieFh zuZU(1=US1A%_C_M{3h3SCQv95LE;|n9;i(rr--J*Deg^{GFk`m(kK_IUywk|ZeA&T z?t@Z^OoHGAA{2l35vT8qu7o1#$Eze3Vl?Cpuxf&VFu=SS;o267@VK|gGbBa~iDKZ| zHbT)*Rdw~knuLa9IjccS0`rN6anQX9Z(>7{2p<^GA$)kCna>RTZ_Iuv?mlIc--(t( z$Rh(;Untp)!h3}N!Rv0QXgt7s5_okCPjV=0iCHwoM_r%%(G^e;q~Mu1XrVR(86jvdV&1To#^9tf z#v$N`@Z!*K#k`@*eS)P6X%glQUIBD3AyUqwZ}_^xYfy+?49wFvfDI?ZiQ+E=>gXH7 zP<4k?7hayeLF|U#_rcvw%p1n(&_NEh7@$6YEWZ{XqjX$RgX<4u(|~2O7T4TJ)qs5( zFFzGzYeJMo%NdpzT!rP&5!uJ%K5|zTSl*uOEfnb?EeU-h+-+oURq*m^xE%X|?Cnv! zd>H7O2M_BSdnrbb%O?ek2{{w7GyQi9+w!50do5u^m;2Vq^ijz1ORiPux0&vTr=^!#?{%ih+jmECUrGD$eLzk7ISZjxhG zZ|4(86m(jKwu`Job3-1rK5`t-*8)Bph?3wphQqR>suJh)1j=qKyrQ{tL*L)er?1ra z2dI|MKJ=(mAsSbjq=^2T%&`qW6uhqgd0b-iPKD~=ud}7TTJL`O(*d09^CDjz;{JxImGuGVdaA##czAYM9K>IoZ5= zC~P5{Bv+wd>P3dxroJcM4bk>a;hO=kBDt>=(qm&BH9H>74mrPIyREPE`|q3j&UdeG z-FN)ktwUWmV)#w<0v7wXxzvS5S3h{GxkJXM(;PbnO1r{3vTmUfcKu zI_45hv0L+^e$O72unhLUHHP2!bpF#y&_r31*{Qf0svXk)ubX@0&vuQE)^dw~&b7TF zbNSu1@)zFC8=OM7ztm0wiIERb@RyEVke)ln^sM#o>E;iIo`q(_hT8fUCp%>fq*LdC z=UVcjeN?XB+&sXpMp8S&AYJx7`B%nY=OHg|_nlgHE~++qo~=k} zIlpYPxg9FeX9FxrVC601{uMXuk+XLBE1Z5gYK6SLtw=A`tYOiTaA=rAhUBgA$q=Pv zZ(NmktKm!ugpbXiW_(wA4JK<3&qKjd>BA-iP}yjl8Rx#a8Mi$&BjkqJzu*nwZTsh% z+b9+%wz-&uo7UgCvFBTY0xrZEj=(!Qd0B0K=a$^tA+tNQR|Dixs9=Yp<9-n^w0@7)pYwvO={=L`Y4Gl>ryVZ?g)O@ z-8}1%G+uz@5#%!aCi&N%^eRfiHSq+Y``%^W3u8{*ue})JE*%#;yN#TyvRn`u0ebdcBOvq*V=s$j;xak=UEm!ID5xWBG8V4*R_Ci* zX?d;pkJ#60Y|5~fl$a$EHLtUerX**2goov~^R8(QI}ROdNE!#_-265Ba*xkCsS)MY zHqX}aMR3nIR))pki_>n~rM$3Sb?F3r7zIgV4d#aBui5`&X!WUYFQa*q)8mIU2uJk#kJbgstQLP{@nc%h7YqK(U==f?_x?`q0VpxM z@-dTYX`J%TO9lrl{!R*6J1MQ$Oet9JcA3}iM8C?r7iv2<$=7D?cZctEAT^>@(sr!o zQwGy&VzJkTgzxawSGoWb)?6`pi(9k#bshQ!Lx#nYA ztbh-kcXeG5c5hDWCA}Q)=1|=vsn-$Oy;H+l%5L5r)O-xZo8lwn$7U}+XkcAy|0G4C zeMVBsu*#Idt`ir0Xx+a4Sni&moFnZE&@1w4urt(8pP%8kT}~4o?0yi?>S;B$0%ps& z?wV^ZY$=yT2}E>J`K=Q=jZT)U{7Goh4)fAUk}@+p$7{ZyvP&G-ZvNOnl06@9bm<5& zYkRKBrP-rHX9Y$7=-Gz)r=pw)?VJrUeJ7NrpKiBBugI$a&RRV8Cuc6S>1GHcZg2`a zf1$p$D6`5VAVe|lI>$XfstR6rHo^f4TbSQ^v*Y;5a<`VX-eaG2dSa9opt07`+P(Kj zzv8veMX!j=EJp}4e!g86aH7WjMR4>y_d+w74r|PFk7t|0S-s{%P$-MzZ2b1AcS2Z8#-=4l+bxkkG140FPR#GcD+7$V!qZ>X3U_^0C_2{h zC1jg(`vi_qiu)8_=0)(WosGBOU(pD8(PNYn<7hvfZ4FkXaYx(o=J-RudKHiymYLv4 zzRx)E#3?yn{;UaK$}WAc4YSH4{x@ImZe6#VUW@6%`r`9mc&7S+AO zP#TW#R!!t(Oqfz!Yac$P`0Gj$6gmZIYhrSh;o4|P7zqrgNs5zZb{L&5_iRaUD=}m1 z+?-z_*Sr%6G;iYbKQU5t^R=CCK*n!7-y4MzBR0Nuyx;Kg~M7{E;gLtS0io)7>gYC5iLsM3+_I~?stTBqugrn>dUDLee*Zjw4 zBN`uPj=Roy1L{bPy0rWE4g=##u3^K-FtKx<7# zz3y%E{mBw;U=l+V$9FmVJT__G1kEG(c5T6L^|bt&mJ>PW*KRm-qqlNcY|<_y`Z0S|A4p5{#^lL)wE1R9HWVM6daNHn@blrmW!bx46 z6xK094b^-rZtDTtwS3$7`kW!CCJb*mG{Wi4SOtD`a-#4>V?vGfi<%_p(?m7V$(2o@Th> zHmQ*Cf8z$BHeBn%ZF7TLe$7BdQ61BRmFAXemdXb9L+F7ECGi^Y9lDMYqv@gsxy$p$ zy^;-VmOz;FDYa&b|7} z>G9dXOheeTZxU!B6u~Q6wi=_N#A!L9fhiKmk1%KR%xK?0wLXVW{o5M?kJ>#oLYhTk?M73`S~$ zreH{Tsb|VvXl$-2fXlevV>#6)vLLh{gV_Scj zprRXa_&_B>4)+gh)bz!#y}KLo>Yq zi$2VqgwG8g!Gzgp@t$c#z+A)@-dmYNvXIc^#@%s3knW>S4zRVB~hhz8%Azygkrr~?IqJk(xeE*ts=J{(k{(axP z=TQH(N5yVGj3I#Sz;Eqx3nN9)kfX6??ef*(;(n1W5PF5% zaM=exJA$s}-rUxoel#aoFMG88sM*{5pgP4)AXv3|HW0hN zTEPnJski2}zwI9JslTIoDj-xN1I9Z-HG;zS2vdafy<42*CNeGtiA?5L1v-2I>B*^VdyS}^uLpG z;|gv%fN^iaigXiNSyoL*eKyKu-#+!#37UcPRcozoFUeE0AEkO}I5Z7-V!z)N`nJ<_ zl{CyheJm-z;JSOK-?+fXC4pl1PwdJ25Kws?cVs?f2j}3 zdL|t45pMANWp&%mI%6_u40+ov2*S%uTiYuh_8T-_dhNb%X5%x`rt5G5)H+PCFhjx2 zIP0b^KY97~zbd;{W%tAr+sljRgRgLZfWRGOu|>yx?T)%S!`r5zdyc%$4}YN3`#ww(#gn`NyzV3iFWBXK zh13Q482OD{eQ{_lHqO9>K7`ux&_nP(%tvm*MKI_iLF4(ZRc3}xI_9sH3g;|@8(=t) z%ZC0}*GgO8<6242W`}`>9LK@D3gk9NXr~&ld204}A)dMjPu-O7qcuav{LuT4C39pq z=_WmUUlwnr0cw0ip0Ox{L6K}BmS4Yob)a@whT_w}42hkcigQgt+4mnA4s~|ClX4)T z$VbV-7c#oXc18W@nb0SeKV0zbrDkf<5MV&Qq~e`CV)wynQdeNc&bm6&u%f1*mJD}& z->Q|5Q*I|_pBn?8tUmGzZaMBdI2Y1Z;P-7&ew}Hu@2~Fd3e$9q_E#4URWmr|Y|E%!E8Ql}P zFw32nm}cBK{PN`sudAM_z=6S8IyN|`FzcM~g`VyStC^r{&mK0GZBo0vd12lRcw@fd zX+<>5a>28*yr=A{v0uKrai-ri-ZTEa_Ue6)t>HMALXEE!Ff%nS#X0VRua~wmn#(*~N!ndgw_`mVT{ObR~ zW!h1A@%_Xbh1&kBE?`TFy@v_VziVVXQdoO#r6_*z4M_c!%HbPs1lWOu?OD66XI%5W zbnV8W2X#HS<{Z9x??!Rlf)meUwhu=9odh1*z>GfZ{=R#qcJlVR9b@J`7$wwR49sE~rTI@-Qxf7$FcF<8f%ti$F zRhm2&voxF|qy0L(jO&m+xX)3zdA|4CgV>bu;P!3+S_Og#5&QRTaNQ0s+BUM#LdLvu zJsiQ)_-2#`)lgwSaGhwsA=$K9z2?;!pJGROeT0NKESClW$hEu$?_@^t)En1std;$- zT1wit;d4hPlz}TchTBM@w7@DeC+=6prwNhUM%!;_JgiuDtFK~=Az!aKG22{LTRl!U z%Hohb5~yO4Hoyr{se=5?P?g8}FIpFi)k_a%iPyJT9vTKStXV9U8k};7@D9vf4<3xo ziGs!Fvj40ff4fqkBa06%ZQbrXPZ%az1VUlBO{`lXStMLS_( zY^JcEs?Wv8S_8h(dT;|4q$-M=xv%8*r=9{n8r|t_vQ`#sU;;kdd>fFLse4MRDxC3a z6;-0KxF8Clx+XHEG=;MTv2KMS}ASvzo*DMsSxVhME8@(64rGaB< z1Zb{YzFoHSN5zpr`me0#pE$f>4HUUBYXWI_A5sWn&wvS{s>8)d&PU0*A3PbdYr60O zR$~BP8@+%R#f~f!<}3#3lG_7^$6V_*!46}E?Q>;~qXut-RzmvU2oTQWyEcj{riP4z z>k8+@T<1Y(tO=_uX6?Ci=<|Fj{crUTMr;6yEW}M=5GJcb&}(&NADE_|ANzXN4?bKQ^*_>=14qr{ZJDyLf~y;!?sI@Vi@v-4G7_{ILWgpyjpIs3p2x z>;oH|Pd69}fpBMc%zxC?Qf0EaC&KIZCuIi2YW zH+z`kbURHM?!*oGLNLW6h?wBJ5nR3Rh3;Fl`A%@2p1W7qzkey|IyhynY&cvGg?tGl zpMp2n5n>SDuZGt20)RM`lNkv8q2}Oz;ZPU}vr~jGB-!WBW$y@OiEp=gqctBMb(qP4 zHNY-R989U$w~h1Wf;9LIe{X<$$u#Re+kV6SM+%Rp2dg9V zf94^%lE{#aPxx6?Xgmi5%fKYvHFh5Q;bV!n?2k|^h;h9>CTrKkKxxYmAM)prAvwM6 zum7g1&c_)*BH!IubRLWrF3{t5#nzNHf^9Nc|J=LDjNP9U4sf{00AaJb>%>BjX-k%` zzEWr@Q+n>R*hdw*+aW{8O$E-UJj{yOzZOIz%UDkSN2sb(5xo{K2C0H~^p&PRUpY(5?C$iO zdiC^{-)n~$s@>_iIt009!H(i6S};Gzdt=0dl`W6(Ub%Yy0%f)VW+8}HcirNC#4t2- zw~U&JGlW$QI86r8vrK8}6(D7cT9j+OANNQ4DY%L6YRphd|P1`P{9H6 zpc?N?$OHDxy*1}PFg)p>vCo3NjI4w|a25|yGv8PhdjMYBnkR&%ZS2xQ6H?0Y!FB3JHOmYB0ty6)-H%!lpTXn{aeH+Ww~#5?uIu z7V%*4_&$YJLU8InC_eoPOlmFNQ!Ro{ZAm9;(vBqelA3b_qY--&+1 zG{lwzVYry}v-X5&&2hNR>)8J=s4C9_{sq?CX(?y8-}VOIg2cJrgOD^-bZbgpf>b>t zTH$PrUDF3=JU)6>Y{g;4+nT-Z5R5nu{u7fQc%dX0dIY*0k0r0@xeyl!u_av9B-J0_ z{@1_!rj>g{Q+4?4<}TKZ$#?_usFxVPMGHKW~q&ZL-YVY8_IZ zGR7N1H9{_=HqusR?h!hzA01e|_RT1jkp*WaUe4Is7&}~M6&zt-oGQaf1MaOZeV%)L ze#Xgh->r}SJ|o@bEPgqtF_;7H|Bnl2n{qD>zjJdgTsfz~hK3W4I9F ztPU#{?zQ~zcu!p6l07z}`p5mdzDV4_mzNt{IcYvXzk_K%%W+l8hx>86OtZ>@jN^n$ zLhnuP4Sv(_Ab)fv*fI@#3zov0`L24{NjiUC7*!(jZLk?zJs+IZ1C0xoua=p?k*oFn zmG>~b>&=t%|K8B3@JsqCj;#(!Y0Wcm z_TGF}0?l&A_b!@7*N-OCz$~`;kuX6&)Gwbkm`5BTHf9 z=L|0cHGI?)vlg#P$+$h-`>RN~cvn`Lc#r6Oa-69_+V#~~ke;}_lL`KF>BGg#}xl5Ognm_V?9Ey_HZ6>Dny|5Zi$T_XyC{!?Xb{T-Kb}f zd)W2!$c^L_KVDhq(N^iVY0&)XYEy`D<4+8PfnD-kxo+FJ?CjQ{t&0lH96w%2)(x2+ zJax^{43PFLS6~lkQCtnDFPY~8`WcX$9_Hx%$WN4{H<=d~GA3(Z|B5b7OX|OeUY=(m zLx8PC4rr$I^G;Ex*|cE9DK-GzifJrsRm|GAr{YfNq~NKXVL+?n`k}!mjkX^|o*0OKPTWvbNGgXbpae2!F~%Ey=Ofbq0w5Tx5NMywlJYl8_!_eL-{2ljjmSM2-3+qc`}jgqK4#k=pv-7K-c1QN*M z`O9Ix>yR3MrG=gA9-Z3%sP0>i3*WSPk7sS6G7Bz`Rc$yIHbV*m5uTL%r{17h<;Ir& z9(C7~-}bNWGHp@S1a0ZOqPOBAPvEMM*I)Bo-?$LW!!M%YV=VJ>n z5m4_P)D~14lC{3dEIH!yu~Rj_{-{fUzXh8)6|C(-hrqthnC*)@DS zt91hI#x4f#xo6-e6zqpu_afyYW4NpDioCqxeTTWW2JdfltcNttXgDq{aARq0ZwGZ6 z)#R^e{$?-KVeG{LkBn;OiD6C${x~51Pk6xH$dZDqX^6(WPPg1I$ErEKOOLdRAxsh| zg9s}j3CkYkS;3R}nsug{hB8fdnzES&F8jl^!GwMK&h+W~JAcicd+s^UdCob{dCs$1DM>jXZ%crIdqi=2h)zT@mKdKfFgBop zD{kxyegFPPPU~EaNZa{XMWO#D9jrJzrR!N+sc8#XLqhoZpsr~|u12^*x&3g*l9)A9I?#dHlKGa4m zS_Xg|!S0K{C*$aCH@9_DwtoHI{X}Qo3#D5Wl?=X#4Zmluue>lCf|SY*v(RENy$c5_ zxZbm_jtbxMZ|3(2)?47p1BE-+7D(>~TyYnt2k)L;*B3f`&XqC=Ky zmA+u}0dRUd-kSgX{Psuj5Er`2Jt zo9t+<@gKZyV&_h*56EQ*O@O?JbwHDMiNCRM=YphArvqb>BAt>gA)z0GTP_b~QEX!w zk;p8@)cNb1uaG55H6N%*zgE-n5zJH@VW#?lDS{+fFYQWd9?hI+*=29m8Gr~ z>bUcl=}xndygvJb%*fA6fEAaiXAS&Z&oupq#fJSBdn+p_>9`VKi{b@g%DKc< zbsf}3uDnYN?vy-x0_rd^Ou1y)y?p2S+gvRpDeilc$l@DFnOf`OX6e{n(=RBoXK%*h zNE6M}jA%D6nD)AgEJvmucw%MSjIwE~u?N6QO?3Tl(cp?u>mMIF_rQ&77&q zj#-}!HI{+Wr-)|qMz@C)nEY4OW+_D-fL@0E05`}nca4WTW`%`XJ7Jd|_?W{da&9$< zZMpVXHalmrofABdMh1MpTdS$>bg$)_Eq{*&hXq|6CSWF19nN=5^&LaqdMK|ou052? z&8)KinySeTzzmVx>xU^&nh^g|&bZ*)3_mp$mtyPc2(oatTEtIM#P)dl=GD^NQBT90 zKg8}Th|wKr^IV!bunq*8$c!3BWWQLD@O67fgM!aijgJp*Xv0Vl3vmui?+OEJMkJn> z7dGc=EEt-- zu8NN}$9?q!x>>3Gcg`)5qF@6SH48%{A|vWw9iHCRD-%=s<(;^|-|4S)ptH!~!%wzljuntEr*Oc-T#me2bJp9T`Tyn5In$&H3v$dPkr88M)Hc8>F3Umjq?(1Na& z_Y5}=nqOvlhNA5#jf{Ysi8<3f9W5q>QG>ltPPXL7%qwf`#t>i_&t+jNEibw?b6)(A z@C~Yhcfl<&H-oK#eh3UaH38!rj(5YcY>ysF=Su*#HEW>d*gB2uZO(Cj0D;k;r?ixN zN_3s8A{I{v?oGRqlIDQKM#k`6d-taD7xsqB`R;;<&Rx_vRtZvJ&fXs!7E8&Lpg8l3yyEWw%XCWhe|!rdDvf2PPhRV5)YF|j097(3|EC> z^QF}IXIOVCQIsRL9S;mS<+jy3_V^AL;QFcQE4*`#w@k;z#kodALOA|3kHYx)O;exa z@une6i{|JvW0otgD4=ThNW6h=|z9fXAh$|dEmqbbFdSB`t*CF)_TV6L)>UG z3}S-I!TP64-X3n=cld4$^hG4Hr#Uu0<;CxQkzv-ka5rwt6S2X#nE)X}3m`0?1+ACt zBuCfM2aPoj8$uTMK*hEWMAs8SIx2VSnZwsU?)j?H=jq=9X(iDya;IUIsabbTYcq^H z!BXtO{1W*OOfdS(8d_m;u48f*+>JT54k}ijKHy3N@RX?z?^4rM5sRyM_e@#VvOoRw zLqDW^B&!!z5R}4mJyj{U4>jwBM|$Nc?o6_|(B1ihqIM;z5wn23Zj$ zJT*nYn)75-RzKw**)5{NgS1c^YQ^>9H1l~6N|#R!K_#anH3#l3V$_uxEf=~~<&EA~UMMAR5qxa2E_ z%#!v|8h!)6YT%9Nr+h32eG;#R6ibj27hI+3hc0Mx=>R&E>&sWK&$9MxhT`I}3*<0_ zS|Dc}01w#6Z-Z8X{6PdCDP|J3fx5clpZ1 zCexz*H4aa548j0ES$;aOIOVzY>W;~NdY3Ft@luMNN)SEy#%F2Y(lE?3*l9|K#9LW3 z6$Ej?KgagkR3`T7FCg-FqBaHuR_b}!<`AkXdACn3LP2LmO?aI``&v}Hb(_TtxZ-D)@* zKLYmV5WIUeKHjVQMdAJPl_-0MNkhfraxqH>)tRaf+oR?#HiJ~)JeIZ7> zo2sXC9CI;+gLUN|e5)~R{+0;F0Hi+ycQ48%W7P38X~1XQ32V8wV-V;3tem)koEt}h zq5xt${^C*7_zi<~%Nj>>f=<6~+R!2S9v5$lv!3sAal_OV|NLt$8=dek0Fdc)d_VwL zghk++1OQ;rQ62!+LFdaYznXW!?R`OhQOEuhpM9RGz>6@E8)sVm;o^%=D}$1I$ND8Z z!!Z}#XA}4NuKi!Pl{fD6{=aWuWYwkV6ABX4tIdl=a6PJ}Y zx6V2y`(1tK)^boJIZ}xs0+r`48}a~>boSBwK*)^A=x5#2s2dSWpSnORn|1&+@Kl}@{!Gz0}8yobOHlasxf zAFH?E@|^nAi`Ua~E`WJy>n!}ke+a=^P!_8(e^@)*`H4VZgLTRNroog8$QQR1lrCe6 zD^JfC;@jr9NDNbP9$2X%>A%C`*gckU6t@gW<`7&Y4gOjdxD@=^gHLXA8+-VBnp7wk zoF!bC9)QSXy){(Ya?SRVeS1#Crf*pd!Qeb_E_mWrODXL3IcnYXqOoYgKXVCZDEaah zzBC#QV?62dqf_r|Yq*|Wtd`2p`XKoh7g$Q+2sb$ca*koPcP4`=Gnp7h=|4T)T>98= z=NJ~vpLwn$)yhVdAG1vD`*s7;|Czx_kFa%*qgRF&n|Lv4%PgD)QZGZdf zWbZNGN1v;!nu6O$W3>*$VsOP?DCC*>n}t1?<^ID?P7gPV6&BGIX5DR)D*qB!hz2uh zt8F;Z9-9fPy6;|@*r{6;UGbg2-gM&ac63K0Wf+DQE0aofY+VSH`GBR39apgi7EoH31=TR*i%t>{rZgL@2Z zu;YxQLvuy;R{ox)+~A%ofL#B{fr?h=^+xluw_qvb$Y?OcZkh9TRC!!Kt+5`sDe28> z&-q?;!q9&peWfbYAn)s7#B_H?+#Sq|Ix{cdpLW00+1S_`U6pf~58DvjeaJm(OS_B+zd5&gJbFTGyM9_}qG)>?b!_V&Or=5|BVo!xGG8%Qpw`Xpe^iot@8)o!)- z^0G7Ic3B*(7~kFFgA*OChcz;2y04Iu_aZA;6=*8>_>Iy4wa-; zQ5CCtJ0Df(@`g*~2Lr&dvA6w*fr?6~LLfz{ea#TDN*?)S`bhUc*Wq%iQ`@{+ zIX$aWHdnv1{VoI`1ho0Ugp1`wL5Ft02?zU2%iagyummIE4#5G5e@fZPZ5d?iT8gv5 zHd+W7o?$$MJB0)B<#P$fu*T5feIbM|b^ zF60Iw?r9?@#YH*kA;5m{5k|;Wg3B3YdEX4OJC|p=DOm_Z+jK^nnuMdXgt*sO77Y*` z0`HZp{Ghn3`0Q3c`-07%Hl~Yqc?N&|UgnNSChgXck|vb(heZVrJNA3hmxcSIz<%FW z_cKYa?);6pJ)j})t`_0DZAAL0r;Xh#Dgze}O=L91Ig=`w0@=&kuYp_UY4o=)76gpT z(I{z43ks`=YP!ik-1U>9Ji&&uQ_!xbqf|&Z5J6do4q2AsJgC3N!HRtahTrzR26dbW zUT-i5Cf#l8>PUZfC=5$X$ za&Ku%o)4iic16GrXQ1?{ILLx0Cv*a*$vZS`XTU}%duu6l zetKVPR_-VbtihZ~OUqCh=Fq&zw!pTyVc7?Y-9PbQqMqB14lBQZe%-o~IxqEQhoE$= z#hI`74m8~>?7$R5PF~pdVyCeb#bLAg<+J`-r%+!$=0jU(sA~X3ptC0|Xiw{?SATYY zaLWhO=T5`1ART~NY5z|SYSM~r-lI$~-z~Os*-h(Ld|grXwMrQ7ay&L5|NXW>rRLr% zyxY6s{|PBHch>=rt-m*hQ(VR9^}*&@1CoZ^^ltoZ0iz;^Y0_^>onZ@Jzpc)5L}&Q& zepJQ?mb&Mi#84RTeyxmZES|u5^QwjOy#M4lZsuYgv-`uQfpitz+wb))Lnmmt zh{k*2q{Xgh%l9bZt6TTK&R)E1%X_6uwW*vZWH?8lSTdS)2^&g~^$S3b+LL&#e6zC< zW;cv2z@0(UITsG!E114xNA0VVGj8t+`1y95Z}DQwOZ{E3-8m3ABfwcI|98bs=sJm6 z%a2*17vpox4_D8$(|D`l^Uv~=`H2pxFJgWzk00|3GiX@>MbbA7*<-)?b+sR}Po9q+ zd1QW#yhDH?HzTCqm6f|*`?IddDr`L^8ZbAo-}u%-_nD4%Qc^2rEe(VFt-IDRw?X#2 zN@V_w>#=SdK1XVQNK{2YdF2)Cvo4&y^CxtFJ4j`2^O*?6^ypJdQs4G=i5(QrNid~b)rIXZ*kUJVHFh6-rV)# z`mFSdjmBT|&v(bXsn|8?pNG6~_l+(Es?WD*TzvlIel@Z>`sz_s8JPds*)}#`t#@`` z!sTps!|=|hNaN!1O2?sgZ%YLLG^1ZUiVjf;0?8a z6}<9|GJkb9-%|3SxJPF^&SRxMx|z@xR@-ClvadzIEBE-P3gaA`^Pyp(!A%9##*R+o ztew|Cvr3Ss1aN8fwD0XG-~8!w#1|HFWf$LBX5jR;ui#Aui>DodNr?#qYssDbb7MO- zdxvK?i+i*??ELojuFp!>(xutstZ`;hzcBL0|4DD6JbhbS{E8OJy}S5*7NuXaV5b$M zn=YJ#`O77dxlG!s`+jnYXTS0@aSI5XrIDSlNbR#Ykd9VFV9kcdAl#Pbu#19GMyDso z*vXx7^MDY274k}UnkrE|WN#}B`jKWu#mckt)Dbk}>Bqd02*p7Dc6SSYjO z8QB))wRUFksaf619tChEhuw{ll!gm#l_sZaj+|3|08c=8x2JaHK)lWdb=n3B!rrX- zWzHz%U%X{FpHll^l)o7lMrB}#BzuWX7}nddSS3#d3kSC7H@@$nN@|L`LhwCT^8Jy< zfD7Ym!|QM6!*eL7Jzs$`0(;>(+Tsn29t5rUzTnbS?J@F`N~w=eUVf#hvA705Zhs16 z$qV>MRhhlt9?tswnKFt!*p&kt9bNG4P(5Ht2dLjs zQs)Iuzg`L}C_3syptNeNN4?_~pR(QZ$}8JaQ7iE# z)`*o^bb1!Lqyup@7+;L7ZnWlbMF#f@q-cQ`;4n4>99TKikioe&QZe?`?NI)Q&l4FF zul-HoQ(#Yg@#Dy$txey@4d6~~L|6l=1i9CYEPtmcP$wGUVcnd(YEuO|g}vIQFk~wi z8RRDeBHBfayWNW-n2X9EB%Os@ym4jXT<(nE&p zozpgJDx#2()2Wy9v+->_1P3N&6?Z@})W-@IeBQ*$xR?;sdY2Cy!vT=59x8eTSNoJb zfMlLUMfMZls-(*tK@S9f8^(A{hw=r^h(<@|eTJGqI7{xG;IT11DO(aedlM8QG+|T<{u{{x+lIM9*&~5NIWsmZM!%JBsU+49y6Qc1SZtIVUZhTzm zT^pO)8+&Tvpa1LeUMD9?@n)m0Q*!S0K@?Al>})I|-jaITnfLyc%|F;)(%#43qzHE& zZV2!?Hdf*?mXN0H5^a#o_tT}=2*Sc`2b0LY{?Pwe)D8Gy%q60%sn{sPt1f+* z9;dZ8<_FBt4+S|Ph`9@rWKcX6aKmHf!@j{xh2M;{>Ey~q`IH!X6olWZr$%6p1RNKp z!^z6X1ku@${kCP``H1BkcqDuTdo99qfBaD54pIUSE&D?YThmNq?~+i&>`=V&dZ=a& zqTZf(AKw|w|5fxtN%3iqxT*mfmW{PIeT`9Zqp`5qB;2#;@)T(}O#lLuDu(&E&=Bkw8z)wyV5_B~P-gISf^!xV;4I zN=!`?2rM;NnLpn3&_7!~@Qn+z>tGN|Sw03oz{0++jjS!Gnh4qad$XnB8fuTW)DD~P zQMu4ldU^}O>UpXo>ekZ?@AtA)B{#@v+8WVYd98mcmo}WvsW=R~HHwgr{`wF5e%?&D z(;fFqih84yy!aX*8g1KEq$s^<#_8w(`VZ_!73N^x)U?C9e!U52QJa+cS5_Wc9X?$) z`I{>yq2VrhyFMbk$9ivDV6QBNm?M`)w7ZMo8Za?ev1Z#4+ZkKEz$Yevs1LYlW3$6+ z9JN)WJ+U!uXnCA*N#~Yv6^+MQ}-%9rS`887NJSjx(A&ILjJ<-#C<(zYg9?QpGUeq}z2(cLJtFeX` zfsa5$QfapTL;s)$SUiUva(=JB#+xuqYcB%MiQtgSM(l3(EPEtwfv*)m1I&=4$mZIJ zCGToMnKMs@%w*Q)&0(idNz4Z_V&dNF_yeO)$D!6nYQcuS+!Ue)RW2yen) zZD*VVJ8tXccKS}8odL^$Voy2DV--t{@LR3?i(XrLm>E>Q9 zR-w^D(0(BAfFkjbJnNA9h@!jC1fX9afj)H~fYE4uaV;iJl8?^ex zYPIRci5hO<6!ln?`nvz+dMv`)$X$BbBO#7YF5<4aS=}BwIcvuvwO5oQ z=isIx@zqg_;+%pk!`SB*#kbJz6tsKT1npL-@U_;G5sdlV66jO;+|ly-ud*J9*Ad*8 zw_4kr@%)s42Eyex-vYN$qa{`#02(nIEANu=nEy^}|DLh2|rHdedu-zZMgY4SbCN zVIjGC*en^)>;{#Q^}D#azt-Miu7{3tT32{)dt1{xlmvJduxOV@K2%Hm!7+h0QO3Wf zrxvpf-Wz}QKC%I5K|9_EE92=0kEN5Z*W~y&UFR%rJ|D2d`|Z!NPY^WyMjJsxVKtr% zt%f6@*)!vGOH^R?j=_2__-P2hSOYla`v(PW4lg+;1k#SRHP$F1)G-_h+^S z8aal+(P^H%QL8q(IsL2W59|8b9bhBsde(sKD3eNXi}Zo-!;*KAy!=hJVM}U5pAEYY zecxjo(Xp5cwlq8lR$|3Y-!H1>^(EA{ym*x4*@s-~As&!bD1f@@z>uG$cJgsbTvRaV zv&E6{`ZrNZePSSsedlW9_~)WB;;k$9@(&OkWzFbiV^S&ulPG0{D`0Nn)qy8u>5p zN}4+SK)rsbKybP)z8 z3j~lfAOG z_;3Y2r-Q6xj-1gviT#8`o1}RIcQIPSXc)zyA!sPJg?5yXvLu1(0YDbUOOhsgE?_zw zh1-<=0VFL^Wg0Xk8sgDt5K+%bgT5feyg6tPVVntGD~WFQ21ZC!(inga282`}(j-j| zo;4wZ;=adre!=uV2mT-==Lb2R@R~XX2KF*?Zwp{|O+F{#beCZKmth%?XZ98}cNN~i zONi1H=qCYJNd{#cD+Ip+3pBqG&A(=#84li_{o0;`E@@~LunI^}Cpviy>dOLs0)$26 z!BQEI)E;#2gYI3#-7iG>F#R)1)NXETD%uOEQ zq47+@q}gDxgfP9)VbWT#Sab+K466_;TtLRa4_SwK??UYE#^Aj#qwD7l2eg*(bFL%` z3LtYKMzefRlwzANGkT&x_FMq)-ZJ3PW;0U&fHN~$`UC(z9H}jd%pKS#mRY_yjk*XQ zj|SV(U?l?lwGnM7o`;a<-BF6f$^&)`B-U3pJ|D!4=Q7D2D37!TB%KHfiIm3H);1T2 z*Zu@~Ar*_(rZPqhyp`xp2TN&)_;ccDZl(Nk*8m2&ONjXgTxQv`nC9Y%RbdP+CQ{7k zUf{6ddEnXOpm@ZaQ~?1biN*u(1+*Cyx+i9M zc=jRPk45(iO!res_eaq^(IlY66II^uxF|(027IC<<0AfKA$()V`#V?*T!koMp&awv zwF~W?Mtdx#JvuU)2@VEnW-ZZ?(Y!!0iB%82rz4{w9iXB}+`b;hL!wTCfhUtgi1jKfh9>bvkw4xGabUp3RaW|>i330K;eE2NFSup z5^7k|!DMuZ82RcXF&CaGH_#@Yi?;bz@w5ETZ{I&J`z$wg0}iBX9Zkv4VK`-5Qic1> zjJ<7<3wEz(Mj8tf$t9C#f2&n~P?{8x|F(_4bBOI71+ATTJNSlR1Kv8TtW|w^7F;gr zMF$k_H4!o9Ms00suVzPN9~@qu>-c@j%%mGpLIHetNUg!Df?X*%!Z)Y<)ZA;NVRXvo z!oW|(#uq($|S2{KsXWFNVaft*A}E2)DRvt^3S0Ihr1y>44aD%U{{n5B?Ba0p;FXJ8h= z@h5ZX>KVTm2HxvE8_ns_NwJ&8OgoXHd65(QVQA5&K}|M2h;yQEi%^LA49TISRRp_y z$wj06NQcd++LKDP4}W=O-z#mn>oP(`{Qwlf7%mZ)X%1|^^TVJmZ{tpf92b*78*@ZG zKP#qd3IJgCkV~bxp{2h!>-D|Y8S{Db$fWb=g@lGc8LKSV^^&lmGj{YPth!UNRPJ42 zt?;~Viro(}oKMn+ju~FG(Ksnmx%5$o!;a#r-xIG7(dmFJ*D`rK^%0Te&<$FJsrIrPQh(mxwR<+e4!m!fsi@#-AZJtnPY>J&J(+Bb7Q_z0w z?~uKvHD%x=ZS(QbLORbC8a8>S$l(RP4_;I|GP!u#J{_c9ILA;W&9PGEf{E?-5QO3h z>JMP%&IH6HPlX?f^uf4E>=9Q5D<&A&z7u=^sVXO~ibLQ@bkm-}FC8(p?&3uW`P7`b zmKw-%yItFyxCM~WJ(m}8FSg`AGR1>n@l2&gqr>zS@ zdj^?8%}NiT4IaLv>HwU{eC_06NO+6=-NGyh_B$C4c-`QaG_3Co8L%z`#c8uF(|6N- z?PLxL_Ba_1^!LF_>8cxuEe*;LEIfzkCY-JS;L<{70+-+bMO?;Z2#k*`c8|qSX|dGr z#0AwMQP@X&&Pay!VP8O_NXNaHZuE+zQS3|Pfk@CH(}MH~G%38C$W`2_mpq+m^eNM* z01P`KIzrovyssx2l0@V>n#umq&jL|Moj~X?PfN;ts*`0Cavx$&X+aMV{a8*YFltY9 zh$4tyO!AGPjMU-ToqOp2Mw9NGVelv)#IzbTm>(=l18>3{rG(A%ITTbXO9PLr2{c9y zs|wC)!IO!e61^!5Ml^YL6Ce5yX8u!U{v&MPAZ5NIQZfNcN0}8>7${}F#0lCY8c>od zlfcwx%Z@w{-6UeF?h;o88+iEy4D9LdM}S`^RS{Y`5@#LGB+_cKxauBM1*CFxRir|o zt6I)Qs|dBvR2B1v4LH%3AX~UJ4SEN`-N6}M7Tut#O_b{ps zM^$?HcTnQ0U;|)cKOUJ~F{@%Wl6wtRk;Qxf-Kr|n6??Fhxf*0M;1Mv@FPQn~ddYA~ z5SxD=jerDZ@l%fS!dT<>M8pxs{7+|S6Jaj37QZ(eM9Y4wy567N$K)cwR4M8FQ>qvRXVlS>*Lb zh9|Tc#I#Am^x_&&gxfTT$3Zcmdj<Lx5|NSlWYxnb9nYTj{X^ao zN(BBT@+GFd6DJFNi?5wr(5UmcYhHdd~Nm2x$W0ml7fED;QOoEc5Pwc*WV}4 zse}v83L?YZ$2nFF*|1iZ^TgbLA#J+b3mFI&?lC!GMn44k`EmP+Z}+32N8du^n5)a{ z-Tipt!O-;0pMDC<+Y>rRSi=SqwH@Sz#C$n3aENUs^amB$2VN0jXK3Ns4WcurAooIn z;am}xi2mazUfGG&20fV&*F&s({7w2OkB?}ut-O8IGCfk081TP4jjE*);4G$8&ptyM z8#e98NXs|Bbi;Qw{DP3nDU_}XH;AGskPMwSX!|7`V?U#S7 zb%1mW1u5U(!RmR*hYqjonyjQlt1$tpc0KoaS45lN{+u+sqeCHCiBx2_%5X@U*Vo~&}Q=*=x^Vy+^(Wm-q~XL_>|M{ z(e-J1w%gyOtOmxskst&}jRx2GFt#41PonM<~u zdr}+p?OXElp6=3!{GadIA^&h!YP&fCH>Vc}$WMRz^ZZlpn6X0l#8)}LnhrkvJ$>1> z%+!HK(1Mq#T*m2icD&y4s_mPfkrf2t`Bi!0wg*2ot=(hV)Hd77c^eldpLQ|CX}_RH zDg8CwV&SS;{YAsAay`ROt?sgnM!d;AO%ITL#^=p%tfN*x8@krk)DrHPOD|&9SUQJI z4c%C~uyqyB%(VHGM*Haa0EpHC-8^LIiVYD%h6t7&Y<5pH{cW}9QpZ2jjn5YhE9(G1 zueJAgB8&ruLL7)9cR@xpV_P`*vBoR%%_9)ZrNp>}ep48@0uY(yo_qT{`F^?MwSmo% z;K=V>w{h)z=-;4NOtKZD)UO*wI+~ei&i{3!!!PWJ)~|V05r<5onhLG@ilQ~?O6;Zz zh2$a+&MyC3r;;HRzqBi8%=;Un-w<#*jIfNm8r@VVtvE@6uB*I#ppX&Aj{D*q zp#9)O_jDjgiK)zjUpET7WIV4}{!4_Z$&S9*%_D!AgdZh>j|TY`=-EigAMs03G<z7v4ZC=O5q(fX+syY!Un!KYg2#@oV??+udYLAzxGp^2|&aSC0X+S6ZT(f)H*M{0q!N*Kf^8CsA6 zlTw($vU>btO8d^S+C31Xcn*XxoczyyC)Ja5r~7Hg z?~Upsju>>AvpSZWzjA(ztz1F%4KI5UE_sVqKr%d(`Qq)HP&SMjAQ-iA^AL`iszGA& z(M9uuyL5;`qV9#>a$oyl^f`>4U-cxjZJ?3O*p#=?Amv~aQ+jQc_0_%ndhW96|JtZO)?WniYQ?^PET+eQqGQ6* ztt*_3k>@zvj!BRIU$b_OBLyEs-J5db_PwXW=rJ|Nf0xN=?zpEm3ZwA!!Gfzn=nxck z^|5}O@}{Z@{{y*j_#!7B|Ep&J9q?4lcI zUzJA_>q-d3g(dlw^q-XGQnrn6__$|BS7CI!6zJ42c$2L}R^jx$ZBG{s9hX4bIc)@Y zdQx;wvjcaAo}L|pZetH(X>FcD|Ibxpg{5~domAmNLfn~bUoHMS!;egmg_KXbEd9xd zat7&z)2p3$3D)UFo^*ZOZs}&~<%Bh#tNHg^kMaR)6#XJAnt zEW#qmKmEPPML{=TP^rr+xOw8matqS9 z7A|}L-Fm?gl$N);yz+nbNb713+hLS}Qs|s5FHE28?LX!aQ05X#Y%&fGVn!S8C6(0F zGoG}w`iL(y11MWHSV;?Z5?r~Q+T8QA<{|@NXSa>(zCk-w@_Id54m7c65(6VrAQ`QC ztl_GpA4QVOp)@Q!vb8^Nh`+@k`jH5LdHskI?gA3-kwTKixa6iH{#PzTbS&2;aQmu0 zNx5*L7`vCfkgip@7}`OXEG4oE6`8I+W8k^-hH?{E?NvVVg+XbC0YrZzYiGb-gp{D` zeo{TdQU|dwD(Yoj=p0Y~*|35%mC#bxu{IYWXizLGh)TLP=p_W;jlb7Yb6UMj+)A%8 z^Oq6rrz@}+=8AmNoL0w3Q>OFESJ|vzHBaGEX^`9sJ?^Fi1~0xuk}783s8}NRe8SwW zD9zK?q(T&iw#@ABslc#zRP3v4RbkRvH>pD67)XldT{YIP=h<{Z2>K77M zj~&DMDEJ{ocpdt$5?c>d;VOF&#GN;h7l^s+Lp=M^jUCen9d-lw61rmSNf6UR+WoUf z6ZJ0r7drr?v{kz&PWgeGn-WyI%rvd|WW|e&a1eb^eh{s}LTG$(?QFune)i-;m6IH) z?B2T#DW=6E_413A7g;E-VY7IXCH>{i1o75`z@EKWJaV3#oip#Ckn)pYdyT>v0fe{$ zvET!43HmH62yJgM_apdz9U4k1xJ(p}R=?~rQ{hhwhv^nvNJw*1^j8k0D_r=~!a7yD zg$d#cmu+2{3X&E!dJUs1NMN`;_g}igT}ca{yhf1`?oqlzn506Z8V!SBn54p@mvn_I zlDWw`pd^HNd=4Y5fe6=i78}Bc!fXlZgI~*tAYb<-)+D6F58F79d=X?IZc_8A0k6M` zy5}nK{1vJ%l_g(TN}BANd5i8-Njz?8<$INLkt)Ck?QFNqX?!Xi9**Oj1FUlCkTebO_|W zB-aC7Ms2jFD=>20!rxn3>kfZdew|X7e*N~)ZPJxFCDam`^V-UJ)1s9(%f5d>9blih zJLVKCmUW7?G=W-u?e5invnN@%RTgvj%`L5|w)d0F{Q5#eDDGG}p)`6H3xh}ki(eLy z$cqJOl&6eT53a{N6UkWS$cP}qVULr5t|BjV2BZy=XQYWmpwL}B$+Lot2q8k*#0!}e zwyso%!P?$GIce18n90iEBh#FzCBw5IjSVG9_myq*Ltvu`V7gA zH!^00*+XDXk}1>hpnosq4%U-A%dxD0uSx_JrQa(@ag(E?6z?$-eemtG*?edyk{JO# zMak&!yrH46k-)QiuwWq21OH*>^Ha#t5~Wxx-VoGoRl&f)FVDJ3u+>jS^uV4YJR+{{ zBF_qw(l+Oa1qIaQD6X}Nih4XFB0~mI=JtFik zhqz;qVQ95@^Ag4F9>`?H@_&lAP%5M!s!M?P!Pwqclbmn}dKXI$Dc)GAkPG&l65?t{itrHE9lDjwKcDOHmO)G_*7H%s6>yYhN|9L4 z2kUcr;bA0y@sSLsNk+6kO1PC#MWH=b-ZX9VFA|^JhGcFX6e|Iebq0B2oxX~?yX0_b zlV;_?c*Ih2q%{na3W2>y7curCrSP1LND;wfiC-W6d|XE46eW}_lQv6M-dJsOb;&vi zI?AmZp^`)#bC%#j2Bii9C3yez{>MlMjvCM^`=d0dLBqeUkDg&H`v)N6W5I5Hl(=}2~X!HDyRFb6X(&IW} zWEt*~EiYy6pz?A&$t6b$PmYyz4&rFge)^eoqK`(Qy``T^=CZw!BB~$GX}Wlg=Ay~d_2W|HRt*aX2Tll*`=|TS^Vye>V)sw?irT!zkkI|T?d`x)>5{@!q~Kz`<5;Cssp_iFtG{&5+O?O)g16fJ2e}NBOsnhbm zz~4ERrwZ-KA8#*XK|oZ1}r(Xd2@G?p>di)c9BLQ_;KQ z-=C`pHjv&C6=$`8UJI1pj4EH#BgZaYi|Z&qQMO}lbB*KiC-vS3U*CGi+{RulU|$-j zZGO5I`DFLIG52HY@`;Hx&AUI>Jo$o@;ZI|kW%&u$wm~XM&+F3SI+PGFnG_epWp~Qe zEAAezs$YNb^))SKLBA@NHLtx9?X*5lR$NVwm1KYfP&f0Q{(8U_H}_#cU{0fXpvm2N zSj1-=U zsoB|wPB^3@-vLjn7?Y+IKCyNH!^`mQDMuc%26;#?(!?Zd963?;roY|t{5VHtx z9$kroF>xDIRp2F<=OF}trSi!)+)I(`ykh(XfB*M#1xhwgnb(^7ql9fz3Bp4UhccUy z4Xed3YUTxSjh{U4!gIrbK)O|Kp_6IC;f`HnF&E-_9bI+5wJ64reoe_emNg&!MAtkt zQ!I~Eh9(OJ2~|a>S2Lr3sKYCoW6ufr(*vZUQFw;ppKd}1&n5O8;zcQWwv&}moL3I) z$oUd-bQv)dMnnrO-yc59bdIL&*8izGlO6eobVNC`BW)$$MJ-@Q?zZP7!UqS14Mz$! z-IT!AO|49aR21}7umEA&RE7(KDjl{T&zdky($z@`Y|iOq21D5c+J}D{MwgVm=sH#j z{jnSx(zF+C-q{?+G)65<@--b5DZPteZ}q(Hn!7i>vzI4{teKvE zA8137qp6a&B0u5}x1=~TTDTzRtE5SAo64u6>PAbZc^96c-8hu+ZW03{fdU$<1$RD4 zK6wc>mORu-Fr^@cES)9x_UUh$s@8nJ(5c0AZLi0(TW2qtu<8dR38%Ot<%BL;DtQwE zuWw<-M^^U9!7o#{O-mfYe1tXTVyu!kKqEwh`GY+fn!v=UF>f#Z-S#V}w`8M)tN+(_ zJhV7+DprXJRcm(C_A-l;+6dL2oxRA#;7@CQL<1T%=0O2*dLV^|ytGs2*q?c|YHqV# zaVtYcTqd*BM~+KzZd`MUnPVjU6r5eH9kT5Vh{aOxR)#nT5U^&XUdphnyqsSt#{-$& z>I3^Gb>)`_gPJ}C&^>T-pf!?Lu}Uq#w>yejnV}2z9e=U@!}+sgKmYf0>V=z!^O{P- z)T&#P3pO=~yUg*HRySX(8n)z2Sf?0Pxb$-7*lRor2-xy}{+nxW^Rzag;~y~_=Yw^v zuKH4G`*h#rde^QmG#I!su_KXcE3}(r{2=A#XRoZP8Sa`4g$2DlyutG6bTL0O5+P=6 zmK!!{ES}rC;J^N7c6Nwi2$M2zJNSKj_|Zi@x1ZGXZpvOBCfCNiqr9N9k0I0{a$@ao zA;&hb=uP)ht~axcc-(r05kb#=Z{#c(pEu^ZVe5+pbDI%nh=xUYa1f_q7I1-S$lT*6 z`ue6j5;HlXVFmq~(uavfKqgJfB9N54O8BrZE35!ZVp?GqQ^SbGQm=d#VrEmldBY_n z#WuN{pp{rJ8w4|2QglHs`mZo-+7fwK6tTqoe!{z)AD=1WO@qRwq|CRTXf-XnUGEsN z^#0V_%Wg%e(aIx=>VjSIp*3BzdvaG#{AF3WNZb@X2Nb=PVugy4_f4F&= z>SGZfNvpq}X-!~Wl045P8!P8W^wxS@=j9J-tai!Ii~kh@oNddbd!}>D9&iK77SFAo z{QdWDn^DQ{UJT@KpYrp!`NMC1I=|nCGRhzLUWlmz#S3*SIL$zg+me{hP+MWD#k9!_ zg*i3zliOdsM=7dy-k+bAFdAdt3*BMf#Qba^rdo7icM=;trYOmXc{eI2?$6I432mhW dc_$Y2XtZrnnLGW;LpJ%uah8+)bz9Hf{}1l5mbCx? literal 0 HcmV?d00001 From c2811844264473e18ff9c83c61a40cc50a15309e Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 16 Mar 2023 11:47:56 -0700 Subject: [PATCH 52/77] [Geneva Metrics Exporter] - Add support for abstract socket (#264) --- exporters/geneva/CMakeLists.txt | 10 +- exporters/geneva/example/stress_test_linux.cc | 597 ++++++++++++++++++ .../geneva/metrics/connection_string_parser.h | 28 +- .../exporters/geneva/metrics/socket_tools.h | 14 +- exporters/geneva/src/exporter.cc | 2 +- .../src/unix_domain_socket_data_transport.cc | 3 +- .../geneva/test/metrics_exporter_test.cc | 16 +- 7 files changed, 650 insertions(+), 20 deletions(-) create mode 100644 exporters/geneva/example/stress_test_linux.cc diff --git a/exporters/geneva/CMakeLists.txt b/exporters/geneva/CMakeLists.txt index b3d6a32b4..c3167e99b 100644 --- a/exporters/geneva/CMakeLists.txt +++ b/exporters/geneva/CMakeLists.txt @@ -95,8 +95,16 @@ if(BUILD_EXAMPLE) add_executable(example_metrics example/example_metrics.cc example/foo_library.cc) target_link_libraries(example_metrics opentelemetry_exporter_geneva_metrics) + + add_executable(stress_test_linux example/stress_test_linux.cc) + find_package(Boost QUIET) + if(Boost_FOUND) + include_directories(${Boost_INCLUDE_DIRS}) + target_compile_definitions(stress_test_linux PRIVATE HAVE_BOOST) + endif() + target_link_libraries(stress_test_linux opentelemetry_exporter_geneva_metrics) endif() if(MAIN_PROJECT AND BUILD_PACKAGE) include(cmake/package.cmake) include(CPack) -endif() \ No newline at end of file +endif() diff --git a/exporters/geneva/example/stress_test_linux.cc b/exporters/geneva/example/stress_test_linux.cc new file mode 100644 index 000000000..462667d13 --- /dev/null +++ b/exporters/geneva/example/stress_test_linux.cc @@ -0,0 +1,597 @@ +#include "opentelemetry/exporters/geneva/metrics/exporter.h" +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +#include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h" +#include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_provider.h" +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace metrics_sdk = opentelemetry::sdk::metrics; +namespace nostd = opentelemetry::nostd; +namespace common = opentelemetry::common; +namespace geneva_exporter = opentelemetry::exporter::geneva::metrics; +namespace metrics_api = opentelemetry::metrics; + + +namespace { + + void initMetrics(std::string account_name, std::string ns, std::string socket_path, bool is_uds, uint64_t metrics_collection_time_secs) + { + + std::cout << " Init metrics : " < exporter{ + new geneva_exporter::Exporter(options)}; + + std::string version{"1.2.0"}; + std::string schema{"https://opentelemetry.io/schemas/1.2.0"}; + + metrics_sdk::PeriodicExportingMetricReaderOptions reader_options; + reader_options.export_interval_millis = std::chrono::milliseconds(metrics_collection_time_secs *1000); + reader_options.export_timeout_millis = std::chrono::milliseconds(500); + std::unique_ptr reader{ + new metrics_sdk::PeriodicExportingMetricReader(std::move(exporter), + reader_options)}; + auto provider = std::shared_ptr( + new metrics_sdk::MeterProvider()); + auto p = std::static_pointer_cast(provider); + p->AddMetricReader(std::move(reader)); + metrics_api::Provider::SetMeterProvider(provider); +} + +static void ReadProcSelfFileForKey(std::string file_name, std::string key, long &value) { + std::string ret; + std::ifstream self_status(file_name, std::ifstream::in); + std::string line; + bool found = false; + while (std::getline(self_status, line)) + { + std::istringstream is_line(line); + std::string field0; + if(std::getline(is_line, field0, ':')) + { + if (field0 == key) + { + std::string value_str; + if(std::getline(is_line, value_str)) + { + value_str.erase(std::remove_if(value_str.begin(), value_str.end(), + []( auto const& c ) -> bool { return not std::isdigit(c); } ), value_str.end()); + value = std::stol(value_str); + found = true; + } + } + } + } + value = found ? value : -1; + self_status.close(); +} + +static void ReadNetworkIOStats(long &total_read_bytes, long &total_write_bytes) { + std::string ret; + const unsigned initial_headers_idx = 2; // to be ignored + const unsigned read_idx = 1; // column number containing received bytes + const unsigned write_idx = 9; // column number containing sent bytes + const std::string loop_back_interface = "lo:"; + unsigned line_idx = 0; + std::ifstream self_status("/proc/self/net/dev", std::ifstream::in); + std::string line; + while (std::getline(self_status, line)) + { + if (line_idx++ < initial_headers_idx) { + continue; + } + std::stringstream lineStream(line); + std::string value; + size_t count = 0; + while ( lineStream >> value){ + if (count > write_idx){ + break; + } + if (count == 0 && value == loop_back_interface){ + break; + } + if (count == read_idx){ + total_read_bytes += std::stol(value); + } + if (count == write_idx){ + total_write_bytes += std::stol(value); + } + count++; + } + } +} + +#ifndef HAVE_BOOST +std::string generate_uuid() { + std::stringstream ss; + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, 255); + for(auto i = 0; i < 16; i++) { + auto rc = static_cast(dis(gen)); + std::stringstream hexstream; + hexstream << std::hex << int(rc); + auto hex = hexstream.str(); + ss << (hex.length() < 2 ? '0' + hex : hex); + if (i == 3 || i == 5 || i == 7 || i == 9) { + ss << "-"; + } + } + return ss.str(); +} +#endif + +void GetProcessCpuTime(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + static long clock_ticks_per_sec_ = sysconf(_SC_CLK_TCK); + struct tms current_cpu_time; + times(¤t_cpu_time); + long cpu_time = (current_cpu_time.tms_utime + current_cpu_time.tms_stime)/clock_ticks_per_sec_; + nostd::get>>(observer_result)->Observe(cpu_time); +} + +void GetProcessMemoryUsage(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + long rss_bytes = 0; + ReadProcSelfFileForKey("/proc/self/status", "VmRSS", rss_bytes); + if (rss_bytes >= 0) { + rss_bytes = rss_bytes * 1024 ; //bytes + nostd::get>>(observer_result)->Observe(rss_bytes); + } +} + +void GetProcessMemoryVirtual(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + long vm_bytes = 0; + ReadProcSelfFileForKey("/proc/self/status", "VmSize", vm_bytes); + if (vm_bytes >= 0) { + vm_bytes = vm_bytes * 1024 ; //bytes + nostd::get>>(observer_result)->Observe(vm_bytes); + } +} + +void GetProcessDiskIO(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + long read_bytes = 0, write_bytes = 0; + ReadProcSelfFileForKey("/proc/self/io", "read_bytes", read_bytes); + if (read_bytes >= 0 ){ + nostd::get>>(observer_result)->Observe(read_bytes, {{"direction", "read"}}); + } + ReadProcSelfFileForKey("/proc/self/io", "write_bytes", write_bytes); + if (write_bytes >= 0 ){ + nostd::get>>(observer_result)->Observe(write_bytes, {{"direction", "write"}}); + } +} + +void GetProcessNetworkIO(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + long read_bytes = 0, write_bytes = 0; + ReadNetworkIOStats(read_bytes, write_bytes); + if (read_bytes > 0 ) { + nostd::get>>(observer_result)->Observe(read_bytes, {{"direction", "receive"}}); + } + if (write_bytes > 0){ + nostd::get>>(observer_result)->Observe(write_bytes, {{"direction", "transmit"}}); + } +} + +void GetProcessThreads(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + long threads_count = 0; + ReadProcSelfFileForKey("/proc/self/status", "Threads", threads_count); + if (threads_count > 0){ + opentelemetry::nostd::get>>(observer_result)->Observe(threads_count); + } +} + +void GetProcessOpenFileDescriptors(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + std::string path = "/proc/self/fd/"; + auto dir = opendir(path.data()); + size_t count_fds = 0; + while (auto f = readdir(dir)) { + if (!f->d_name || f->d_name[0] == '.') + { + continue ; //Skip everything that starts with a dot + } + count_fds ++; + } + closedir(dir); + opentelemetry::nostd::get>>(observer_result)->Observe(count_fds); +} + +void GetProcessHeapMemory(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + struct mallinfo m = mallinfo(); + long used = m.uordblks + m.hblkhd ; + opentelemetry::nostd::get>>(observer_result)->Observe(used, {{"type", "memory_usage_mallinfo"}}); +} + +void GetProcessContextSwitches(opentelemetry::metrics::ObserverResult observer_result, void * /*state*/) +{ + long voluntary_ctxt_switches = 0; + long nonvoluntary_ctxt_switches = 0; + ReadProcSelfFileForKey("/proc/self/status", "voluntary_ctxt_switches", voluntary_ctxt_switches); + ReadProcSelfFileForKey("/proc/self/status", "nonvoluntary_ctxt_switches", nonvoluntary_ctxt_switches); + auto total_ctxt_switches = voluntary_ctxt_switches + nonvoluntary_ctxt_switches; + opentelemetry::nostd::get>>(observer_result)->Observe(voluntary_ctxt_switches, {{"type", "voluntary_ctxt_switches"}}); + opentelemetry::nostd::get>>(observer_result)->Observe(nonvoluntary_ctxt_switches, {{"type", "nonvoluntary_ctxt_switches"}}); +} + +void create_process_cpu_time_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr cpu_time_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0", "schema"); + cpu_time_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.cpu.time", "des", "unit"); + cpu_time_obserable_gauge_->AddCallback(GetProcessCpuTime, nullptr); +} + +void create_process_memory_usage_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr memory_usage_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + memory_usage_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.memory.physical", "des", "unit"); + memory_usage_obserable_gauge_->AddCallback(GetProcessMemoryUsage, nullptr); +} + +void create_process_memory_virtual_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr memory_virtual_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + memory_virtual_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.memory.virtual", "des", "unit"); + memory_virtual_obserable_gauge_->AddCallback(GetProcessMemoryVirtual, nullptr); +} + +void create_process_heap_memory_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr memory_heap_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + memory_heap_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.memory.heap", "des", "unit"); + memory_heap_obserable_gauge_->AddCallback(GetProcessHeapMemory, nullptr); +} + +void create_process_disk_io_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr disk_io_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + disk_io_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.disk.io", "des", "unit"); + disk_io_obserable_gauge_->AddCallback(GetProcessDiskIO, nullptr); +} + +void create_process_network_io_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr network_io_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + network_io_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.network.io", "des", "unit"); + network_io_obserable_gauge_->AddCallback(GetProcessNetworkIO, nullptr); +} + +void create_process_threads_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr threads_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + threads_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.threads", "des", "unit"); + threads_obserable_gauge_->AddCallback(GetProcessThreads, nullptr); +} + +void create_process_open_files_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr open_files_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + open_files_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.open.files", "des", "unit"); + open_files_obserable_gauge_->AddCallback(GetProcessOpenFileDescriptors, nullptr); +} + +void create_process_context_switches_observable_gauge() +{ + static opentelemetry::nostd::shared_ptr context_switches_obserable_gauge_; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + context_switches_obserable_gauge_ = meter->CreateInt64ObservableGauge("process.context.switches", "des", "unit"); + context_switches_obserable_gauge_->AddCallback(GetProcessContextSwitches, nullptr); +} + +void start_stress_test_counter(size_t dimension_count, size_t dimension_cardinality, size_t delay_between_measurements_secs, size_t number_of_threads, size_t number_of_measurements, std::vector &measurementThreads) +{ + measurementThreads.resize(0); +#ifdef HAVE_BOOST + std::vector dimension_values; +#else + std::vector dimension_values; +#endif + dimension_values.reserve(dimension_cardinality); + for (int val_idx = 0 ; val_idx < dimension_cardinality ; ++val_idx){ +#ifdef HAVE_BOOST + dimension_values.emplace_back(boost::uuids::random_generator()()); +#else + dimension_values.emplace_back(generate_uuid()); +#endif + } + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + static std::vector>> instrument_vector; + instrument_vector.reserve(number_of_measurements); + for (size_t measurement_idx = 0 ; measurement_idx < number_of_measurements ; ++measurement_idx){ + std::string counter_name = "counter" + std::to_string(measurement_idx + 1); + instrument_vector.emplace_back(meter->CreateDoubleCounter(counter_name, counter_name + "_description", counter_name + "_unit")); + } + for (int i = 0; i < number_of_threads; i++){ + measurementThreads.push_back(std::thread( [i , dimension_count, dimension_cardinality, delay_between_measurements_secs, number_of_measurements, dimension_values]() { + while(true) + { + for (size_t measurement_idx = 0 ; measurement_idx < number_of_measurements ; ++measurement_idx){ + std::map properties; + for (int j = 0 ; j < dimension_count ; j++){ + std::string key = "dimension" + std::to_string(j); + size_t rand_val = rand() % dimension_cardinality; +#ifdef HAVE_BOOST + properties[key] = boost::uuids::to_string(dimension_values[rand_val]); +#else + properties[key] = dimension_values[rand_val]; +#endif + } + int value = rand() % 10 + 1; + auto labelkv = opentelemetry::common::KeyValueIterableView{properties}; + instrument_vector[measurement_idx]->Add(value, labelkv); + } + std::this_thread::sleep_for(std::chrono::seconds(delay_between_measurements_secs)); + + } + })); + } +} + +void start_stress_test_histogram(size_t dimension_count, size_t dimension_cardinality, size_t delay_between_measurements_secs, size_t number_of_threads, size_t number_of_measurements, std::vector &measurementThreads) +{ + measurementThreads.resize(0); +#ifdef HAVE_BOOST + std::vector dimension_values; +#else + std::vector dimension_values; +#endif + dimension_values.reserve(dimension_cardinality); + for (int val_idx = 0 ; val_idx < dimension_cardinality ; ++val_idx){ +#ifdef HAVE_BOOST + dimension_values.emplace_back(boost::uuids::random_generator()()); +#else + dimension_values.emplace_back(generate_uuid()); +#endif + } + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = provider->GetMeter("process.metrics", "1.2.0"); + static std::vector>> instrument_vector; + instrument_vector.reserve(number_of_measurements); + for (size_t measurement_idx = 0 ; measurement_idx < number_of_measurements ; ++measurement_idx){ + std::string histogram_name = "histogram" + std::to_string(measurement_idx + 1); + instrument_vector.emplace_back(meter->CreateDoubleHistogram(histogram_name, histogram_name + "_description", histogram_name + "_unit")); + } + for (int i = 0; i < number_of_threads; i++){ + measurementThreads.push_back(std::thread( [i , dimension_count, dimension_cardinality, delay_between_measurements_secs, number_of_measurements, dimension_values]() { + while(true) + { + for (size_t measurement_idx = 0 ; measurement_idx < number_of_measurements ; ++measurement_idx){ + std::map properties; + for (int j = 0 ; j < dimension_count ; j++){ + std::string key = "dimension" + std::to_string(j); + size_t rand_val = rand() % dimension_cardinality; +#ifdef HAVE_BOOST + properties[key] = boost::uuids::to_string(dimension_values[rand_val]); +#else + properties[key] = dimension_values[rand_val]; +#endif + } + int value = rand() % 10 + 1; + auto labelkv = opentelemetry::common::KeyValueIterableView{properties}; + auto context = opentelemetry::context::Context{}; + instrument_vector[measurement_idx]->Record(value, labelkv, context); + } + std::this_thread::sleep_for(std::chrono::seconds(delay_between_measurements_secs)); + + } + })); + } +} +} + +int main(int argc, char **argv) +{ + std::vector args(argv + 1, argv + argc); + std::string example_type; + if (args.size() == 0 || args[0] == "--help") { + std::cout << "Options -- \n" ; + std::cout << "\t --geneva_account_name [default=test_account] --geneva_namespace [default=test_ns]\n"; + std::cout << "\t --socket_type [uds|abstract, default=uds] --socket_path [path default=/tmp/geneva.socket]\n"; + std::cout << "\t --metrics_collection_time_secs [default=60]\n"; + std::cout << "\t --process.cpu.time --process.cpu.utilization --process.memory.physical --process.memory.virtual --process.memory.heap\n" ; + std::cout << "\t --process.disk.io --process.network.io --process.threads --process.open.files --process.context.switches --stress.test\n"; + std::cout << "\t --dimension_count [default=3] --dimension_cardinality [default=5] --delay_between_measurements_secs [default=0]\n"; // relevant options for stress test + std::cout << "\t --measurement_type [counter|histogram default=counter] --number_of_threads [default=1] --number_of_measurements [default=1]\n"; // relevant options for stress test + std::cout << "\n"; + exit(1); + } + + // read initial config options + size_t index = 0; + std::string account_name = "test_account"; + std::string geneva_ns = "test_ns"; + std::string socket_path = "/tmp/geneva.socket"; + bool is_uds = true; + bool is_stress_test = false; + uint64_t collection_ts = 60; + while (index < args.size()) + { + if (args[index] == "--geneva_account_name") + { + account_name = args[++index]; + } + else if (args[index] == "--geneva_namespace") + { + geneva_ns = args[++index]; + } + else if (args[index] == "--socket_type") + { + if (args[++index] == "abstract"){ + is_uds = false; + } + } + else if (args[index] == "--socket_path") + { + socket_path = args[++index]; + } + else if (args[index] == "--metrics_collection_time_secs") + { + collection_ts = atoi(args[++index].c_str()); + } + else if (args[index] == "--stress.test") + { + is_stress_test = true; + } + index++; + } + + // read measurement_type, dimension_count, dimension_cardinality, delay_between_measurements_secs + size_t dimension_count = 3; + size_t dimension_cardinality = 5; + size_t delay_between_measurements_secs = 0; + size_t number_of_threads = 1; + size_t number_of_measurements = 1; + std::string measurement_type = "counter"; + + if (is_stress_test) + { + index = 0; + while(index < args.size()) + { + if(args[index] == "--dimension_count") + { + dimension_count = atoi(args[++index].c_str()); + } + else if (args[index] == "--dimension_cardinality") + { + dimension_cardinality = atoi(args[++index].c_str()); + } + else if (args[index] == "--measurement_type") + { + measurement_type = args[++index]; + } + else if (args[index] == "--delay_between_measurements_secs") + { + delay_between_measurements_secs = atoi(args[++index].c_str()); + } + else if (args[index] == "--number_of_threads") + { + number_of_threads = atoi(args[++index].c_str()); + } + else if (args[index] == "--number_of_measurements") + { + number_of_measurements = atoi(args[++index].c_str()); + } + index++; + } + } + + initMetrics(account_name, geneva_ns, socket_path, is_uds, collection_ts); + + + // read rest of the arguments. + for (auto &arg: args) { + if (arg == "--process.cpu.time") { + create_process_cpu_time_observable_gauge(); + } + else if (arg == "--process.memory.physical") + { + create_process_memory_usage_observable_gauge(); + } + else if (arg == "--process.memory.virtual") + { + create_process_memory_virtual_observable_gauge(); + } + else if (arg == "--process.memory.heap") + { + create_process_heap_memory_observable_gauge(); + } + else if (arg == "--process.disk.io") + { + create_process_disk_io_observable_gauge(); + } + else if (arg == "--process.network.io") + { + create_process_network_io_observable_gauge(); + } + else if (arg == "--process.threads") + { + create_process_threads_observable_gauge(); + } + else if(arg == "--process.open.files") + { + create_process_open_files_observable_gauge(); + } + else if (arg == "--process.context.switches") + { + create_process_context_switches_observable_gauge(); + } + } + + std::vector measurementThreads; + + if (is_stress_test) + { + if (measurement_type == "counter") + { + start_stress_test_counter(dimension_count, dimension_cardinality, delay_between_measurements_secs, number_of_threads, number_of_measurements, measurementThreads); + } + else if (measurement_type == "histogram") + { + start_stress_test_histogram(dimension_count, dimension_cardinality, delay_between_measurements_secs, number_of_threads, number_of_measurements, measurementThreads); + } + } + + while(true) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + for (auto &thread: measurementThreads){ + thread.join(); + } +} \ No newline at end of file diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h index 39fff58ae..3fae8c8e9 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/connection_string_parser.h @@ -5,7 +5,6 @@ #include "opentelemetry/exporters/geneva/metrics/macros.h" #include "opentelemetry/exporters/geneva/metrics/socket_tools.h" -#include "opentelemetry/ext/http/common/url_parser.h" #include "opentelemetry/version.h" #include #include @@ -26,8 +25,7 @@ class ConnectionStringParser { public: ConnectionStringParser(const std::string &connection_string) - : account_(""), namespace_(""), - url_(nullptr), transport_protocol_{TransportProtocol::kUnknown} { + : account_(""), namespace_(""), transport_protocol_{TransportProtocol::kUnknown} { std::string::size_type key_pos = 0; std::string::size_type key_end; std::string::size_type val_pos; @@ -36,14 +34,16 @@ class ConnectionStringParser { while ((key_end = connection_string.find(kEqual, key_pos)) != std::string::npos) { if ((val_pos = connection_string.find_first_not_of(kEqual, key_end)) == - std::string::npos) { + std::string::npos) + { break; } val_end = connection_string.find(kSemicolon, val_pos); auto key = connection_string.substr(key_pos, key_end - key_pos); auto value = connection_string.substr(val_pos, val_end - val_pos); key_pos = val_end; - if (key_pos != std::string::npos) { + if (key_pos != std::string::npos) + { ++key_pos; } if (key == kNamespace) { @@ -52,22 +52,24 @@ class ConnectionStringParser { account_ = value; } else if (key == kEndpoint) { is_endpoint_found = true; - url_ = std::unique_ptr( - new ext::http::common::UrlParser(value)); - if (url_->success_) { + size_t pos = value.find("://", 0); + if (pos != std::string::npos) + { + auto scheme = std::string(value.begin(), value.begin() + pos); + connection_string_ = value.substr(pos + strlen("://")); #ifdef HAVE_UNIX_DOMAIN - if (url_->scheme_ == "unix") { + if (scheme == "unix") { transport_protocol_ = TransportProtocol::kUNIX; } #else - if (url_->scheme_ == "unix") { + if (scheme == "unix") { LOG_ERROR("Unix domain socket not supported on this platform") } #endif - if (url_->scheme_ == "tcp") { + if (scheme == "tcp") { transport_protocol_ = TransportProtocol::kTCP; } - if (url_->scheme_ == "udp") { + if (scheme == "udp") { transport_protocol_ = TransportProtocol::kUDP; } } @@ -84,8 +86,8 @@ class ConnectionStringParser { std::string account_; std::string namespace_; - std::unique_ptr url_; TransportProtocol transport_protocol_; + std::string connection_string_; }; } // namespace metrics } // namespace geneva diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h index 0031f65d7..8c460d010 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h @@ -214,6 +214,7 @@ struct SocketAddr { // Indicator that the sockaddr is sockaddr_un bool isUnixDomain; + size_t abstract_socket_size; /// /// SocketAddr constructor @@ -221,6 +222,7 @@ struct SocketAddr { /// SocketAddr SocketAddr() { isUnixDomain = false; + abstract_socket_size = 0; #ifdef HAVE_UNIX_DOMAIN memset(&m_data_un, 0, sizeof(m_data_un)); #else @@ -252,6 +254,12 @@ struct SocketAddr { // Max length of Unix domain filename is up to 108 chars strncpy_s(m_data_un.sun_path, sizeof(m_data_un.sun_path), unix_domain_path, sizeof(m_data_un.sun_path)); + // special handling for abstract socket - they should be + // prefixed with '@' character. + if (unix_domain_path[0] == '@') { + m_data_un.sun_path[0] = '\0'; + abstract_socket_size = ipAddress.size(); + } return; } #endif @@ -305,8 +313,10 @@ struct SocketAddr { size_t size() const { #ifdef HAVE_UNIX_DOMAIN - // Unix domain struct m_data_un - if (isUnixDomain) + if (isUnixDomain && abstract_socket_size) + return sizeof(sa_family_t) + abstract_socket_size; + else if(isUnixDomain) + // Unix domain struct m_data_un return sizeof(m_data_un); #endif // IPv4 struct m_data_in diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc index 8bc4e91fb..956b55475 100644 --- a/exporters/geneva/src/exporter.cc +++ b/exporters/geneva/src/exporter.cc @@ -26,7 +26,7 @@ Exporter::Exporter(const ExporterOptions &options) TransportProtocol::kUNIX) { data_transport_ = std::unique_ptr(new UnixDomainSocketDataTransport( - connection_string_parser_.url_->path_)); + connection_string_parser_.connection_string_)); } #ifdef _WIN32 else if (connection_string_parser_.transport_protocol_ == diff --git a/exporters/geneva/src/unix_domain_socket_data_transport.cc b/exporters/geneva/src/unix_domain_socket_data_transport.cc index 364ff0afb..9fe347e8e 100644 --- a/exporters/geneva/src/unix_domain_socket_data_transport.cc +++ b/exporters/geneva/src/unix_domain_socket_data_transport.cc @@ -10,7 +10,8 @@ namespace geneva { namespace metrics { UnixDomainSocketDataTransport::UnixDomainSocketDataTransport( - const std::string &connection_string) { + const std::string &connection_string) +{ addr_.reset(new SocketTools::SocketAddr(connection_string.c_str(), true)); } diff --git a/exporters/geneva/test/metrics_exporter_test.cc b/exporters/geneva/test/metrics_exporter_test.cc index c1dd94986..fe7cda660 100644 --- a/exporters/geneva/test/metrics_exporter_test.cc +++ b/exporters/geneva/test/metrics_exporter_test.cc @@ -17,7 +17,9 @@ using namespace kaitai; using namespace opentelemetry::sdk::metrics; using namespace opentelemetry::exporter::geneva::metrics; -const std::string kUnixDomainPath = "/tmp/ifx_unix_socket"; +std::string kUnixDomainPathUDS = "/tmp/ifx_unix_socket"; +std::string kUnixDomainPathAbstractSocket = "@/tmp/ifx_unix_socket"; + const std::string kNamespaceName = "test_ns"; const std::string kAccountName = "test_account"; @@ -202,7 +204,12 @@ struct TestServer { } }; -TEST(GenevaMetricsExporter, BasicTests) { +class GenericMetricsExporterTextFixture: public ::testing::TestWithParam +{}; + +TEST_P(GenericMetricsExporterTextFixture, BasicTests) { + + std::string kUnixDomainPath = GetParam(); bool isRunning = true; // Start test server @@ -255,3 +262,8 @@ TEST(GenevaMetricsExporter, BasicTests) { testServer.Stop(); } + +INSTANTIATE_TEST_SUITE_P(GenericMetricsExporterText, GenericMetricsExporterTextFixture, + ::testing::Values(kUnixDomainPathUDS, kUnixDomainPathAbstractSocket)); + + From e66486340059835c9e30710245882de78c5fa2aa Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 24 Apr 2023 11:08:21 -0700 Subject: [PATCH 53/77] add versioned libraries (#275) --- exporters/geneva/CMakeLists.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/exporters/geneva/CMakeLists.txt b/exporters/geneva/CMakeLists.txt index c3167e99b..7db11631b 100644 --- a/exporters/geneva/CMakeLists.txt +++ b/exporters/geneva/CMakeLists.txt @@ -9,6 +9,12 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(opentelemetry-geneva-metrics) set(MAIN_PROJECT ON) endif() +option(OTELCPP_VERSIONED_LIBS "Whether to generate the versioned shared libs" + OFF) +if(OTELCPP_VERSIONED_LIBS AND NOT BUILD_SHARED_LIBS) + message(FATAL_ERROR "OTELCPP_VERSIONED_LIBS=ON requires BUILD_SHARED_LIBS=ON") +endif() + if(NOT WIN32) find_package(CURL REQUIRED) @@ -21,6 +27,17 @@ endif() include_directories(include) +set(OTEL_GENEVA_EXPORTER_VERSION 1.0.0) +set(OTEL_GENEVA_EXPORTER_MAJOR_VERSION 1) + +function(set_target_version target_name) + if(OTELCPP_VERSIONED_LIBS) + set_target_properties( + ${target_name} PROPERTIES VERSION ${OTEL_GENEVA_EXPORTER_VERSION} + SOVERSION ${OTEL_GENEVA_EXPORTER_MAJOR_VERSION}) + endif() +endfunction() + # create geneva metrics exporter if(WIN32) add_library( @@ -44,6 +61,8 @@ endif() set_target_properties(opentelemetry_exporter_geneva_metrics PROPERTIES EXPORT_NAME metrics) +set_target_version(opentelemetry_exporter_geneva_metrics) + if(BUILD_TESTING) if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) # Prefer GTest from build tree. GTest is not always working with From 711814bd968a1d00003fa6a9cfc5265e8935657a Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 2 May 2023 08:54:51 -0700 Subject: [PATCH 54/77] fix (#276) --- .../opentelemetry/exporters/geneva/metrics/socket_tools.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h index 8c460d010..e8fddb5fc 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/socket_tools.h @@ -48,6 +48,10 @@ #include #include +// sa_family_t is not defined in Windows, so typedef-ing it. +// refer - https://learn.microsoft.com/en-us/windows/win32/winsock/sockaddr-2 +typedef u_short sa_family_t; + #ifdef min // NOMINMAX may be a better choice. However, defining it globally may break // other. Code that depends on macro definition in Windows SDK. From 5a6bcfd77c5edb63ec908b2538076e2db1007bd5 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 5 May 2023 10:38:17 -0700 Subject: [PATCH 55/77] [Geneva Exporter] Add support for exporting metrics to different combinations of account and namespace (#280) --- .../exporters/geneva/metrics/exporter.h | 10 +- exporters/geneva/src/exporter.cc | 198 +++++++++++------- .../geneva/test/common/generate_metrics.h | 101 ++++++--- .../geneva/test/decoder/ifx_metrics_bin.cpp | 4 - .../geneva/test/metrics_exporter_test.cc | 70 +++++-- 5 files changed, 263 insertions(+), 120 deletions(-) diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h index 855eb9467..edb407057 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -33,6 +33,9 @@ constexpr uint64_t kSecondsToUnixTime = // 1601-01-01T00:00:00Z and UNIX/Linux epoch // (1970-01-01T00:00:00Z) +const std::string kAttributeNamespaceKey = "_microsoft_metrics_namespace"; +const std::string kAttributeAccountKey = "_microsoft_metrics_account"; + using ValueType = nostd::variant; /** @@ -65,13 +68,8 @@ class Exporter final : public opentelemetry::sdk::metrics::PushMetricExporter { std::unique_ptr data_transport_; // metrics storage - char buffer_non_histogram_[kBufferSize]; - char buffer_histogram_[kBufferSize]; - uint64_t buffer_index_non_histogram_; - uint64_t buffer_index_histogram_; + char buffer_[kBufferSize]; - size_t InitializeBufferForNonHistogramData(); - size_t InitiaizeBufferForHistogramData(); size_t SerializeNonHistogramMetrics(sdk::metrics::AggregationType, MetricsEventType, const sdk::metrics::ValueType &, diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc index 956b55475..f2bd0f302 100644 --- a/exporters/geneva/src/exporter.cc +++ b/exporters/geneva/src/exporter.cc @@ -19,8 +19,7 @@ namespace geneva { namespace metrics { Exporter::Exporter(const ExporterOptions &options) : options_(options), connection_string_parser_(options_.connection_string), - data_transport_{nullptr}, buffer_index_histogram_(0), - buffer_index_non_histogram_(0) { + data_transport_{nullptr} { if (connection_string_parser_.IsValid()) { if (connection_string_parser_.transport_protocol_ == TransportProtocol::kUNIX) { @@ -43,11 +42,6 @@ Exporter::Exporter(const ExporterOptions &options) is_shutdown_ = true; return; } - // Initialize non-histogram buffer - buffer_index_non_histogram_ = InitializeBufferForNonHistogramData(); - - // Initialize histogram buffer - buffer_index_histogram_ = InitiaizeBufferForHistogramData(); } sdk::metrics::AggregationTemporality Exporter::GetAggregationTemporality( @@ -106,7 +100,7 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( sdk::metrics::AggregationType::kSum, event_type, new_value, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); - data_transport_->Send(event_type, buffer_non_histogram_, + data_transport_->Send(event_type, buffer_, body_length + kBinaryHeaderSize); } else if (nostd::holds_alternative( @@ -127,7 +121,7 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( sdk::metrics::AggregationType::kLastValue, event_type, new_value, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); - data_transport_->Send(event_type, buffer_non_histogram_, + data_transport_->Send(event_type, buffer_, body_length + kBinaryHeaderSize); } else if (nostd::holds_alternative( point_data_with_attributes.point_data)) { @@ -156,7 +150,7 @@ opentelemetry::sdk::common::ExportResult Exporter::Export( .counts_, metric_data.end_ts, metric_data.instrument_descriptor.name_, point_data_with_attributes.attributes); - data_transport_->Send(event_type, buffer_histogram_, + data_transport_->Send(event_type, buffer_, body_length + kBinaryHeaderSize); } } @@ -175,7 +169,12 @@ bool Exporter::Shutdown(std::chrono::microseconds timeout) noexcept { return true; } -size_t Exporter::InitializeBufferForNonHistogramData() { +size_t Exporter::SerializeNonHistogramMetrics( + sdk::metrics::AggregationType agg_type, MetricsEventType event_type, + const sdk::metrics::ValueType &value, common::SystemTimestamp ts, + const std::string &metric_name, + const sdk::metrics::PointAttributes &attributes) { + // The buffer format is as follows: // -- BinaryHeader // -- MetricPayload @@ -183,49 +182,62 @@ size_t Exporter::InitializeBufferForNonHistogramData() { // Leave enough space for the header and fixed payload auto bufferIndex = kBinaryHeaderSize + kMetricPayloadSize; - SerializeString(buffer_non_histogram_, bufferIndex, - connection_string_parser_.account_); - SerializeString(buffer_non_histogram_, bufferIndex, - connection_string_parser_.namespace_); - return bufferIndex; -} -size_t Exporter::InitiaizeBufferForHistogramData() { - // The buffer format is as follows: - // -- BinaryHeader - // -- ExternalPayload - // -- Variable length content + auto account_name = connection_string_parser_.account_; + auto account_namespace = connection_string_parser_.namespace_; - // Leave enough space for the header and fixed payload - auto bufferIndex = kBinaryHeaderSize + kExternalPayloadSize; - SerializeString(buffer_histogram_, bufferIndex, - connection_string_parser_.account_); - SerializeString(buffer_histogram_, bufferIndex, - connection_string_parser_.namespace_); - return bufferIndex; -} + // try reading namespace and/or account from attributes + // TBD = This can be avoided by migrating to the + // TLV binary format + for (const auto &kv : attributes) { + if (kv.first == kAttributeAccountKey){ + account_name = AttributeValueToString(kv.second); + } + else if (kv.first == kAttributeNamespaceKey) { + account_namespace = AttributeValueToString(kv.second); + } + } -size_t Exporter::SerializeNonHistogramMetrics( - sdk::metrics::AggregationType agg_type, MetricsEventType event_type, - const sdk::metrics::ValueType &value, common::SystemTimestamp ts, - const std::string &metric_name, - const sdk::metrics::PointAttributes &attributes) { - auto bufferIndex = buffer_index_non_histogram_; - SerializeString(buffer_non_histogram_, bufferIndex, metric_name); + // account name + SerializeString(buffer_, bufferIndex, account_name); + // namespace + SerializeString(buffer_, bufferIndex, account_namespace); + // metric name + SerializeString(buffer_, bufferIndex, metric_name); + + uint16_t attributes_size = 0; for (const auto &kv : attributes) { if (kv.first.size() > kMaxDimensionNameSize) { - LOG_WARN("Dimension name limit overflow: %s Limit %d", kv.first.c_str(), + LOG_WARN("Dimension name limit overflow: %s Limit: %d", kv.first.c_str(), kMaxDimensionNameSize); continue; } - SerializeString(buffer_non_histogram_, bufferIndex, kv.first); + if (kv.first == kAttributeAccountKey || + kv.first == kAttributeNamespaceKey) + { + // custom namespace and account name should't be exported + continue; + } + attributes_size++; + SerializeString(buffer_, bufferIndex, kv.first); } for (const auto &kv : attributes) { + if (kv.first.size() > kMaxDimensionNameSize) { + LOG_WARN("Dimension name limit overflow: %s Limit: %d", kv.first.c_str(), + kMaxDimensionNameSize); + continue; + } + if (kv.first == kAttributeAccountKey || + kv.first == kAttributeNamespaceKey) + { + // custom namespace and account name should't be exported + continue; + } auto attr_value = AttributeValueToString(kv.second); - SerializeString(buffer_non_histogram_, bufferIndex, attr_value); + SerializeString(buffer_, bufferIndex, attr_value); } // length zero for auto-pilot - SerializeInt(buffer_non_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // get final size of payload to be added in front of buffer uint16_t body_length = bufferIndex - kBinaryHeaderSize; @@ -234,22 +246,22 @@ size_t Exporter::SerializeNonHistogramMetrics( bufferIndex = 0; // event_type - SerializeInt(buffer_non_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(event_type)); // body length - SerializeInt(buffer_non_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(body_length)); // count of dimensions. - SerializeInt(buffer_non_histogram_, bufferIndex, - static_cast(attributes.size())); + SerializeInt(buffer_, bufferIndex, + static_cast(attributes_size)); // reserverd word (2 bytes) - SerializeInt(buffer_non_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // reserved word (4 bytes) - SerializeInt(buffer_non_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // timestamp utc (8 bytes) auto windows_ticks = UnixTimeToWindowsTicks( @@ -257,13 +269,13 @@ size_t Exporter::SerializeNonHistogramMetrics( ts.time_since_epoch()) .count()); - SerializeInt(buffer_non_histogram_, bufferIndex, windows_ticks); + SerializeInt(buffer_, bufferIndex, windows_ticks); if (event_type == MetricsEventType::Uint64Metric) { - SerializeInt(buffer_non_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(nostd::get(value))); } else if (event_type == MetricsEventType::DoubleMetric) { SerializeInt( - buffer_non_histogram_, bufferIndex, + buffer_, bufferIndex, *(reinterpret_cast(&(nostd::get(value))))); } else { // Won't reach here. @@ -279,10 +291,37 @@ size_t Exporter::SerializeHistogramMetrics( common::SystemTimestamp ts, const std::string &metric_name, const sdk::metrics::PointAttributes &attributes) { - auto bufferIndex = buffer_index_histogram_; + // The buffer format is as follows: + // -- BinaryHeader + // -- ExternalPayload + // -- Variable length content + + // Leave enough space for the header and fixed payload + auto bufferIndex = kBinaryHeaderSize + kExternalPayloadSize; + + auto account_name = connection_string_parser_.account_; + auto account_namespace = connection_string_parser_.namespace_; + + // try reading namespace and/or account from attributes + // TODO: This can be avoided by migrating to the + // TLV binary format + for (const auto &kv : attributes) { + if (kv.first == kAttributeAccountKey){ + account_name = AttributeValueToString(kv.second); + } + else if (kv.first == kAttributeNamespaceKey) { + account_namespace = AttributeValueToString(kv.second); + } + } + + // account name + SerializeString(buffer_, bufferIndex, account_name); + // namespace + SerializeString(buffer_, bufferIndex, account_namespace); // metric name - SerializeString(buffer_histogram_, bufferIndex, metric_name); + SerializeString(buffer_, bufferIndex, metric_name); + uint16_t attributes_size = 0; // dimentions - name for (const auto &kv : attributes) { if (kv.first.size() > kMaxDimensionNameSize) { @@ -290,29 +329,46 @@ size_t Exporter::SerializeHistogramMetrics( kMaxDimensionNameSize); continue; } - SerializeString(buffer_histogram_, bufferIndex, kv.first); + if (kv.first == kAttributeAccountKey || + kv.first == kAttributeNamespaceKey) + { + // custom namespace and account name should't be exported + continue; + } + attributes_size++; + SerializeString(buffer_, bufferIndex, kv.first); } // dimentions - value for (const auto &kv : attributes) { + if (kv.first.size() > kMaxDimensionNameSize) { + // warning is already logged earlier, no logging again + continue; + } + if (kv.first == kAttributeAccountKey || + kv.first == kAttributeNamespaceKey) + { + // custom namespace and account name should't be exported + continue; + } auto attr_value = AttributeValueToString(kv.second); - SerializeString(buffer_histogram_, bufferIndex, attr_value); + SerializeString(buffer_, bufferIndex, attr_value); } // two bytes padding for auto-pilot - SerializeInt(buffer_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // version - set as 0 - SerializeInt(buffer_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // Meta-data // Value-count pairs is associated with the constant value of 2 in the // distribution_type enum. - SerializeInt(buffer_histogram_, bufferIndex, 2); + SerializeInt(buffer_, bufferIndex, 2); // Keep a position to record how many buckets are added auto itemsWrittenIndex = bufferIndex; - SerializeInt(buffer_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // bucket values size_t index = 0; @@ -321,9 +377,9 @@ size_t Exporter::SerializeHistogramMetrics( MetricsEventType::ExternallyAggregatedUlongDistributionMetric) { for (auto boundary : boundaries) { if (counts[index] > 0) { - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(boundary)); - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, (uint32_t)(counts[index])); bucket_count++; } @@ -332,7 +388,7 @@ size_t Exporter::SerializeHistogramMetrics( } // write bucket count to previous preserved index - SerializeInt(buffer_histogram_, itemsWrittenIndex, bucket_count); + SerializeInt(buffer_, itemsWrittenIndex, bucket_count); // get final size of payload to be added in front of buffer uint16_t body_length = bufferIndex - kBinaryHeaderSize; @@ -341,42 +397,42 @@ size_t Exporter::SerializeHistogramMetrics( bufferIndex = 0; // event_type - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(event_type)); // body length - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(body_length)); // count of dimensions. - SerializeInt(buffer_histogram_, bufferIndex, - static_cast(attributes.size())); + SerializeInt(buffer_, bufferIndex, + static_cast(attributes_size)); // reserverd word (2 bytes) - SerializeInt(buffer_histogram_, bufferIndex, 0); + SerializeInt(buffer_, bufferIndex, 0); // count of events - SerializeInt(buffer_histogram_, bufferIndex, count); + SerializeInt(buffer_, bufferIndex, count); // timestamp utc (8 bytes) auto windows_ticks = UnixTimeToWindowsTicks( std::chrono::duration_cast>( ts.time_since_epoch()) .count()); - SerializeInt(buffer_histogram_, bufferIndex, windows_ticks); + SerializeInt(buffer_, bufferIndex, windows_ticks); // sum, min, max if (event_type == MetricsEventType::ExternallyAggregatedUlongDistributionMetric) { // sum - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(nostd::get(sum))); // min - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(nostd::get(min))); // max - SerializeInt(buffer_histogram_, bufferIndex, + SerializeInt(buffer_, bufferIndex, static_cast(nostd::get(max))); } else { // won't reach here. diff --git a/exporters/geneva/test/common/generate_metrics.h b/exporters/geneva/test/common/generate_metrics.h index 588e3c26e..67a3eb6d7 100644 --- a/exporters/geneva/test/common/generate_metrics.h +++ b/exporters/geneva/test/common/generate_metrics.h @@ -30,7 +30,10 @@ const uint16_t kCounterDoubleCountDimensions = 1; const uint16_t kCounterDoubleEventId = 55; static inline opentelemetry::sdk::metrics::ResourceMetrics -GenerateSumDataDoubleMetrics() { +GenerateSumDataDoubleMetrics( + std::string account_name = "", + std::string account_namespace= "" +) { opentelemetry::sdk::metrics::SumPointData sum_point_data1{}; sum_point_data1.value_ = kCounterDoubleValue1; sum_point_data1.is_monotonic_ = true; @@ -44,6 +47,18 @@ GenerateSumDataDoubleMetrics() { auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::PointAttributes attributes1 = + {{kCounterDoubleAttributeKey1, + kCounterDoubleAttributeValue1}}; + opentelemetry::sdk::metrics::PointAttributes attributes2 = + {{kCounterDoubleAttributeKey2, kCounterDoubleAttributeValue2}, + {kCounterDoubleAttributeKey3, kCounterDoubleAttributeValue3}}; + if (account_name.size() && account_namespace.size()) { + attributes1[opentelemetry::exporter::geneva::metrics::kAttributeNamespaceKey] = account_namespace; + attributes1[opentelemetry::exporter::geneva::metrics::kAttributeAccountKey] = account_name; + attributes2[opentelemetry::exporter::geneva::metrics::kAttributeNamespaceKey] = account_namespace; + attributes2[opentelemetry::exporter::geneva::metrics::kAttributeAccountKey] = account_name; + } opentelemetry::sdk::metrics::MetricData metric_data{ opentelemetry::sdk::metrics::InstrumentDescriptor{ kCounterDoubleInstrumentName, kCounterDoubleInstrumentDesc, @@ -54,12 +69,9 @@ GenerateSumDataDoubleMetrics() { opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ - {opentelemetry::sdk::metrics::PointAttributes{ - {kCounterDoubleAttributeKey1, kCounterDoubleAttributeValue1}}, + {attributes1, sum_point_data1}, - {opentelemetry::sdk::metrics::PointAttributes{ - {kCounterDoubleAttributeKey2, kCounterDoubleAttributeValue2}, - {kCounterDoubleAttributeKey3, kCounterDoubleAttributeValue3}}, + {attributes2, sum_point_data2}}}; data.scope_metric_data_ = std::vector{ @@ -76,6 +88,7 @@ const std::string kCounterLongInstrumentDesc = const std::string kCounterLongInstrumentUnit = "test_instrument_conter_long_unit"; const long kCounterLongValue = 102; +const long kCounterCustomLongValue = 103; const std::string kCounterLongAttributeKey1 = "counter_long_key1"; const std::string kCounterLongAttributeValue1 = "counter_long_value1"; @@ -83,9 +96,11 @@ const uint16_t kCounterLongCountDimensions = 1; const uint16_t kCounterLongEventId = 50; static inline opentelemetry::sdk::metrics::ResourceMetrics -GenerateSumDataLongMetrics() { +GenerateSumDataLongMetrics( + std::string account_name = "", + std::string account_namespace= "" +) { opentelemetry::sdk::metrics::SumPointData sum_point_data{}; - sum_point_data.value_ = kCounterLongValue; sum_point_data.is_monotonic_ = true; opentelemetry::sdk::metrics::ResourceMetrics data; auto resource = opentelemetry::sdk::resource::Resource::Create( @@ -94,6 +109,16 @@ GenerateSumDataLongMetrics() { auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::PointAttributes attributes = + {{kCounterLongAttributeKey1, + kCounterLongAttributeValue1}}; + if (account_name.size() && account_namespace.size()) { + attributes[opentelemetry::exporter::geneva::metrics::kAttributeNamespaceKey] = account_namespace; + attributes[opentelemetry::exporter::geneva::metrics::kAttributeAccountKey] = account_name; + sum_point_data.value_ = kCounterCustomLongValue; + } else { + sum_point_data.value_ = kCounterLongValue; + } opentelemetry::sdk::metrics::MetricData metric_data{ opentelemetry::sdk::metrics::InstrumentDescriptor{ kCounterLongInstrumentName, kCounterLongInstrumentDesc, @@ -104,9 +129,7 @@ GenerateSumDataLongMetrics() { opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ - {opentelemetry::sdk::metrics::PointAttributes{ - {kCounterLongAttributeKey1, kCounterLongAttributeValue1}}, - sum_point_data}}}; + {attributes, sum_point_data}}}; data.scope_metric_data_ = std::vector{ {scope.get(), @@ -128,7 +151,10 @@ const std::string kUpDownCounterLongAttributeValue1 = const uint16_t kUpDownCounterLongCountDimensions = 1; static inline opentelemetry::sdk::metrics::ResourceMetrics -GenerateSumDataLongMetricsNonMonotonic() { +GenerateSumDataLongMetricsNonMonotonic( + std::string account_name = "", + std::string account_namespace= "" +) { opentelemetry::sdk::metrics::SumPointData sum_point_data{}; sum_point_data.value_ = kUpDownCounterLongValue; sum_point_data.is_monotonic_ = false; @@ -139,6 +165,13 @@ GenerateSumDataLongMetricsNonMonotonic() { auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::PointAttributes attributes = + {{kUpDownCounterLongAttributeKey1, + kUpDownCounterLongAttributeValue1}}; + if (account_name.size() && account_namespace.size()) { + attributes[opentelemetry::exporter::geneva::metrics::kAttributeNamespaceKey] = account_namespace; + attributes[opentelemetry::exporter::geneva::metrics::kAttributeAccountKey] = account_name; + } opentelemetry::sdk::metrics::MetricData metric_data{ opentelemetry::sdk::metrics::InstrumentDescriptor{ kUpDownCounterLongInstrumentName, kUpDownCounterLongInstrumentDesc, @@ -149,10 +182,7 @@ GenerateSumDataLongMetricsNonMonotonic() { opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ - {opentelemetry::sdk::metrics::PointAttributes{ - {kUpDownCounterLongAttributeKey1, - kUpDownCounterLongAttributeValue1}}, - sum_point_data}}}; + {attributes, sum_point_data}}}; data.scope_metric_data_ = std::vector{ {scope.get(), @@ -175,7 +205,10 @@ const std::string kUpDownCounterDoubleAttributeValue1 = const uint16_t kUpDownCounterDoubleCountDimensions = 1; static inline opentelemetry::sdk::metrics::ResourceMetrics -GenerateSumDataDoubleMetricsNonMonotonic() { +GenerateSumDataDoubleMetricsNonMonotonic( + std::string account_name = "", + std::string account_namespace = "" +) { opentelemetry::sdk::metrics::SumPointData sum_point_data1{}; sum_point_data1.value_ = kUpDownCounterDoubleValue; sum_point_data1.is_monotonic_ = false; @@ -186,6 +219,13 @@ GenerateSumDataDoubleMetricsNonMonotonic() { auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::PointAttributes attributes = + {{kUpDownCounterDoubleAttributeKey1, + kUpDownCounterDoubleAttributeValue1}}; + if (account_name.size() && account_namespace.size()) { + attributes[opentelemetry::exporter::geneva::metrics::kAttributeNamespaceKey] = account_namespace; + attributes[opentelemetry::exporter::geneva::metrics::kAttributeAccountKey] = account_name; + } opentelemetry::sdk::metrics::MetricData metric_data{ opentelemetry::sdk::metrics::InstrumentDescriptor{ kUpDownCounterDoubleInstrumentName, @@ -197,9 +237,7 @@ GenerateSumDataDoubleMetricsNonMonotonic() { opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ - {opentelemetry::sdk::metrics::PointAttributes{ - {kUpDownCounterDoubleAttributeKey1, - kUpDownCounterDoubleAttributeValue1}}, + {attributes, sum_point_data1}}}; data.scope_metric_data_ = std::vector{ @@ -217,6 +255,7 @@ const std::string kHistogramLongInstrumentUnit = "test_instrument_histogram_long_unit"; const long kHistogramLongSum = 4024l; +const long kHistogramCustomLongSum = 4025l; const long kHistogramLongMin = 3l; const long kHistogramLongMax = 1004l; const size_t kHistogramLongCount = 10l; @@ -234,10 +273,11 @@ const uint16_t kHistogramLongCountDimensions = 1; const uint16_t kHistogramLongEventId = 56; static inline opentelemetry::sdk::metrics::ResourceMetrics -GenerateHistogramDataLongMetrics() { - +GenerateHistogramDataLongMetrics( + std::string account_name = "", + std::string account_namespace = "" +) { opentelemetry::sdk::metrics::HistogramPointData histogram_point_data{}; - histogram_point_data.sum_ = kHistogramLongSum; histogram_point_data.boundaries_ = kHistogramLongBoundaries; histogram_point_data.count_ = kHistogramLongCount; histogram_point_data.min_ = kHistogramLongMin; @@ -251,6 +291,17 @@ GenerateHistogramDataLongMetrics() { auto scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( kInstrumentScopeName, kInstrumentScopeVer); + opentelemetry::sdk::metrics::PointAttributes attributes = + {{kHistogramLongAttributeKey1, + kHistogramLongAttributeValue1}}; + if (account_name.size() && account_namespace.size()) { + attributes[opentelemetry::exporter::geneva::metrics::kAttributeNamespaceKey] = account_namespace; + attributes[opentelemetry::exporter::geneva::metrics::kAttributeAccountKey] = account_name; + histogram_point_data.sum_ = kHistogramCustomLongSum; + + } else { + histogram_point_data.sum_ = kHistogramLongSum; + } opentelemetry::sdk::metrics::MetricData metric_data{ opentelemetry::sdk::metrics::InstrumentDescriptor{ kHistogramLongInstrumentName, kHistogramLongInstrumentDesc, @@ -261,9 +312,7 @@ GenerateHistogramDataLongMetrics() { opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ - {opentelemetry::sdk::metrics::PointAttributes{ - {kHistogramLongAttributeKey1, kHistogramLongAttributeValue1}}, - histogram_point_data}}}; + {attributes, histogram_point_data}}}; data.scope_metric_data_ = std::vector{ {scope.get(), diff --git a/exporters/geneva/test/decoder/ifx_metrics_bin.cpp b/exporters/geneva/test/decoder/ifx_metrics_bin.cpp index bd6091e8f..aa1979183 100644 --- a/exporters/geneva/test/decoder/ifx_metrics_bin.cpp +++ b/exporters/geneva/test/decoder/ifx_metrics_bin.cpp @@ -4,8 +4,6 @@ #include ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, ifx_metrics_bin_t* p__root) : kaitai::kstruct(p__io) { - std::cout << "\nLALIT:ifx_metrics_bin::CONST.."; - m__parent = p__parent; m__root = this; m_body = 0; @@ -20,9 +18,7 @@ ifx_metrics_bin_t::ifx_metrics_bin_t(kaitai::kstream* p__io, kaitai::kstruct* p_ } void ifx_metrics_bin_t::_read() { - std::cout << "\nLALIT:ifx_metrics_bin::READ.."; m_event_id = m__io->read_u2le(); - std::cout << "\nLALIT:ifx_metrics_bin Event ID:" << m_event_id << "\n"; m_len_body = m__io->read_u2le(); m__raw_body = m__io->read_bytes(len_body()); m__io__raw_body = new kaitai::kstream(m__raw_body); diff --git a/exporters/geneva/test/metrics_exporter_test.cc b/exporters/geneva/test/metrics_exporter_test.cc index fe7cda660..694a312ba 100644 --- a/exporters/geneva/test/metrics_exporter_test.cc +++ b/exporters/geneva/test/metrics_exporter_test.cc @@ -23,6 +23,10 @@ std::string kUnixDomainPathAbstractSocket = "@/tmp/ifx_unix_socket"; const std::string kNamespaceName = "test_ns"; const std::string kAccountName = "test_account"; +const std::string kCustomNamespaceName = "custom_ns"; +const std::string kCustomAccountName = "custom_account"; + + // "busy sleep" while suggesting that other threads run // for a small amount of time template void yield_for(timeunit duration) { @@ -41,6 +45,7 @@ struct TestServer { size_t count_up_down_counter_long = 0; size_t count_up_down_counter_double = 0; size_t count_histogram_long = 0; + size_t count_custom_histogram_long = 0; TestServer(SocketServer &server) : server(server) { server.onRequest = [&](SocketServer::Connection &conn) { @@ -110,18 +115,39 @@ struct TestServer { } else if (event_bin.event_id() == kCounterLongEventId) { EXPECT_EQ(event_bin.event_id(), kCounterLongEventId); auto event_body = event_bin.body(); - EXPECT_EQ(static_cast( + if (static_cast( + event_body->value_section())->value() == kCounterLongValue) { + EXPECT_EQ(static_cast( event_body->value_section()) ->value(), kCounterLongValue); - EXPECT_EQ(event_body->num_dimensions(), + EXPECT_EQ(event_body->num_dimensions(), kCounterLongCountDimensions); - EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), kCounterLongAttributeValue1); - EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), kCounterLongAttributeKey1); - count_counter_long++; - } else if (event_bin.event_id() == kHistogramLongEventId) { + count_counter_long++; + EXPECT_EQ(event_body->metric_account()->value(), kAccountName); + EXPECT_EQ(event_body->metric_namespace()->value(), kNamespaceName); + } else if (static_cast( + event_body->value_section())->value() == kCounterCustomLongValue) { + EXPECT_EQ(static_cast( + event_body->value_section()) + ->value(), + kCounterCustomLongValue); + EXPECT_EQ(event_body->num_dimensions(), + kCounterLongCountDimensions); + EXPECT_EQ(event_body->dimensions_values()->at(0)->value(), + kCounterLongAttributeValue1); + EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), + kCounterLongAttributeKey1); + count_counter_long++; + EXPECT_EQ(event_body->metric_account()->value(), kCustomAccountName); + EXPECT_EQ(event_body->metric_namespace()->value(), kCustomNamespaceName); + } + } + else if (event_bin.event_id() == kHistogramLongEventId) { EXPECT_EQ(event_bin.event_id(), kHistogramLongEventId); auto event_body = event_bin.body(); EXPECT_EQ(event_body->num_dimensions(), @@ -130,11 +156,19 @@ struct TestServer { kHistogramLongAttributeValue1); EXPECT_EQ(event_body->dimensions_names()->at(0)->value(), kHistogramLongAttributeKey1); - EXPECT_EQ( - static_cast( + if (static_cast( event_body->value_section()) - ->sum(), - kHistogramLongSum); + ->sum() == kHistogramLongSum) { + EXPECT_EQ(event_body->metric_account()->value(), kAccountName); + EXPECT_EQ(event_body->metric_namespace()->value(), kNamespaceName); + count_histogram_long++; + } else if (static_cast( + event_body->value_section()) + ->sum() == kHistogramCustomLongSum) { + EXPECT_EQ(event_body->metric_account()->value(), kCustomAccountName); + EXPECT_EQ(event_body->metric_namespace()->value(), kCustomNamespaceName); + count_custom_histogram_long++; + } EXPECT_EQ( static_cast( event_body->value_section()) @@ -177,7 +211,6 @@ struct TestServer { } index_all_buckets++; } - count_histogram_long++; } } catch (...) { @@ -228,6 +261,7 @@ TEST_P(GenericMetricsExporterTextFixture, BasicTests) { ExporterOptions options{conn_string}; opentelemetry::exporter::geneva::metrics::Exporter exporter(options); + // export sum aggregation - double auto metric_data = GenerateSumDataDoubleMetrics(); exporter.Export(metric_data); @@ -238,6 +272,11 @@ TEST_P(GenericMetricsExporterTextFixture, BasicTests) { exporter.Export(metric_data); yield_for(std::chrono::milliseconds(1000)); + // export sum aggregation - long, custom account & ns + metric_data = GenerateSumDataLongMetrics(kCustomAccountName, kCustomNamespaceName); + exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(1000)); + // export sum aggregation - long - non monotonic metric_data = GenerateSumDataLongMetricsNonMonotonic(); exporter.Export(metric_data); @@ -253,12 +292,17 @@ TEST_P(GenericMetricsExporterTextFixture, BasicTests) { exporter.Export(metric_data); yield_for(std::chrono::milliseconds(1000)); + // export histogram aggregation - long, custom account & ns + metric_data = GenerateHistogramDataLongMetrics(kCustomAccountName, kCustomNamespaceName); + exporter.Export(metric_data); + yield_for(std::chrono::milliseconds(1000)); + EXPECT_EQ(testServer.count_counter_double, 1); - EXPECT_EQ(testServer.count_counter_long, 1); + EXPECT_EQ(testServer.count_counter_long, 2); EXPECT_EQ(testServer.count_up_down_counter_long, 1); EXPECT_EQ(testServer.count_up_down_counter_double, 1); - EXPECT_EQ(testServer.count_histogram_long, 1); + EXPECT_EQ(testServer.count_custom_histogram_long, 1); testServer.Stop(); } From b666b2e6aa2936c892aa7c0f3c5c39ec9fbc5f32 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 16 May 2023 10:15:29 -0700 Subject: [PATCH 56/77] [Geneva Metrics Exporter] Fix stress test for abstract socket. (#287) --- exporters/geneva/example/stress_test_linux.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/geneva/example/stress_test_linux.cc b/exporters/geneva/example/stress_test_linux.cc index 462667d13..3145821ea 100644 --- a/exporters/geneva/example/stress_test_linux.cc +++ b/exporters/geneva/example/stress_test_linux.cc @@ -47,7 +47,7 @@ namespace { std::cout << " Init metrics : " < Date: Thu, 1 Jun 2023 19:54:17 -0700 Subject: [PATCH 57/77] Add OpenTelemetry logs exporter targeting user_events on Linux (#286) --- .gitmodules | 3 + exporters/user_events/.clang-format | 61 +++++++ exporters/user_events/.cmake-format.py | 7 + exporters/user_events/.gitignore | 1 + .../user_events/.vscode/c_cpp_properties.json | 11 ++ exporters/user_events/CMakeLists.txt | 107 +++++++++++ .../user_events/benchmark/logger_benchmark.cc | 170 ++++++++++++++++++ exporters/user_events/example/foo_library.cc | 46 +++++ exporters/user_events/example/foo_library.h | 6 + exporters/user_events/example/main.cc | 74 ++++++++ .../exporters/user_events/logs/exporter.h | 70 ++++++++ .../user_events/logs/exporter_options.h | 26 +++ .../exporters/user_events/logs/recordable.h | 131 ++++++++++++++ .../exporters/user_events/logs/utils.h | 28 +++ exporters/user_events/src/logs_exporter.cc | 96 ++++++++++ exporters/user_events/src/recordable.cc | 115 ++++++++++++ exporters/user_events/src/utils.cc | 87 +++++++++ .../user_events/test/logs_exporter_test.cc | 35 ++++ .../user_events/third_party/LinuxTracepoints | 1 + 19 files changed, 1075 insertions(+) create mode 100644 exporters/user_events/.clang-format create mode 100644 exporters/user_events/.cmake-format.py create mode 100644 exporters/user_events/.gitignore create mode 100644 exporters/user_events/.vscode/c_cpp_properties.json create mode 100644 exporters/user_events/CMakeLists.txt create mode 100644 exporters/user_events/benchmark/logger_benchmark.cc create mode 100644 exporters/user_events/example/foo_library.cc create mode 100644 exporters/user_events/example/foo_library.h create mode 100644 exporters/user_events/example/main.cc create mode 100644 exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h create mode 100644 exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h create mode 100644 exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h create mode 100644 exporters/user_events/include/opentelemetry/exporters/user_events/logs/utils.h create mode 100644 exporters/user_events/src/logs_exporter.cc create mode 100644 exporters/user_events/src/recordable.cc create mode 100644 exporters/user_events/src/utils.cc create mode 100644 exporters/user_events/test/logs_exporter_test.cc create mode 160000 exporters/user_events/third_party/LinuxTracepoints diff --git a/.gitmodules b/.gitmodules index eabbc692f..864362ecc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "exporters/geneva-trace/third_party/opentelemetry-cpp"] path = exporters/geneva-trace/third_party/opentelemetry-cpp url = https://github.com/open-telemetry/opentelemetry-cpp +[submodule "exporters/user_events/third_party/LinuxTracepoints"] + path = exporters/user_events/third_party/LinuxTracepoints + url = https://github.com/microsoft/LinuxTracepoints diff --git a/exporters/user_events/.clang-format b/exporters/user_events/.clang-format new file mode 100644 index 000000000..2640295e6 --- /dev/null +++ b/exporters/user_events/.clang-format @@ -0,0 +1,61 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# See Clang docs: http://clang.llvm.org/docs/ClangFormatStyleOptions.html +BasedOnStyle: Chromium + +# Allow double brackets such as std::vector>. +Standard: Cpp11 + +# Indent 2 spaces at a time. +IndentWidth: 2 + +# Keep lines under 100 columns long. +ColumnLimit: 100 + +# Always break before braces +BreakBeforeBraces: Custom +BraceWrapping: +# TODO(lujc) wait for clang-format-9 support in Chromium tools +# AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false + + # Keeps extern "C" blocks unindented. + AfterExternBlock: false + +# Indent case labels. +IndentCaseLabels: true + +# Right-align pointers and references +PointerAlignment: Right + +# ANGLE likes to align things as much as possible. +AlignOperands: true +AlignConsecutiveAssignments: true + +# Use 2 space negative offset for access modifiers +AccessModifierOffset: -2 + +# TODO(jmadill): Decide if we want this on. Doesn't have an "all or none" mode. +AllowShortCaseLabelsOnASingleLine: false + +# Useful for spacing out functions in classes +KeepEmptyLinesAtTheStartOfBlocks: true + +# Indent nested PP directives. +IndentPPDirectives: AfterHash + +# Include blocks style +IncludeBlocks: Preserve diff --git a/exporters/user_events/.cmake-format.py b/exporters/user_events/.cmake-format.py new file mode 100644 index 000000000..d232ac8eb --- /dev/null +++ b/exporters/user_events/.cmake-format.py @@ -0,0 +1,7 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# If comment markup is enabled, don't reflow the first comment block in +# eachlistfile. Use this to preserve formatting of your +# copyright/licensestatements. +first_comment_is_literal = True diff --git a/exporters/user_events/.gitignore b/exporters/user_events/.gitignore new file mode 100644 index 000000000..89f9ac04a --- /dev/null +++ b/exporters/user_events/.gitignore @@ -0,0 +1 @@ +out/ diff --git a/exporters/user_events/.vscode/c_cpp_properties.json b/exporters/user_events/.vscode/c_cpp_properties.json new file mode 100644 index 000000000..469afd321 --- /dev/null +++ b/exporters/user_events/.vscode/c_cpp_properties.json @@ -0,0 +1,11 @@ +{ + "configurations": [ + { + "name": "otel_log", + "defines": [ + "ENABLE_LOGS_PREVIEW" + ] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/exporters/user_events/CMakeLists.txt b/exporters/user_events/CMakeLists.txt new file mode 100644 index 000000000..f6fcac5c9 --- /dev/null +++ b/exporters/user_events/CMakeLists.txt @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.12) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(WIN32) + message(FATAL_ERROR "user_events is Linux only for now") +endif() + +option(BUILD_EXAMPLE "Build example" ON) +option(BUILD_TESTING "Build tests" ON) + +set(MAIN_PROJECT OFF) + +if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) + project(opentelemetry-userevents-logs) + set(MAIN_PROJECT ON) +endif() + +add_definitions(-DHAVE_CONSOLE_LOG -DENABLE_LOGS_PREVIEW) + +if(MAIN_PROJECT) + find_package(opentelemetry-cpp REQUIRED) +endif() + +add_subdirectory(third_party/LinuxTracepoints) + +include_directories(include) + +add_library(opentelemetry_exporter_user_events_logs + src/logs_exporter.cc src/recordable.cc src/utils.cc) + +if(MAIN_PROJECT) + target_include_directories(opentelemetry_exporter_user_events_logs + PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) + target_link_libraries(opentelemetry_exporter_user_events_logs + PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES}) +else() + target_link_libraries( + opentelemetry_exporter_user_events_logs + PUBLIC opentelemetry_logs opentelemetry_resources opentelemetry_common) +endif() + +target_link_libraries(opentelemetry_exporter_user_events_logs + PUBLIC eventheader-tracepoint tracepoint) + +set_target_properties(opentelemetry_exporter_user_events_logs + PROPERTIES EXPORT_NAME logs) + +if(BUILD_EXAMPLE) + + add_executable(user_events_logs example/main.cc example/foo_library.cc) + target_link_libraries( + user_events_logs ${CMAKE_THREAD_LIBS_INIT} opentelemetry_logs + opentelemetry_exporter_user_events_logs) + +endif(BUILD_EXAMPLE) + +if(BUILD_TESTING) + if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) + # Prefer GTest from build tree. GTest is not always working with + # CMAKE_PREFIX_PATH + set(GTEST_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googletest/include + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/googletest/googlemock/include) + set(GTEST_BOTH_LIBRARIES + ${CMAKE_BINARY_DIR}/lib/libgtest.a + ${CMAKE_BINARY_DIR}/lib/libgtest_main.a + ${CMAKE_BINARY_DIR}/lib/libgmock.a) + else() + find_package(GTest REQUIRED) + endif() + include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) + include_directories(SYSTEM test/decoder) + enable_testing() + include(GoogleTest) + # build tests for user_events logs + add_executable(userevents_logs_exporter_test test/logs_exporter_test.cc) + target_link_libraries( + userevents_logs_exporter_test ${GTEST_BOTH_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_exporter_user_events_logs) + + gtest_add_tests( + TARGET userevents_logs_exporter_test + TEST_PREFIX exporter. + TEST_LIST userevents_logs_exporter_test) +endif() + +find_package(benchmark CONFIG REQUIRED) +add_executable(user_events_logger_benchmark benchmark/logger_benchmark.cc) +target_link_libraries( + user_events_logger_benchmark benchmark::benchmark ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_logs + opentelemetry_exporter_user_events_logs) + +install( + TARGETS opentelemetry_exporter_user_events_logs + EXPORT "${PROJECT_NAME}-target" + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install( + DIRECTORY include/opentelemetry/exporters/userevents + DESTINATION include/opentelemetry/exporters + FILES_MATCHING + PATTERN "*.h") diff --git a/exporters/user_events/benchmark/logger_benchmark.cc b/exporters/user_events/benchmark/logger_benchmark.cc new file mode 100644 index 000000000..d45741f65 --- /dev/null +++ b/exporters/user_events/benchmark/logger_benchmark.cc @@ -0,0 +1,170 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/logs/provider.h" +# include "opentelemetry/nostd/shared_ptr.h" + +# include "opentelemetry/exporters/user_events/logs/exporter.h" +# include "opentelemetry/logs/provider.h" +# include "opentelemetry/sdk/logs/logger_provider_factory.h" +# include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" + +# include +# include +# include +# include +# include +# include + +# include + +using opentelemetry::logs::EventId; +using opentelemetry::logs::Logger; +using opentelemetry::logs::LoggerProvider; +using opentelemetry::logs::Provider; +using opentelemetry::logs::Severity; +using opentelemetry::nostd::shared_ptr; +using opentelemetry::nostd::span; +using opentelemetry::nostd::string_view; + +namespace common = opentelemetry::common; +namespace nostd = opentelemetry::nostd; +namespace trace = opentelemetry::trace; +namespace log_api = opentelemetry::logs; + +namespace logs_api = opentelemetry::logs; +namespace logs_sdk = opentelemetry::sdk::logs; +namespace user_events_logs = opentelemetry::exporter::user_events::logs; + +namespace +{ + +constexpr int64_t kMaxIterations = 1000000; + +class Barrier +{ +public: + explicit Barrier(std::size_t iCount) : mThreshold(iCount), mCount(iCount), mGeneration(0) {} + + void Wait() + { + std::unique_lock lLock{mMutex}; + auto lGen = mGeneration; + if (!--mCount) + { + mGeneration++; + mCount = mThreshold; + mCond.notify_all(); + } + else + { + mCond.wait(lLock, [this, lGen] { return lGen != mGeneration; }); + } + } + +private: + std::mutex mMutex; + std::condition_variable mCond; + std::size_t mThreshold; + std::size_t mCount; + std::size_t mGeneration; +}; + +static void ThreadRoutine(Barrier &barrier, + benchmark::State &state, + int thread_id, + std::function func) +{ + barrier.Wait(); + + if (thread_id == 0) + { + state.ResumeTiming(); + } + + barrier.Wait(); + + func(); + + if (thread_id == 0) + { + state.PauseTiming(); + } + + barrier.Wait(); +} + +void MultiThreadRunner(benchmark::State &state, std::function func) +{ + int num_threads = std::thread::hardware_concurrency(); + + Barrier barrier(num_threads); + + std::vector threads; + + for (int i = 0; i < num_threads; i++) + { + threads.emplace_back(ThreadRoutine, std::ref(barrier), std::ref(state), i, func); + } + + for (auto &thread : threads) + { + thread.join(); + } +} + +void InitLogger() +{ + // Create user_events log exporter instance + auto exporter_options = user_events_logs::ExporterOptions(); + auto exporter = + std::unique_ptr(new user_events_logs::Exporter(exporter_options)); + auto processor = logs_sdk::SimpleLogRecordProcessorFactory::Create(std::move(exporter)); + std::shared_ptr provider( + logs_sdk::LoggerProviderFactory::Create(std::move(processor))); + + // Set the global logger provider + logs_api::Provider::SetLoggerProvider(provider); +} + +static void BM_StructuredLogWithEventIdStructAndTwoAttributes(benchmark::State &state) +{ + InitLogger(); + + auto lp = Provider::GetLoggerProvider(); + auto logger = lp->GetLogger("StructuredLogWithEventId"); + + const EventId function_name_event_id{0x12345678, "Company.Component.SubComponent.FunctionName"}; + + for (auto _ : state) + { + state.PauseTiming(); + + MultiThreadRunner(state, [&logger, &function_name_event_id]() { + for (int64_t i = 0; i < kMaxIterations; i++) + { + logger->Trace( + function_name_event_id, + "Simulate function enter trace message from {process_id}:{thread_id}", + opentelemetry::common::MakeAttributes({{"process_id", 12347}, {"thread_id", 12348}})); + } + }); + + state.ResumeTiming(); + } +} +BENCHMARK(BM_StructuredLogWithEventIdStructAndTwoAttributes); + +} // namespace + +int main(int argc, char **argv) +{ + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); +} + +#endif diff --git a/exporters/user_events/example/foo_library.cc b/exporters/user_events/example/foo_library.cc new file mode 100644 index 000000000..e4ff82308 --- /dev/null +++ b/exporters/user_events/example/foo_library.cc @@ -0,0 +1,46 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/logs/event_id.h" +# include "opentelemetry/logs/provider.h" +# include "opentelemetry/sdk/version/version.h" + +namespace logs = opentelemetry::logs; +namespace nostd = opentelemetry::nostd; + +const logs::EventId fruit_sell_event_id{0x1, "FruitCompany.SalesDepartment.SellFruit"}; +const logs::EventId fruit_not_found_event_id{0x2, "FruitCompany.SalesDepartment.FruitNotFound"}; + +std::map fruit_inventory = {{"apple", 1}, {"orange", 2}, {"banana", 3}}; + +namespace +{ +nostd::shared_ptr get_logger() +{ + auto provider = logs::Provider::GetLoggerProvider(); + return provider->GetLogger("fruit_selling"); +} +} // namespace + +void sell_fruit(std::string_view fruit) +{ + auto logger = get_logger(); + + if (fruit_inventory.find(std::string{fruit}) == fruit_inventory.end()) + { + logger->Error( + fruit_not_found_event_id, "Fruit {fruit_name} not found in inventory with {error_code}", + opentelemetry::common::MakeAttributes({{"fruit_name", fruit.data()}, {"error_code", 404}})); + + return; + } + + logger->Trace(fruit_sell_event_id, "Selling fruit {fruit_name} with {fruit_price}", + opentelemetry::common::MakeAttributes( + {{"fruit_name", fruit.data()}, + {"fruit_price", static_cast(fruit_inventory[fruit.data()])}})); +} + +#endif diff --git a/exporters/user_events/example/foo_library.h b/exporters/user_events/example/foo_library.h new file mode 100644 index 000000000..16ce9c76e --- /dev/null +++ b/exporters/user_events/example/foo_library.h @@ -0,0 +1,6 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +void sell_fruit(std::string_view fruit); diff --git a/exporters/user_events/example/main.cc b/exporters/user_events/example/main.cc new file mode 100644 index 000000000..f0c2cf1ed --- /dev/null +++ b/exporters/user_events/example/main.cc @@ -0,0 +1,74 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/user_events/logs/exporter.h" +#include "opentelemetry/logs/provider.h" +#include "opentelemetry/sdk/logs/logger_provider_factory.h" +#include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" + +#include +#include + +#include "foo_library.h" + +namespace logs_api = opentelemetry::logs; +namespace logs_sdk = opentelemetry::sdk::logs; +namespace user_events_logs = opentelemetry::exporter::user_events::logs; + +namespace +{ + +void InitLogger() +{ + // Create user_events log exporter instance + auto exporter_options = user_events_logs::ExporterOptions(); + auto exporter = + std::unique_ptr(new user_events_logs::Exporter(exporter_options)); + auto processor = logs_sdk::SimpleLogRecordProcessorFactory::Create(std::move(exporter)); + std::shared_ptr provider( + logs_sdk::LoggerProviderFactory::Create(std::move(processor))); + + // Set the global logger provider + logs_api::Provider::SetLoggerProvider(provider); +} + +void CleanupLogger() +{ + std::shared_ptr none; + logs_api::Provider::SetLoggerProvider(none); +} + +} // namespace + +using namespace std; + +int i = 0; +std::string get_fruit_name_from_customer() +{ + static int i = 0; + + if (i++ % 2 == 0) + { + return "strawberry"; + } + else + { + return "apple"; + } +} + +int main() +{ + InitLogger(); + + while (true) + { + string fruit_name = get_fruit_name_from_customer(); + + sell_fruit(fruit_name); + + this_thread::sleep_for(chrono::seconds(3)); + } + + CleanupLogger(); +} diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h new file mode 100644 index 000000000..f8dbec128 --- /dev/null +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include "exporter_options.h" +# include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/sdk/logs/exporter.h" + +# include +# include +# include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace logs +{ + +namespace sdk_logs = opentelemetry::sdk::logs; + +/** + * The user_events logs exporter exports logs data to Geneva + */ +class Exporter final : public opentelemetry::sdk::logs::LogRecordExporter +{ +public: + Exporter(const ExporterOptions &options) noexcept; + + /** + * Exports a span of logs sent from the processor. + */ + + std::unique_ptr MakeRecordable() noexcept override; + + opentelemetry::sdk::common::ExportResult Export( + const opentelemetry::nostd::span> &records) noexcept + override; + + bool Shutdown( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; + + bool isShutdown() const noexcept; + +private: + const ExporterOptions options_; + bool is_shutdown_ = false; + mutable opentelemetry::common::SpinLockMutex lock_; + + ehd::Provider provider_{"opentelemetry_logs"}; + std::array, 6> event_set_levels_ = { + provider_.RegisterSet(static_cast(6), 1), + provider_.RegisterSet(event_level_verbose, 1), + provider_.RegisterSet(event_level_information, 1), + provider_.RegisterSet(event_level_warning, 1), + provider_.RegisterSet(event_level_error, 1), + provider_.RegisterSet(event_level_critical_error, 1)}; + +}; // class Exporter + +} // namespace logs +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE + +#endif \ No newline at end of file diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h new file mode 100644 index 000000000..ae9042b01 --- /dev/null +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h @@ -0,0 +1,26 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace logs +{ + +struct ExporterOptions +{}; +} // namespace logs +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE + +#endif \ No newline at end of file diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h new file mode 100644 index 000000000..7a477c676 --- /dev/null +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h @@ -0,0 +1,131 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/logs/recordable.h" +# include "opentelemetry/version.h" +# include "utils.h" + +# include +# include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace logs +{ + +class Recordable final : public opentelemetry::sdk::logs::Recordable +{ +public: + ehd::EventBuilder &GetEventBuilder() noexcept { return event_builder_; } + + int GetLevelIndex() noexcept { return level_index_; } + + bool PrepareExport() noexcept; + + /** + * Construct a new Recordable object + * + */ + Recordable() noexcept; + /** + * Set the severity for this log. + * @param severity the severity of the event + */ + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override; + + /** + * Set name for this log + * @param name the name to set + */ + void SetName(nostd::string_view name) noexcept; + + /** + * Set body field for this log. + * @param message the body to set + */ + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override; + + /** + * Set event id for this log. + * @param id the id to set + * @param name the name to set + */ + void SetEventId(int64_t id, nostd::string_view name) noexcept override; + + /** + * Set a resource for this log. + * @param Resource the resource to set + */ + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override { + } // Not Supported + + /** + * Set an attribute of a log. + * @param key the key of the attribute + * @param value the attribute value + */ + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override; + + /** + * Set trace id for this log. + * @param trace_id the trace id to set + */ + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override; + + /** + * Set span id for this log. + * @param span_id the span id to set + */ + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override; + + /** + * Inject a trace_flags for this log. + * @param trace_flags the span id to set + */ + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override { + } // Not Supported + + /** + * Set the timestamp for this log. + * @param timestamp the timestamp of the event + */ + void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + + /** + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetObservedTimestamp(common::SystemTimestamp timestamp) noexcept override {} + + /** + * Set instrumentation_scope for this log. + * @param instrumentation_scope the instrumentation scope to set + */ + void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept override + {} // Not Supported + +private: + ehd::EventBuilder event_builder_; + int level_index_; + size_t cs_part_b_bookmark_ = 0; + size_t cs_part_b_bookmark_size_ = 0; + size_t cs_part_c_bookmark_ = 0; + size_t cs_part_c_bookmark_size_ = 0; +}; + +} // namespace logs +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE + +#endif // ENABLE_LOGS_PREVIEW diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/utils.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/utils.h new file mode 100644 index 000000000..917864592 --- /dev/null +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/utils.h @@ -0,0 +1,28 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/version.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace utils +{ + +namespace api_common = opentelemetry::common; + +void PopulateAttribute(nostd::string_view key, + const api_common::AttributeValue &value, + ehd::EventBuilder &event_builder) noexcept; + +} // namespace utils +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/user_events/src/logs_exporter.cc b/exporters/user_events/src/logs_exporter.cc new file mode 100644 index 000000000..7121f5cf5 --- /dev/null +++ b/exporters/user_events/src/logs_exporter.cc @@ -0,0 +1,96 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/exporters/user_events/logs/exporter.h" +# include "opentelemetry/exporters/user_events/logs/recordable.h" +# include "opentelemetry/sdk_config.h" + +namespace nostd = opentelemetry::nostd; +namespace sdklogs = opentelemetry::sdk::logs; +namespace sdkcommon = opentelemetry::sdk::common; + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace logs +{ + +/*********************** Constructor ***********************/ + +Exporter::Exporter(const ExporterOptions &options) noexcept : options_(options) {} + +/*********************** Exporter methods ***********************/ + +std::unique_ptr Exporter::MakeRecordable() noexcept +{ + return std::unique_ptr(new Recordable()); +} + +sdk::common::ExportResult Exporter::Export( + const nostd::span> &records) noexcept +{ + if (isShutdown()) + { + OTEL_INTERNAL_LOG_ERROR("[user_events Log Exporter] Exporting " + << records.size() << " log(s) failed, exporter is shutdown"); + return sdk::common::ExportResult::kFailure; + } + + int err; + + for (auto &record : records) + { + auto user_events_record = + std::unique_ptr(static_cast(record.release())); + + user_events_record->PrepareExport(); + + // assert(user_events_record != nullptr, "Recordable is null"); + + int level_index = user_events_record->GetLevelIndex(); + + auto event_set = event_set_levels_[level_index]; + + if (event_set->Enabled()) + { + err = user_events_record->GetEventBuilder().Write(*event_set_levels_[level_index]); + } + else + { + // event_set is not enabled + err = 0; + } + + if (err != 0) + { + OTEL_INTERNAL_LOG_ERROR("[user_events Log Exporter] Exporting failed, error code: " << err); + return sdk::common::ExportResult::kFailure; + } + } + + return sdk::common::ExportResult::kSuccess; +} + +bool Exporter::Shutdown(std::chrono::microseconds) noexcept +{ + const std::lock_guard locked(lock_); + is_shutdown_ = true; + return true; +} + +bool Exporter::isShutdown() const noexcept +{ + const std::lock_guard locked(lock_); + return is_shutdown_; +} + +} // namespace logs +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE + +#endif \ No newline at end of file diff --git a/exporters/user_events/src/recordable.cc b/exporters/user_events/src/recordable.cc new file mode 100644 index 000000000..69bfaad1f --- /dev/null +++ b/exporters/user_events/src/recordable.cc @@ -0,0 +1,115 @@ +/// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/user_events/logs/recordable.h" +#include "opentelemetry/sdk/common/global_log_handler.h" + +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace logs +{ + +namespace api_logs = opentelemetry::logs; + +Recordable::Recordable() noexcept +{ + event_builder_.Reset("OpenTelemetry-Logs"); + + utils::PopulateAttribute("__csver__", static_cast(0x400), event_builder_); +} + +void Recordable::SetSeverity(api_logs::Severity severity) noexcept +{ + uint8_t severity_value = static_cast(severity); + if (severity_value == 0 || severity_value > 24) + { + // TODO: log error + OTEL_INTERNAL_LOG_ERROR( + "[user_events Log Exporter] Recordable: invalid severity value: " << severity_value); + severity_value = 1; + } + + level_index_ = (severity_value - 1) >> 2; + + cs_part_b_bookmark_size_ += 2; + event_builder_.AddValue("severityNumber", static_cast(severity_value), + event_field_format_default); + event_builder_.AddString( + "severityText", api_logs::SeverityNumToText[static_cast(severity_value)].data(), + event_field_format_default); +} + +void Recordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept +{ + // Set intial bookmark size to 1 for body below. + cs_part_b_bookmark_size_++; + event_builder_.AddStruct("PartB", 1, 0, &cs_part_b_bookmark_); + utils::PopulateAttribute("body", message, event_builder_); +} + +void Recordable::SetEventId(int64_t id, nostd::string_view name) noexcept +{ + cs_part_b_bookmark_size_++; + utils::PopulateAttribute("eventId", id, event_builder_); + if (!name.empty()) + { + cs_part_b_bookmark_size_++; + utils::PopulateAttribute("name", name, event_builder_); + } +} + +void Recordable::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept +{ + // TODO: implement +} + +void Recordable::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept +{ + // TODO: implement +} + +// +// Attributes should be set consecutively without other fields, so we can use the bookmark to do +// backpatching. +// +void Recordable::SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept +{ + if (cs_part_c_bookmark_size_ == 0) + { + event_builder_.AddStruct("PartC", 1, 0, &cs_part_c_bookmark_); + } + + cs_part_c_bookmark_size_++; + utils::PopulateAttribute(key, value, event_builder_); +} + +void Recordable::SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + // TODO: convert to nanoseconds +} + +bool Recordable::PrepareExport() noexcept +{ + if (cs_part_b_bookmark_size_ > 0) + { + event_builder_.SetStructFieldCount(cs_part_b_bookmark_, cs_part_b_bookmark_size_); + } + if (cs_part_c_bookmark_size_ > 0) + { + event_builder_.SetStructFieldCount(cs_part_c_bookmark_, cs_part_c_bookmark_size_); + } + + return true; +} + +} // namespace logs +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/user_events/src/utils.cc b/exporters/user_events/src/utils.cc new file mode 100644 index 000000000..a3d2f3b49 --- /dev/null +++ b/exporters/user_events/src/utils.cc @@ -0,0 +1,87 @@ + +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/user_events/logs/utils.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace exporter +{ +namespace user_events +{ +namespace utils +{ + +namespace api_common = opentelemetry::common; + +const int kAttributeValueSize = 16; + +void PopulateAttribute(nostd::string_view key, + const api_common::AttributeValue &value, + ehd::EventBuilder &event_builder) noexcept +{ + static_assert(nostd::variant_size::value == kAttributeValueSize, + "AttributeValue has changed, update PopulateAttributeValue"); + + const char *key_name = key.data(); + + if (nostd::holds_alternative(value)) + { + event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + } + else if (nostd::holds_alternative(value)) + { + event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + } + else if (nostd::holds_alternative(value)) + { + event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + } + else if (nostd::holds_alternative(value)) + { + event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + } + else if (nostd::holds_alternative(value)) + { + event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + } + else if (nostd::holds_alternative(value), event_field_format_default) + { + event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + } + else if (nostd::holds_alternative(value)) + { + event_builder.AddString(key_name, nostd::get(value), + event_field_format_default); + } + else if (nostd::holds_alternative(value)) + { + event_builder.AddString(key_name, nostd::get(value).data(), + event_field_format_default); + } + else if (nostd::holds_alternative>(value)) + { + // TODO: implement + } + else if (nostd::holds_alternative>(value)) + {} + else if (nostd::holds_alternative>(value)) + {} + else if (nostd::holds_alternative>(value)) + {} + else if (nostd::holds_alternative>(value)) + {} + else if (nostd::holds_alternative>(value)) + {} + else if (nostd::holds_alternative>(value)) + {} + else if (nostd::holds_alternative>(value)) + {} +} + +} // namespace utils +} // namespace user_events +} // namespace exporter + +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/user_events/test/logs_exporter_test.cc b/exporters/user_events/test/logs_exporter_test.cc new file mode 100644 index 000000000..97b2388c3 --- /dev/null +++ b/exporters/user_events/test/logs_exporter_test.cc @@ -0,0 +1,35 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include +# include +# include + +# include "opentelemetry/exporters/user_events/logs/exporter.h" + +# include + +namespace sdk_logs = opentelemetry::sdk::logs; +namespace user_events_logs = opentelemetry::exporter::user_events::logs; + +// Test that when OStream Log exporter is shutdown, no logs should be sent to stream +TEST(UserEventsLogRecordExporter, Shutdown) +{ + auto options = user_events_logs::ExporterOptions(); + auto exporter = + std::unique_ptr(new user_events_logs::Exporter(options)); + + // Save cout's original buffer here + std::streambuf *original = std::cout.rdbuf(); + + // Redirect cout to our stringstream buffer + std::stringstream output; + std::cout.rdbuf(output.rdbuf()); + + EXPECT_TRUE(exporter->Shutdown()); +} + +#endif \ No newline at end of file diff --git a/exporters/user_events/third_party/LinuxTracepoints b/exporters/user_events/third_party/LinuxTracepoints new file mode 160000 index 000000000..0561e730f --- /dev/null +++ b/exporters/user_events/third_party/LinuxTracepoints @@ -0,0 +1 @@ +Subproject commit 0561e730f84e56f2c0f5e9eec108f516e8d0ef88 From 5474b9990a112b51d4ea37fe35b3d777bb24f0d6 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 2 Jun 2023 09:46:20 -0700 Subject: [PATCH 58/77] Add Dockerfile for building user_events exporter (#288) --- exporters/user_events/CMakeLists.txt | 4 ++ exporters/user_events/Docker/Dockerfile | 60 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 exporters/user_events/Docker/Dockerfile diff --git a/exporters/user_events/CMakeLists.txt b/exporters/user_events/CMakeLists.txt index f6fcac5c9..6ab0c3b7f 100644 --- a/exporters/user_events/CMakeLists.txt +++ b/exporters/user_events/CMakeLists.txt @@ -20,6 +20,10 @@ endif() add_definitions(-DHAVE_CONSOLE_LOG -DENABLE_LOGS_PREVIEW) if(MAIN_PROJECT) + # TODO: cleanup the dependent packages + find_package(protobuf REQUIRED) + find_package(CURL REQUIRED) + find_package(nlohmann_json REQUIRED) find_package(opentelemetry-cpp REQUIRED) endif() diff --git a/exporters/user_events/Docker/Dockerfile b/exporters/user_events/Docker/Dockerfile new file mode 100644 index 000000000..6356ed3e3 --- /dev/null +++ b/exporters/user_events/Docker/Dockerfile @@ -0,0 +1,60 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +FROM ubuntu:latest +ENV DEBIAN_FRONTEND=noninteractive + +WORKDIR /work + +RUN apt update && apt install -y \ + build-essential \ + cmake \ + git \ + ninja-build \ + protobuf-compiler \ + libcurl4-openssl-dev \ + libgtest-dev + +RUN cd /work && git clone --recursive --depth=1 https://github.com/google/googletest.git && \ + cd googletest && mkdir build && cd build && \ + cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug .. && \ + ninja && ninja install + +RUN cd /work && \ + git clone --recursive --depth=1 https://github.com/google/benchmark.git && \ + cd benchmark && mkdir out && cd out && \ + cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug -D BENCHMARK_DOWNLOAD_DEPENDENCIES=on .. && \ + ninja && \ + ninja install + +RUN cd /work && \ + git clone --recursive --depth=1 https://github.com/nlohmann/json.git && \ + cd json && mkdir build && cd build && \ + cmake -G Ninja .. && \ + ninja && \ + ninja install + +RUN cd /work && \ + git clone --recursive --depth=1 https://github.com/open-telemetry/opentelemetry-cpp.git && \ + cd opentelemetry-cpp && \ + mkdir build && cd build && \ + cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug -D BUILD_TESTING=0 -D WITH_OTLP_HTTP=1 -D WITH_OTLP_GRPC=0 -D WITH_LOGS_PREVIEW=1 .. && \ + ninja && \ + ninja install + +RUN cd /work && \ + git clone --recursive --depth=1 https://github.com/protocolbuffers/protobuf.git && \ + cd protobuf && mkdir build && cd build && \ + cmake -G Ninja -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_EXAMPLES=OFF .. && \ + ninja && \ + ninja install + +RUN cd /work && \ + git clone --recursive --depth=1 https://github.com/open-telemetry/opentelemetry-cpp-contrib + +RUN cd /work && \ + cd opentelemetry-cpp-contrib/exporters/user_events && \ + mkdir build && cd build && \ + cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug .. && \ + ninja && \ + ninja install \ No newline at end of file From 05b20a304ef17f13185bfe3639f94c36eff7ceb6 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Tue, 6 Jun 2023 16:10:31 -0700 Subject: [PATCH 59/77] [user_events exporter] Fix event_field_format_ flag in PopulateAttribute (#292) --- exporters/user_events/CMakeLists.txt | 2 +- exporters/user_events/Docker/Dockerfile | 9 +-- .../exporters/user_events/logs/exporter.h | 2 +- exporters/user_events/src/utils.cc | 78 ++++++++++++++++--- 4 files changed, 69 insertions(+), 22 deletions(-) diff --git a/exporters/user_events/CMakeLists.txt b/exporters/user_events/CMakeLists.txt index 6ab0c3b7f..f09e8f5a7 100644 --- a/exporters/user_events/CMakeLists.txt +++ b/exporters/user_events/CMakeLists.txt @@ -21,7 +21,7 @@ add_definitions(-DHAVE_CONSOLE_LOG -DENABLE_LOGS_PREVIEW) if(MAIN_PROJECT) # TODO: cleanup the dependent packages - find_package(protobuf REQUIRED) + find_package(Protobuf REQUIRED) find_package(CURL REQUIRED) find_package(nlohmann_json REQUIRED) find_package(opentelemetry-cpp REQUIRED) diff --git a/exporters/user_events/Docker/Dockerfile b/exporters/user_events/Docker/Dockerfile index 6356ed3e3..7d6347a88 100644 --- a/exporters/user_events/Docker/Dockerfile +++ b/exporters/user_events/Docker/Dockerfile @@ -42,13 +42,6 @@ RUN cd /work && \ ninja && \ ninja install -RUN cd /work && \ - git clone --recursive --depth=1 https://github.com/protocolbuffers/protobuf.git && \ - cd protobuf && mkdir build && cd build && \ - cmake -G Ninja -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_EXAMPLES=OFF .. && \ - ninja && \ - ninja install - RUN cd /work && \ git clone --recursive --depth=1 https://github.com/open-telemetry/opentelemetry-cpp-contrib @@ -57,4 +50,4 @@ RUN cd /work && \ mkdir build && cd build && \ cmake -G Ninja -D CMAKE_BUILD_TYPE=Debug .. && \ ninja && \ - ninja install \ No newline at end of file + ninja install diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h index f8dbec128..d69eb580f 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h @@ -29,7 +29,7 @@ namespace sdk_logs = opentelemetry::sdk::logs; class Exporter final : public opentelemetry::sdk::logs::LogRecordExporter { public: - Exporter(const ExporterOptions &options) noexcept; + explicit Exporter(const ExporterOptions &options) noexcept; /** * Exports a span of logs sent from the processor. diff --git a/exporters/user_events/src/utils.cc b/exporters/user_events/src/utils.cc index a3d2f3b49..cbe539e78 100644 --- a/exporters/user_events/src/utils.cc +++ b/exporters/user_events/src/utils.cc @@ -17,6 +17,27 @@ namespace api_common = opentelemetry::common; const int kAttributeValueSize = 16; +// +// Iterator which convers "nostd::string_view *" to "std::string_view *". +// This is needed to pass a span of "nostd::string_view" to EventBuilder::AddStringRange. +// +struct StringViewIterator +{ + const nostd::string_view *m_ptr; + explicit StringViewIterator(const nostd::string_view *ptr) noexcept : m_ptr(ptr) {} + bool operator==(StringViewIterator other) const noexcept { return m_ptr == other.m_ptr; } + bool operator!=(StringViewIterator other) const noexcept { return m_ptr != other.m_ptr; } + const std::string_view operator*() const noexcept + { + return std::string_view(m_ptr->data(), m_ptr->size()); + } + StringViewIterator &operator++() noexcept + { + m_ptr += 1; + return *this; + } +}; + void PopulateAttribute(nostd::string_view key, const api_common::AttributeValue &value, ehd::EventBuilder &event_builder) noexcept @@ -26,17 +47,19 @@ void PopulateAttribute(nostd::string_view key, const char *key_name = key.data(); + // TODO: implement this with a visitor + if (nostd::holds_alternative(value)) { - event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + event_builder.AddValue(key_name, nostd::get(value), event_field_format_boolean); } else if (nostd::holds_alternative(value)) { - event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + event_builder.AddValue(key_name, nostd::get(value), event_field_format_signed_int); } else if (nostd::holds_alternative(value)) { - event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + event_builder.AddValue(key_name, nostd::get(value), event_field_format_signed_int); } else if (nostd::holds_alternative(value)) { @@ -48,7 +71,7 @@ void PopulateAttribute(nostd::string_view key, } else if (nostd::holds_alternative(value), event_field_format_default) { - event_builder.AddValue(key_name, nostd::get(value), event_field_format_default); + event_builder.AddValue(key_name, nostd::get(value), event_field_format_float); } else if (nostd::holds_alternative(value)) { @@ -62,22 +85,53 @@ void PopulateAttribute(nostd::string_view key, } else if (nostd::holds_alternative>(value)) { - // TODO: implement + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_default); } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_signed_int); + } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_signed_int); + } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_default); + } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_default); + } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_float); + } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddValueRange(key_name, value_span.begin(), value_span.end(), + event_field_format_boolean); + } else if (nostd::holds_alternative>(value)) - {} + { + auto value_span = nostd::get>(value); + event_builder.AddStringRange(key_name, StringViewIterator(value_span.data()), + StringViewIterator(value_span.data() + value_span.size()), + event_field_format_default); + } } } // namespace utils From 49d5efb7fe4845e34a1f20f842f23bbf7127ced1 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 30 Jun 2023 11:38:46 -0700 Subject: [PATCH 60/77] Initial metrics exporter targeting user_events (#291) --- exporters/user_events/.vscode/settings.json | 83 ++++++++++++ exporters/user_events/CMakeLists.txt | 49 +++++-- .../user_events/benchmark/logger_benchmark.cc | 1 + .../example/{ => logs}/foo_library.cc | 0 .../example/{ => logs}/foo_library.h | 0 .../user_events/example/{ => logs}/main.cc | 1 + .../example/metrics/foo_library.cc | 93 +++++++++++++ .../user_events/example/metrics/foo_library.h | 12 ++ exporters/user_events/example/metrics/main.cc | 123 ++++++++++++++++++ .../exporters/user_events/logs/exporter.h | 2 +- .../exporters/user_events/logs/recordable.h | 2 + .../exporters/user_events/metrics/exporter.h | 76 +++++++++++ .../user_events/metrics/exporter_options.h | 27 ++++ exporters/user_events/src/metrics_exporter.cc | 109 ++++++++++++++++ exporters/user_events/src/recordable.cc | 12 +- 15 files changed, 568 insertions(+), 22 deletions(-) create mode 100644 exporters/user_events/.vscode/settings.json rename exporters/user_events/example/{ => logs}/foo_library.cc (100%) rename exporters/user_events/example/{ => logs}/foo_library.h (100%) rename exporters/user_events/example/{ => logs}/main.cc (97%) create mode 100644 exporters/user_events/example/metrics/foo_library.cc create mode 100644 exporters/user_events/example/metrics/foo_library.h create mode 100644 exporters/user_events/example/metrics/main.cc create mode 100644 exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter.h create mode 100644 exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h create mode 100644 exporters/user_events/src/metrics_exporter.cc diff --git a/exporters/user_events/.vscode/settings.json b/exporters/user_events/.vscode/settings.json new file mode 100644 index 000000000..49d7fe002 --- /dev/null +++ b/exporters/user_events/.vscode/settings.json @@ -0,0 +1,83 @@ +{ + "files.associations": { + "memory": "cpp", + "mutex": "cpp", + "xstring": "cpp", + "atomic": "cpp", + "bit": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "exception": "cpp", + "list": "cpp", + "map": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "initializer_list": "cpp", + "ios": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "iterator": "cpp", + "limits": "cpp", + "new": "cpp", + "optional": "cpp", + "ostream": "cpp", + "ratio": "cpp", + "shared_mutex": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "system_error": "cpp", + "thread": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "typeinfo": "cpp", + "utility": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocinfo": "cpp", + "xlocnum": "cpp", + "xmemory": "cpp", + "xstddef": "cpp", + "xtr1common": "cpp", + "xtree": "cpp", + "xutility": "cpp", + "chrono": "cpp", + "algorithm": "cpp", + "array": "cpp", + "charconv": "cpp", + "forward_list": "cpp", + "format": "cpp", + "functional": "cpp", + "iomanip": "cpp", + "locale": "cpp", + "sstream": "cpp", + "xlocbuf": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xloctime": "cpp" + }, + "files.exclude": { + "**/.git": true, + "**/.svn": true, + "**/.hg": true, + "**/CVS": true, + "**/.DS_Store": true, + "**/Thumbs.db": true + "out/": true, + } +} \ No newline at end of file diff --git a/exporters/user_events/CMakeLists.txt b/exporters/user_events/CMakeLists.txt index f09e8f5a7..0b83ec0ff 100644 --- a/exporters/user_events/CMakeLists.txt +++ b/exporters/user_events/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if(WIN32) - message(FATAL_ERROR "user_events is Linux only for now") + message(FATAL_ERROR "user_events exporter is Linux only for now") endif() option(BUILD_EXAMPLE "Build example" ON) @@ -12,13 +12,12 @@ option(BUILD_TESTING "Build tests" ON) set(MAIN_PROJECT OFF) +project(opentelemetry-user_events-exporter) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) - project(opentelemetry-userevents-logs) set(MAIN_PROJECT ON) + message(STATUS "${PROJECT_NAME} is main project") endif() -add_definitions(-DHAVE_CONSOLE_LOG -DENABLE_LOGS_PREVIEW) - if(MAIN_PROJECT) # TODO: cleanup the dependent packages find_package(Protobuf REQUIRED) @@ -34,6 +33,9 @@ include_directories(include) add_library(opentelemetry_exporter_user_events_logs src/logs_exporter.cc src/recordable.cc src/utils.cc) +target_compile_definitions(opentelemetry_exporter_user_events_logs + PUBLIC HAVE_CONSOLE_LOG HAVE_LOGS_PREVIEW) + if(MAIN_PROJECT) target_include_directories(opentelemetry_exporter_user_events_logs PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) @@ -51,14 +53,33 @@ target_link_libraries(opentelemetry_exporter_user_events_logs set_target_properties(opentelemetry_exporter_user_events_logs PROPERTIES EXPORT_NAME logs) -if(BUILD_EXAMPLE) +add_library(opentelemetry_exporter_user_events_metrics src/metrics_exporter.cc) - add_executable(user_events_logs example/main.cc example/foo_library.cc) +if(MAIN_PROJECT) + target_include_directories(opentelemetry_exporter_user_events_metrics + PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) target_link_libraries( - user_events_logs ${CMAKE_THREAD_LIBS_INIT} opentelemetry_logs - opentelemetry_exporter_user_events_logs) + opentelemetry_exporter_user_events_metrics + PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES} tracepoint protobuf::libprotobuf) + # TODO: link to opentelemetry_otlp_recordable +else() + target_link_libraries( + opentelemetry_exporter_user_events_metrics + PUBLIC opentelemetry_metrics opentelemetry_resources opentelemetry_common + opentelemetry_otlp_recordable tracepoint) +endif() -endif(BUILD_EXAMPLE) +if(BUILD_EXAMPLE) + add_executable(user_events_logs example/logs/main.cc + example/logs/foo_library.cc) + target_link_libraries(user_events_logs ${CMAKE_THREAD_LIBS_INIT} + opentelemetry_exporter_user_events_logs) + + add_executable(user_events_metrics example/metrics/main.cc + example/metrics/foo_library.cc) + target_link_libraries(user_events_metrics ${CMAKE_THREAD_LIBS_INIT} + opentelemetry_exporter_user_events_metrics) +endif() if(BUILD_TESTING) if(EXISTS ${CMAKE_BINARY_DIR}/lib/libgtest.a) @@ -79,15 +100,15 @@ if(BUILD_TESTING) enable_testing() include(GoogleTest) # build tests for user_events logs - add_executable(userevents_logs_exporter_test test/logs_exporter_test.cc) + add_executable(user_events_logs_exporter_test test/logs_exporter_test.cc) target_link_libraries( - userevents_logs_exporter_test ${GTEST_BOTH_LIBRARIES} + user_events_logs_exporter_test ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} opentelemetry_exporter_user_events_logs) gtest_add_tests( - TARGET userevents_logs_exporter_test + TARGET user_events_logs_exporter_test TEST_PREFIX exporter. - TEST_LIST userevents_logs_exporter_test) + TEST_LIST user_events_logs_exporter_test) endif() find_package(benchmark CONFIG REQUIRED) @@ -105,7 +126,7 @@ install( ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) install( - DIRECTORY include/opentelemetry/exporters/userevents + DIRECTORY include/opentelemetry/exporters/user_events DESTINATION include/opentelemetry/exporters FILES_MATCHING PATTERN "*.h") diff --git a/exporters/user_events/benchmark/logger_benchmark.cc b/exporters/user_events/benchmark/logger_benchmark.cc index d45741f65..3a54d10ec 100644 --- a/exporters/user_events/benchmark/logger_benchmark.cc +++ b/exporters/user_events/benchmark/logger_benchmark.cc @@ -11,6 +11,7 @@ # include "opentelemetry/exporters/user_events/logs/exporter.h" # include "opentelemetry/logs/provider.h" # include "opentelemetry/sdk/logs/logger_provider_factory.h" +# include "opentelemetry/sdk/logs/processor.h" # include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" # include diff --git a/exporters/user_events/example/foo_library.cc b/exporters/user_events/example/logs/foo_library.cc similarity index 100% rename from exporters/user_events/example/foo_library.cc rename to exporters/user_events/example/logs/foo_library.cc diff --git a/exporters/user_events/example/foo_library.h b/exporters/user_events/example/logs/foo_library.h similarity index 100% rename from exporters/user_events/example/foo_library.h rename to exporters/user_events/example/logs/foo_library.h diff --git a/exporters/user_events/example/main.cc b/exporters/user_events/example/logs/main.cc similarity index 97% rename from exporters/user_events/example/main.cc rename to exporters/user_events/example/logs/main.cc index f0c2cf1ed..f96c8af37 100644 --- a/exporters/user_events/example/main.cc +++ b/exporters/user_events/example/logs/main.cc @@ -4,6 +4,7 @@ #include "opentelemetry/exporters/user_events/logs/exporter.h" #include "opentelemetry/logs/provider.h" #include "opentelemetry/sdk/logs/logger_provider_factory.h" +#include "opentelemetry/sdk/logs/processor.h" #include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" #include diff --git a/exporters/user_events/example/metrics/foo_library.cc b/exporters/user_events/example/metrics/foo_library.cc new file mode 100644 index 000000000..2ece3d87d --- /dev/null +++ b/exporters/user_events/example/metrics/foo_library.cc @@ -0,0 +1,93 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "foo_library.h" +#include "opentelemetry/context/context.h" +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/nostd/shared_ptr.h" +#include +#include +#include +#include +#include + +namespace nostd = opentelemetry::nostd; +namespace metrics_api = opentelemetry::metrics; + +namespace { + +std::map get_random_attr() { + static const std::vector> labels = { + {"key1", "value1"}, + {"key2", "value2"}, + {"key3", "value3"}, + {"key4", "value4"}, + {"key5", "value5"}}; + return std::map{ + labels[rand() % (labels.size() - 1)], + labels[rand() % (labels.size() - 1)]}; +} + +class MeasurementFetcher { +public: + static void Fetcher(opentelemetry::metrics::ObserverResult observer_result, + void *state) { + std::map labels = get_random_attr(); + auto labelkv = + opentelemetry::common::KeyValueIterableView{labels}; + if (nostd::holds_alternative< + nostd::shared_ptr>>( + observer_result)) { + double val = (rand() % 700) + 1.1; + nostd::get< + nostd::shared_ptr>>( + observer_result) + ->Observe(val /*, labelkv */); + } + } +}; +} // namespace + +void FooLibrary::counter_example(const std::string &name) { + std::string counter_name = name + "_counter"; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = + provider->GetMeter(name, "1.2.0"); + auto double_counter = meter->CreateDoubleCounter(counter_name); + + while (true) { + double val = (rand() % 700) + 1.1; + double_counter->Add(val); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } +} + +void FooLibrary::observable_counter_example(const std::string &name) { + std::string counter_name = name + "_observable_counter"; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = + provider->GetMeter(name, "1.2.0"); + auto counter = meter->CreateDoubleObservableCounter(counter_name); + counter->AddCallback(MeasurementFetcher::Fetcher, nullptr); + std::this_thread::sleep_until( + std::chrono::system_clock::now() + + std::chrono::hours(std::numeric_limits::max())); +} + +void FooLibrary::histogram_example(const std::string &name) { + std::string histogram_name = name + "_histogram"; + auto provider = metrics_api::Provider::GetMeterProvider(); + nostd::shared_ptr meter = + provider->GetMeter(name, "1.2.0"); + auto histogram_counter = + meter->CreateDoubleHistogram(histogram_name, "des", "unit"); + auto context = opentelemetry::context::Context{}; + while (true) { + double val = (rand() % 700) + 1.1; + std::map labels = get_random_attr(); + auto labelkv = + opentelemetry::common::KeyValueIterableView{labels}; + histogram_counter->Record(val, labelkv, context); + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } +} diff --git a/exporters/user_events/example/metrics/foo_library.h b/exporters/user_events/example/metrics/foo_library.h new file mode 100644 index 000000000..bc625f13c --- /dev/null +++ b/exporters/user_events/example/metrics/foo_library.h @@ -0,0 +1,12 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#include + +class FooLibrary { +public: + static void counter_example(const std::string &name); + static void histogram_example(const std::string &name); + static void observable_counter_example(const std::string &name); +}; diff --git a/exporters/user_events/example/metrics/main.cc b/exporters/user_events/example/metrics/main.cc new file mode 100644 index 000000000..406a8ae06 --- /dev/null +++ b/exporters/user_events/example/metrics/main.cc @@ -0,0 +1,123 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/user_events/metrics/exporter.h" +#include "opentelemetry/metrics/provider.h" +#include "opentelemetry/sdk/metrics/aggregation/default_aggregation.h" +#include "opentelemetry/sdk/metrics/aggregation/histogram_aggregation.h" +#include "opentelemetry/sdk/metrics/export/periodic_exporting_metric_reader.h" +#include "opentelemetry/sdk/metrics/meter.h" +#include "opentelemetry/sdk/metrics/meter_provider.h" +#include +#include + +#include "foo_library.h" + +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace nostd = opentelemetry::nostd; +namespace common = opentelemetry::common; +namespace user_events_exporter = opentelemetry::exporter::user_events::metrics; +namespace metrics_api = opentelemetry::metrics; + +namespace { + +void initMetrics(const std::string &name, const std::string &account_name) { + + user_events_exporter::ExporterOptions options{}; + std::unique_ptr exporter{ + new user_events_exporter::Exporter(options)}; + + std::string version{"1.2.0"}; + std::string schema{"https://opentelemetry.io/schemas/1.2.0"}; + + // Initialize and set the global MeterProvider + metric_sdk::PeriodicExportingMetricReaderOptions reader_options; + reader_options.export_interval_millis = std::chrono::milliseconds(1000); + reader_options.export_timeout_millis = std::chrono::milliseconds(500); + std::unique_ptr reader{ + new metric_sdk::PeriodicExportingMetricReader(std::move(exporter), + reader_options)}; + auto provider = std::shared_ptr( + new metric_sdk::MeterProvider()); + auto p = std::static_pointer_cast(provider); + p->AddMetricReader(std::move(reader)); + + // counter view + std::string counter_name = name + "_counter"; + std::unique_ptr instrument_selector{ + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, + counter_name)}; + std::unique_ptr meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr sum_view{new metric_sdk::View{ + name, "description", metric_sdk::AggregationType::kSum}}; + p->AddView(std::move(instrument_selector), std::move(meter_selector), + std::move(sum_view)); + + // observable counter view + std::string observable_counter_name = name + "_observable_counter"; + std::unique_ptr + observable_instrument_selector{new metric_sdk::InstrumentSelector( + metric_sdk::InstrumentType::kObservableCounter, + observable_counter_name)}; + std::unique_ptr observable_meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::unique_ptr observable_sum_view{new metric_sdk::View{ + name, "description", metric_sdk::AggregationType::kSum}}; + p->AddView(std::move(observable_instrument_selector), + std::move(observable_meter_selector), + std::move(observable_sum_view)); + + // histogram view + std::string histogram_name = name + "_histogram"; + std::unique_ptr histogram_instrument_selector{ + new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kHistogram, + histogram_name)}; + std::unique_ptr histogram_meter_selector{ + new metric_sdk::MeterSelector(name, version, schema)}; + std::shared_ptr + aggregation_config{ + new opentelemetry::sdk::metrics::HistogramAggregationConfig()}; + static_cast( + aggregation_config.get()) + ->boundaries_ = std::vector{0.0, 50.0, 100.0, 250.0, 500.0, + 750.0, 1000.0, 2500.0, 5000.0, 10000.0}; + std::unique_ptr histogram_view{new metric_sdk::View{ + name, "description", metric_sdk::AggregationType::kHistogram, + aggregation_config}}; + p->AddView(std::move(histogram_instrument_selector), + std::move(histogram_meter_selector), std::move(histogram_view)); + metrics_api::Provider::SetMeterProvider(provider); +} +} // namespace + +int main(int argc, char **argv) { + std::string account_name = "TestAccount"; + std::string example_type; + if (argc >= 2) { + account_name = argv[1]; + if (argc >= 3) { + example_type = argv[2]; + } + } + + std::string name{"ostream_metric_example"}; + initMetrics(name, account_name); + + if (example_type == "counter") { + FooLibrary::counter_example(name); + } else if (example_type == "observable_counter") { + FooLibrary::observable_counter_example(name); + } else if (example_type == "histogram") { + FooLibrary::histogram_example(name); + } else { + std::thread counter_example{&FooLibrary::counter_example, name}; + std::thread observable_counter_example{ + &FooLibrary::observable_counter_example, name}; + std::thread histogram_example{&FooLibrary::histogram_example, name}; + + counter_example.join(); + observable_counter_example.join(); + histogram_example.join(); + } +} diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h index d69eb580f..3cb4e27f8 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h @@ -24,7 +24,7 @@ namespace logs namespace sdk_logs = opentelemetry::sdk::logs; /** - * The user_events logs exporter exports logs data to Geneva + * The user_events logs exporter exports logs data to tracepoint via user_events. */ class Exporter final : public opentelemetry::sdk::logs::LogRecordExporter { diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h index 7a477c676..99b646cb1 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h @@ -5,6 +5,8 @@ #ifdef ENABLE_LOGS_PREVIEW +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/logs/severity.h" # include "opentelemetry/sdk/common/attribute_utils.h" # include "opentelemetry/sdk/logs/recordable.h" # include "opentelemetry/version.h" diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter.h b/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter.h new file mode 100644 index 000000000..0e0392c69 --- /dev/null +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter.h @@ -0,0 +1,76 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/exporters/otlp/otlp_metric_utils.h" + +#include "exporter_options.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" + +#include "opentelemetry/common/spin_lock_mutex.h" +#include "opentelemetry/sdk/common/global_log_handler.h" + +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace metrics +{ + +namespace api_common = opentelemetry::common; +namespace sdk_common = opentelemetry::sdk::common; +namespace sdk_metrics = opentelemetry::sdk::metrics; +namespace otlp_exporter = opentelemetry::exporter::otlp; + +class Exporter final : public opentelemetry::sdk::metrics::PushMetricExporter +{ +public: + /** + * Create a metrics exporter using all default options. + */ + Exporter(); + + explicit Exporter(const ExporterOptions &options); + + ~Exporter() override; + + /** + * Get the a`AggregationTeporality for this exporter. + * + * @return AggregationTemporality + */ + sdk_metrics::AggregationTemporality GetAggregationTemporality( + sdk_metrics::InstrumentType instrument_type) const noexcept override; + + sdk_common::ExportResult Export( + const sdk_metrics::ResourceMetrics &data) noexcept override; + + bool ForceFlush( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + bool Shutdown( + std::chrono::microseconds timeout = std::chrono::microseconds::max()) noexcept override; + + private: + // The configration options associated with this exporter. + const ExporterOptions options_; + mutable opentelemetry::common::SpinLockMutex lock_; + const sdk_metrics::AggregationTemporalitySelector aggregation_temporality_selector_; + + bool is_shutdown_ = false; + + // A tracepoint_provider_state represents a connection to the tracing system. + // It is usually global so that it can be shared between exporters. + tracepoint_provider_state provider_ = TRACEPOINT_PROVIDER_STATE_INIT; + tracepoint_state otlp_metrics_ = TRACEPOINT_STATE_INIT; + +}; + +} // namespace metrics +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h b/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h new file mode 100644 index 000000000..6c42022f9 --- /dev/null +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include "opentelemetry/version.h" +#include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace user_events +{ +namespace metrics +{ + +namespace sdk_metrics = opentelemetry::sdk::metrics; + +struct ExporterOptions +{ + sdk_metrics::AggregationTemporality aggregation_temporality = sdk_metrics::AggregationTemporality::kCumulative; +}; + +} // namespace metrics +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/user_events/src/metrics_exporter.cc b/exporters/user_events/src/metrics_exporter.cc new file mode 100644 index 000000000..8fa1fcc8f --- /dev/null +++ b/exporters/user_events/src/metrics_exporter.cc @@ -0,0 +1,109 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/user_events/metrics/exporter.h" + +#include "tracepoint/tracepoint.h" + +#include +#include + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace exporter { +namespace user_events { +namespace metrics { + +// -------------------------------- Constructors -------------------------------- + +Exporter::Exporter() : Exporter(ExporterOptions()) {} + +Exporter::Exporter(const ExporterOptions &options) +: options_(options), + aggregation_temporality_selector_{otlp_exporter::OtlpMetricUtils::ChooseTemporalitySelector(options_.aggregation_temporality)} +{ + int err; + + err = tracepoint_open_provider(&provider_); + + err = tracepoint_connect(&otlp_metrics_, &provider_, "otlp_metrics"); + if (err) { + OTEL_INTERNAL_LOG_ERROR("[user_events Metrics Exporter] Failed to connect to tracepoint provider"); + } +} + +Exporter::~Exporter() +{ + tracepoint_close_provider(&provider_); +} + +// ----------------------------- Exporter methods ------------------------------ + +sdk_metrics::AggregationTemporality Exporter::GetAggregationTemporality( + sdk_metrics::InstrumentType instrument_type) const noexcept +{ + return sdk_metrics::AggregationTemporality::kDelta; +} + +sdk_common::ExportResult Exporter::Export( + const sdk_metrics::ResourceMetrics &data) noexcept +{ + auto shutdown = false; + { + const std::lock_guard locked(lock_); + shutdown = is_shutdown_; + } + + if (shutdown) { + OTEL_INTERNAL_LOG_ERROR("[user_events Metrics Exporter] Exporting") + + return sdk_common::ExportResult::kFailure; + } + + if (!TRACEPOINT_ENABLED(&otlp_metrics_)) + { + return sdk_common::ExportResult::kSuccess; + } + + proto::collector::metrics::v1::ExportMetricsServiceRequest request; + otlp_exporter::OtlpMetricUtils::PopulateRequest(data, &request); + + int size = (int)request.ByteSizeLong(); + char *buffer = new char[size+sizeof(int)]; + request.SerializeToArray(buffer+sizeof(int), size); + memcpy(buffer, &size, sizeof(int)); + + struct iovec data_vecs[] = { + {}, + { buffer, size+sizeof(int)}, + }; + + int err = tracepoint_write(&otlp_metrics_, sizeof(data_vecs)/sizeof(data_vecs[0]), data_vecs); + if (err) + { + OTEL_INTERNAL_LOG_ERROR("[user_events Metrics Exporter] Exporting failed with " << err); + + return sdk_common::ExportResult::kFailure; + } + return sdk_common::ExportResult::kSuccess; +} + +bool Exporter::ForceFlush(std::chrono::microseconds timeout) noexcept +{ + return true; +} + +bool Exporter::Shutdown(std::chrono::microseconds time) noexcept { + const std::lock_guard locked(lock_); + if (!is_shutdown_) { + tracepoint_close_provider(&provider_); + } + is_shutdown_ = true; + return true; +} + +} // namespace metrics +} // namespace user_events +} // namespace exporter + +OPENTELEMETRY_END_NAMESPACE \ No newline at end of file diff --git a/exporters/user_events/src/recordable.cc b/exporters/user_events/src/recordable.cc index 69bfaad1f..debfd7fd6 100644 --- a/exporters/user_events/src/recordable.cc +++ b/exporters/user_events/src/recordable.cc @@ -29,7 +29,6 @@ void Recordable::SetSeverity(api_logs::Severity severity) noexcept uint8_t severity_value = static_cast(severity); if (severity_value == 0 || severity_value > 24) { - // TODO: log error OTEL_INTERNAL_LOG_ERROR( "[user_events Log Exporter] Recordable: invalid severity value: " << severity_value); severity_value = 1; @@ -40,9 +39,8 @@ void Recordable::SetSeverity(api_logs::Severity severity) noexcept cs_part_b_bookmark_size_ += 2; event_builder_.AddValue("severityNumber", static_cast(severity_value), event_field_format_default); - event_builder_.AddString( - "severityText", api_logs::SeverityNumToText[static_cast(severity_value)].data(), - event_field_format_default); + auto severity_text = api_logs::SeverityNumToText[static_cast(severity_value)].data(); + event_builder_.AddString("severityText", severity_text, event_field_format_default); } void Recordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept @@ -66,12 +64,12 @@ void Recordable::SetEventId(int64_t id, nostd::string_view name) noexcept void Recordable::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept { - // TODO: implement + // optional for logs. } void Recordable::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept { - // TODO: implement + // optional for logs. } // @@ -92,7 +90,7 @@ void Recordable::SetAttribute(nostd::string_view key, void Recordable::SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept { - // TODO: convert to nanoseconds + // Timestamp is optional because timestamp is always recorded in the header of user_events. } bool Recordable::PrepareExport() noexcept From 20721e51235565020fc7fef2ba1aee92fc5744e8 Mon Sep 17 00:00:00 2001 From: Nick Anderson <105019436+niande-xbox@users.noreply.github.com> Date: Fri, 30 Jun 2023 14:15:40 -0700 Subject: [PATCH 61/77] Bump opentelemetry-cpp version to 1.9.1, change LogExporter/LogProcessor to post-1.6 LogRecordExporter and LogRecordProcessor (#294) --- exporters/fluentd/CHANGELOG.md | 4 ++ exporters/fluentd/CMakeLists.txt | 5 ++- exporters/fluentd/README.md | 14 +++++- .../fluentd/cmake/opentelemetry-cpp.cmake | 11 ++--- exporters/fluentd/example/CMakeLists.txt | 4 +- .../example/log/foo_library/foo_library.cc | 28 +++++++++--- exporters/fluentd/example/log/main.cc | 8 ++-- .../exporters/fluentd/common/fluentd_common.h | 26 +++++++++++ .../exporters/fluentd/common/fluentd_fields.h | 43 ++++++++++--------- .../exporters/fluentd/log/fluentd_exporter.h | 4 +- .../exporters/fluentd/log/recordable.h | 22 ++++++++-- exporters/fluentd/src/log/fluentd_exporter.cc | 8 ++-- exporters/fluentd/src/log/recordable.cc | 34 ++++++++++++--- .../test/log/fluentd_recordable_test.cc | 39 ++++++++++------- exporters/fluentd/vcpkg.json | 22 ++++++++++ 15 files changed, 196 insertions(+), 76 deletions(-) create mode 100644 exporters/fluentd/vcpkg.json diff --git a/exporters/fluentd/CHANGELOG.md b/exporters/fluentd/CHANGELOG.md index fcdc2bd73..7a0d0e0d0 100644 --- a/exporters/fluentd/CHANGELOG.md +++ b/exporters/fluentd/CHANGELOG.md @@ -13,6 +13,10 @@ Increment the: * MINOR version when you add functionality in a backwards compatible manner, and * PATCH version when you make backwards compatible bug fixes. +## [2.0.0] 2023-06-30 + +* [EXPORTER] OpenTelemetry SDK v1.9.1 compatibility. Migrate to ObservedTimestamp from Timestamp. + ## [1.2.0] 2022-08-29 * [EXPORTER] OpenTelemetry SDK v1.6.0 compatibility diff --git a/exporters/fluentd/CMakeLists.txt b/exporters/fluentd/CMakeLists.txt index 7dc94de16..21cdc569a 100644 --- a/exporters/fluentd/CMakeLists.txt +++ b/exporters/fluentd/CMakeLists.txt @@ -26,8 +26,8 @@ add_definitions(-DHAVE_CONSOLE_LOG) add_definitions(-DENABLE_LOGS_PREVIEW) if (MAIN_PROJECT) - find_package(opentelemetry-cpp QUIET) - if(opentelemetry_cpp_FOUND) + find_package(opentelemetry-cpp CONFIG QUIET) + if(opentelemetry-cpp_FOUND) message("Using external opentelemetry-cpp") else() include(cmake/opentelemetry-cpp.cmake) @@ -52,6 +52,7 @@ else() endif() find_package(CURL REQUIRED) +find_package(Threads REQUIRED) include_directories(include) # create fluentd trace exporter diff --git a/exporters/fluentd/README.md b/exporters/fluentd/README.md index 8c0834226..3969e6fe5 100644 --- a/exporters/fluentd/README.md +++ b/exporters/fluentd/README.md @@ -12,7 +12,7 @@ Refer to install instructions [INSTALL.md](../../INSTALL.md#building-as-standalo Modify step 2 to create `cmake` build configuration for compiling fluentd as below: ```console - $ cmake -DWITH_fluentd=ON .. + $ cmake .. -- The C compiler identification is GNU 9.3.0 -- The CXX compiler identification is GNU 9.3.0 ... @@ -22,6 +22,18 @@ Modify step 2 to create `cmake` build configuration for compiling fluentd as bel $ ``` +### VCPKG Integration + +If integrating with VCPKG, make sure the cmake invocation defines the additional CMAKE_TOOLCHAIN_FILE. + +For example: + +```console + $ .../opentelemetry-cpp-contrib2/exporters/fluentd$ ~/vcpkg/vcpkg install + $ .../opentelemetry-cpp-contrib2/exporters/fluentd$ cmake -D CMAKE_TOOLCHAIN_FILE=/home/niande/vcpkg/scripts/buildsystems/vcpkg.cmake + $ .../opentelemetry-cpp-contrib2/exporters/fluentd$ make +``` + ### Bazel Install Instructions TODO diff --git a/exporters/fluentd/cmake/opentelemetry-cpp.cmake b/exporters/fluentd/cmake/opentelemetry-cpp.cmake index b89ca175c..e380a34b9 100644 --- a/exporters/fluentd/cmake/opentelemetry-cpp.cmake +++ b/exporters/fluentd/cmake/opentelemetry-cpp.cmake @@ -1,5 +1,5 @@ if("${opentelemetry-cpp-tag}" STREQUAL "") - set(opentelemetry-cpp-tag "v1.6.0") + set(opentelemetry-cpp-tag "v1.9.1") endif() function(target_create _target _lib) add_library(${_target} STATIC IMPORTED) @@ -11,7 +11,7 @@ endfunction() function(build_opentelemetry) set(opentelemetry_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/opentelemetry-cpp") set(opentelemetry_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/opentelemetry-cpp") - set(opentelemetry_cpp_targets opentelemetry_trace opentelemetry_logs opentelemetry_http_client_curl ) + set(opentelemetry_cpp_targets opentelemetry_trace opentelemetry_logs) set(opentelemetry_CMAKE_ARGS -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} @@ -24,7 +24,6 @@ function(build_opentelemetry) ${opentelemetry_BINARY_DIR}/sdk/src/logs/libopentelemetry_logs.a ${opentelemetry_BINARY_DIR}/sdk/src/resource/libopentelemetry_resources.a ${opentelemetry_BINARY_DIR}/sdk/src/common/libopentelemetry_common.a - ${opentelemetry_BINARY_DIR}/ext/src/http/client/curl/libopentelemetry_http_client_curl.a ${CURL_LIBRARIES} ) @@ -35,9 +34,7 @@ function(build_opentelemetry) include_directories(SYSTEM ${opentelemetry_include_dir}) - set(opentelemetry_deps opentelemetry_trace opentelemetry_logs opentelemetry_resources opentelemetry_common - opentelemetry_http_client_curl - ${CURL_LIBRARIES}) + set(opentelemetry_deps opentelemetry_trace opentelemetry_logs opentelemetry_resources opentelemetry_common ${CURL_LIBRARIES}) set(make_cmd ${CMAKE_COMMAND} --build --target ${opentelemetry_cpp_targets}) @@ -64,8 +61,6 @@ function(build_opentelemetry) "sdk/src/resource/libopentelemetry_resources.a") target_create("opentelemetry_common" "sdk/src/common/libopentelemetry_common.a") - target_create("opentelemetry_http_client_curl" - "ext/src/http/client/curl/libopentelemetry_http_client_curl.a") add_library(opentelemetry::libopentelemetry INTERFACE IMPORTED) add_dependencies(opentelemetry::libopentelemetry opentelemetry-cpp) set_target_properties( diff --git a/exporters/fluentd/example/CMakeLists.txt b/exporters/fluentd/example/CMakeLists.txt index f68f93f81..df1300ed5 100644 --- a/exporters/fluentd/example/CMakeLists.txt +++ b/exporters/fluentd/example/CMakeLists.txt @@ -7,7 +7,7 @@ target_link_libraries(foo_library_trace opentelemetry_exporter_fluentd_trace add_executable(fluentd_example_trace trace/main.cc) target_link_libraries(fluentd_example_trace ${CMAKE_THREAD_LIBS_INIT} - foo_library_trace opentelemetry_trace) + foo_library_trace opentelemetry-cpp::trace) add_library(foo_library_logs log/foo_library/foo_library.cc) @@ -16,4 +16,4 @@ target_link_libraries(foo_library_logs opentelemetry_exporter_fluentd_logs add_executable(fluentd_example_logs log/main.cc) target_link_libraries(fluentd_example_logs ${CMAKE_THREAD_LIBS_INIT} - foo_library_logs opentelemetry_logs) + foo_library_logs opentelemetry-cpp::logs) diff --git a/exporters/fluentd/example/log/foo_library/foo_library.cc b/exporters/fluentd/example/log/foo_library/foo_library.cc index cd74c47f5..653628eff 100644 --- a/exporters/fluentd/example/log/foo_library/foo_library.cc +++ b/exporters/fluentd/example/log/foo_library/foo_library.cc @@ -14,13 +14,24 @@ nostd::shared_ptr get_logger() { } void f1() { - get_logger()->Log(opentelemetry::logs::Severity::kDebug, "logName2", - {{"k1", "v1"}, {"k2", "v2"}}); + auto log_record = get_logger()->CreateLogRecord(); + log_record->SetSeverity(opentelemetry::logs::Severity::kDebug); + log_record->SetAttribute("k1", "v1"); + log_record->SetAttribute("k2", "v2"); + log_record->SetTimestamp(std::chrono::system_clock::now()); + log_record->SetEventId(2, "logName2"); + + get_logger()->EmitLogRecord(std::move(log_record)); } void f2() { - get_logger()->Log(opentelemetry::logs::Severity::kDebug, "logName3", - "log body - 3"); + auto log_record = get_logger()->CreateLogRecord(); + log_record->SetSeverity(opentelemetry::logs::Severity::kDebug); + log_record->SetBody("log body - 3"); + log_record->SetTimestamp(std::chrono::system_clock::now()); + log_record->SetEventId(3, "logName3"); + + get_logger()->EmitLogRecord(std::move(log_record)); f1(); f1(); @@ -28,6 +39,11 @@ void f2() { } // namespace void foo_library() { - get_logger()->Log(opentelemetry::logs::Severity::kDebug, "logName1", - "log body - 1"); + auto log_record = get_logger()->CreateLogRecord(); + log_record->SetSeverity(opentelemetry::logs::Severity::kDebug); + log_record->SetBody("log body - 1"); + log_record->SetTimestamp(std::chrono::system_clock::now()); + log_record->SetEventId(1, "logName1"); + + get_logger()->EmitLogRecord(std::move(log_record)); } diff --git a/exporters/fluentd/example/log/main.cc b/exporters/fluentd/example/log/main.cc index e9eb4d9b3..828bbeeff 100644 --- a/exporters/fluentd/example/log/main.cc +++ b/exporters/fluentd/example/log/main.cc @@ -4,7 +4,7 @@ #include "opentelemetry/exporters/fluentd/log/fluentd_exporter.h" #include "opentelemetry/logs/provider.h" #include "opentelemetry/sdk/logs/logger_provider.h" -#include "opentelemetry/sdk/logs/simple_log_processor.h" +#include "opentelemetry/sdk/logs/simple_log_record_processor.h" // Using an exporter that simply dumps span data to stdout. #include "foo_library/foo_library.h" @@ -20,10 +20,10 @@ namespace { void initLogger() { opentelemetry::exporter::fluentd::common::FluentdExporterOptions options; options.endpoint = "tcp://localhost:24222"; - auto exporter = std::unique_ptr( + auto exporter = std::unique_ptr( new opentelemetry::exporter::fluentd::logs::FluentdExporter(options)); - auto processor = std::unique_ptr( - new sdk_logs::SimpleLogProcessor(std::move(exporter))); + auto processor = std::unique_ptr( + new sdk_logs::SimpleLogRecordProcessor(std::move(exporter))); auto provider = std::shared_ptr( new opentelemetry::sdk::logs::LoggerProvider(std::move(processor))); diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h index 7cd42779e..a8a14790d 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h @@ -95,6 +95,32 @@ void inline PopulateAttribute( } } +inline std::string AttributeValueToString( + const opentelemetry::common::AttributeValue &value) { + std::string result; + if (nostd::holds_alternative(value)) { + result = nostd::get(value) ? "true" : "false"; + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::to_string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::string(nostd::get(value)); + } else if (nostd::holds_alternative(value)) { + result = std::string(nostd::get(value).data()); + } else { + LOG_WARN("[Fluentd Exporter] AttributeValueToString - " + " Nested attributes not supported - ignored"); + } + return result; +} + // Ref. https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1 enum class TransportFormat { kMessage, diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_fields.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_fields.h index 234109803..b4a600dbd 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_fields.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_fields.h @@ -19,39 +19,40 @@ * - links - OT Span links array */ -# define FLUENT_FIELD_VERSION "env_ver" /* Event version */ -# define FLUENT_FIELD_TYPE "env_type" /* Event type */ -# define FLUENT_FIELD_NAME "name" /* Event name */ +# define FLUENT_FIELD_VERSION "env_ver" /* Event version */ +# define FLUENT_FIELD_TYPE "env_type" /* Event type */ +# define FLUENT_FIELD_NAME "name" /* Event name */ #ifndef HAVE_FIELD_TIME #define HAVE_FIELD_TIME #endif -# define FLUENT_FIELD_TIME "env_time" /* Event time at envelope */ +# define FLUENT_FIELD_TIME "env_time" /* Event time at envelope */ -# define FLUENT_FIELD_TRACE_ID "env_dt_traceId" /* Trace Id */ -# define FLUENT_FIELD_SPAN_ID "env_dt_spanId" /* Span Id */ -# define FLUENT_FIELD_SPAN_PARENTID "parentId" /* Span ParentId */ -# define FLUENT_FIELD_SPAN_KIND "kind" /* Span Kind */ -# define FLUENT_FIELD_SPAN_LINKS "links" /* Span Links array */ +# define FLUENT_FIELD_TRACE_ID "env_dt_traceId" /* Trace Id */ +# define FLUENT_FIELD_SPAN_ID "env_dt_spanId" /* Span Id */ +# define FLUENT_FIELD_SPAN_PARENTID "parentId" /* Span ParentId */ +# define FLUENT_FIELD_SPAN_KIND "kind" /* Span Kind */ +# define FLUENT_FIELD_SPAN_LINKS "links" /* Span Links array */ -# define FLUENT_FIELD_PROPERTIES "env_properties" +# define FLUENT_FIELD_PROPERTIES "env_properties" /* Span option constants */ -# define FLUENT_FIELD_STARTTIME "startTime" /* Operation start time */ -# define FLUENT_FIELD_ENDTTIME "env_time" /* Operation end time */ -# define FLUENT_FIELD_DURATION "duration" /* Operation duration */ -# define FLUENT_FIELD_STATUSCODE "statusCode" /* OT Span status code */ -# define FLUENT_FIELD_STATUSMESSAGE "statusMessage" /* OT Span status message */ -# define FLUENT_FIELD_SUCCESS "success" /* OT Span success */ +# define FLUENT_FIELD_STARTTIME "startTime" /* Operation start time */ +# define FLUENT_FIELD_ENDTTIME "env_time" /* Operation end time */ +# define FLUENT_FIELD_DURATION "duration" /* Operation duration */ +# define FLUENT_FIELD_STATUSCODE "statusCode" /* OT Span status code */ +# define FLUENT_FIELD_STATUSMESSAGE "statusMessage" /* OT Span status message */ +# define FLUENT_FIELD_SUCCESS "success" /* OT Span success */ /*Log option constants */ -# define FLUENT_FIELD_TIMESTAMP "Timestamp" /* Log timestamp */ +# define FLUENT_FIELD_TIMESTAMP "Timestamp" /* Log timestamp */ +# define FLUENT_FIELD_OBSERVEDTIMESTAMP "ObservedTimestamp" /* Log observed timestamp */ /* Value constants */ -# define FLUENT_VALUE_SPAN "Span" /* Event name for Span */ -# define FLUENT_VALUE_LOG "Log" /* Event name for Log */ +# define FLUENT_VALUE_SPAN "Span" /* Event name for Span */ +# define FLUENT_VALUE_LOG "Log" /* Event name for Log */ -# define FLUENT_VALUE_SPAN_START "SpanStart" /* Span Start */ -# define FLUENT_VALUE_SPAN_END "SpanEnd" /* Span Start */ +# define FLUENT_VALUE_SPAN_START "SpanStart" /* Span Start */ +# define FLUENT_VALUE_SPAN_END "SpanEnd" /* Span Start */ /* clang-format on */ diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h index 26f496ff7..67c1be171 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h @@ -9,7 +9,7 @@ #include "opentelemetry/exporters/fluentd/trace/recordable.h" #include "opentelemetry/ext/http/common/url_parser.h" #include "opentelemetry/sdk/logs/exporter.h" -#include "opentelemetry/sdk/logs/log_record.h" +#include "opentelemetry/logs/log_record.h" #include @@ -25,7 +25,7 @@ namespace fluentd_common = opentelemetry::exporter::fluentd::common; /** * The fluentd exporter exports span data in JSON format as expected by fluentd */ -class FluentdExporter final : public logs_sdk::LogExporter { +class FluentdExporter final : public logs_sdk::LogRecordExporter { public: /** * Create a FluentdExporter using all default options. diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h index 717966bb1..50f2bf384 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h @@ -39,7 +39,7 @@ class Recordable final : public opentelemetry::sdk::logs::Recordable { * Set body field for this log. * @param message the body to set */ - void SetBody(nostd::string_view message) noexcept override; + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override; /** * Set a resource for this log. @@ -57,25 +57,32 @@ class Recordable final : public opentelemetry::sdk::logs::Recordable { nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept override; + /** + * Set the Event Id. + * @param id The event id to set + * @param name Optional event name to set + */ + void SetEventId(int64_t id, nostd::string_view name = {}) noexcept override; + /** * Set trace id for this log. * @param trace_id the trace id to set */ - void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override; + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override; /** * Set span id for this log. * @param span_id the span id to set */ virtual void - SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override; + SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override; /** * Inject a trace_flags for this log. * @param trace_flags the span id to set */ void SetTraceFlags( - opentelemetry::trace::TraceFlags trace_flags) noexcept override { + const opentelemetry::trace::TraceFlags &trace_flags) noexcept override { } // Not Supported /** @@ -85,6 +92,13 @@ class Recordable final : public opentelemetry::sdk::logs::Recordable { void SetTimestamp( opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetObservedTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** * Set instrumentation_scope for this log. * @param instrumentation_scope the instrumentation scope to set diff --git a/exporters/fluentd/src/log/fluentd_exporter.cc b/exporters/fluentd/src/log/fluentd_exporter.cc index 9a296ae36..9dfa46815 100644 --- a/exporters/fluentd/src/log/fluentd_exporter.cc +++ b/exporters/fluentd/src/log/fluentd_exporter.cc @@ -5,6 +5,7 @@ #include "opentelemetry/exporters/fluentd/log/fluentd_exporter.h" #include "opentelemetry/exporters/fluentd/log/recordable.h" #include "opentelemetry/ext/http/common/url_parser.h" +#include "opentelemetry/sdk/logs/read_write_log_record.h" #include "opentelemetry/exporters/fluentd/common/fluentd_logging.h" @@ -60,7 +61,7 @@ FluentdExporter::FluentdExporter() */ std::unique_ptr FluentdExporter::MakeRecordable() noexcept { - return std::unique_ptr(new Recordable); + return std::unique_ptr(new opentelemetry::exporter::fluentd::logs::Recordable()); } /** @@ -90,7 +91,8 @@ sdk::common::ExportResult FluentdExporter::Export( auto log = rec->Log(); // Emit "log" as fluentd event json record = json::array(); - record.push_back(log[FLUENT_FIELD_TIMESTAMP]); + // ObservedTimestamp is now set when Log/EmitLogRecord is invoked rather than Timestamp. + record.push_back(log[FLUENT_FIELD_OBSERVEDTIMESTAMP]); json fields = {}; for (auto &kv : log.items()) { fields[kv.key()] = kv.value(); @@ -150,7 +152,7 @@ bool FluentdExporter::Send(std::vector &packet) { return true; } - LOG_WARN("send failed, retrying %u ...", retryCount); + LOG_WARN("send failed, retrying %lu ...", retryCount); // Retry to connect and/or send } diff --git a/exporters/fluentd/src/log/recordable.cc b/exporters/fluentd/src/log/recordable.cc index 93f1fcd9a..5af84d882 100644 --- a/exporters/fluentd/src/log/recordable.cc +++ b/exporters/fluentd/src/log/recordable.cc @@ -26,17 +26,25 @@ void Recordable::SetName(nostd::string_view name) noexcept { json_["name"] = name.data(); } -void Recordable::SetBody(nostd::string_view message) noexcept { - json_["body"] = message.data(); +void Recordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept { + json_["body"] = fluentd_common::AttributeValueToString(message).data(); } -void Recordable::SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept { +void Recordable::SetEventId(int64_t id, nostd::string_view name) noexcept { + json_["EventId"] = id; + + if (!name.empty()) { + json_["name"] = name.data(); + } +} + +void Recordable::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept { char trace_id_lower_base16[opentelemetry::trace::TraceId::kSize * 2] = {0}; trace_id.ToLowerBase16(trace_id_lower_base16); json_[FLUENT_FIELD_TRACE_ID] = std::string(trace_id_lower_base16, 32); } -void Recordable::SetSpanId(opentelemetry::trace::SpanId span_id) noexcept { +void Recordable::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept { char span_id_lower_base16[opentelemetry::trace::SpanId::kSize * 2] = {0}; span_id.ToLowerBase16(span_id_lower_base16); json_[FLUENT_FIELD_SPAN_ID] = std::string(span_id_lower_base16, 16); @@ -52,18 +60,30 @@ void Recordable::SetAttribute( fluentd_common::PopulateAttribute(json_[FLUENT_FIELD_PROPERTIES], key, value); } -void Recordable::SetTimestamp( - opentelemetry::common::SystemTimestamp timestamp) noexcept { - json_["Timestamp"] = fluentd_common::get_msgpack_eventtimeext( +static inline nlohmann::byte_container_with_subtype> + GetMsgPackEventTimeFromSystemTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept { + return fluentd_common::get_msgpack_eventtimeext( + // Add all whole seconds to the event time static_cast(std::chrono::duration_cast( timestamp.time_since_epoch()) .count()), + // Add any remaining nanoseconds past the last whole second std::chrono::duration_cast( timestamp.time_since_epoch()) .count() % 1000000000); } +void Recordable::SetTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept { + json_["Timestamp"] = GetMsgPackEventTimeFromSystemTimestamp(timestamp); +} + +void Recordable::SetObservedTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept { + json_["ObservedTimestamp"] = GetMsgPackEventTimeFromSystemTimestamp(timestamp); +} + } // namespace logs } // namespace fluentd } // namespace exporter diff --git a/exporters/fluentd/test/log/fluentd_recordable_test.cc b/exporters/fluentd/test/log/fluentd_recordable_test.cc index 7eac26294..d31d1395a 100644 --- a/exporters/fluentd/test/log/fluentd_recordable_test.cc +++ b/exporters/fluentd/test/log/fluentd_recordable_test.cc @@ -28,7 +28,7 @@ #include "opentelemetry/logs/provider.h" #include "opentelemetry/sdk/logs/logger_provider.h" #include "opentelemetry/sdk/logs/recordable.h" -#include "opentelemetry/sdk/logs/simple_log_processor.h" +#include "opentelemetry/sdk/logs/simple_log_record_processor.h" #include "opentelemetry/sdk/logs/exporter.h" @@ -80,7 +80,6 @@ struct TestServer { std::vector msg(conn.request_buffer.data(), conn.request_buffer.data() + conn.request_buffer.size()); - try { auto j = nlohmann::json::from_msgpack(msg); std::cout << "[" << count.fetch_add(1) @@ -126,18 +125,13 @@ TEST(FluentdExporter, SendLogEvents) { options.endpoint = "tcp://127.0.0.1:24222"; options.tag = "tag.my_service"; - auto exporter = std::unique_ptr( + auto exporter = std::unique_ptr( new opentelemetry::exporter::fluentd::logs::FluentdExporter(options)); - auto processor = std::shared_ptr( - new sdklogs::SimpleLogProcessor(std::move(exporter))); + auto processor = std::unique_ptr( + new sdklogs::SimpleLogRecordProcessor(std::move(exporter))); auto provider = std::shared_ptr( - new opentelemetry::sdk::logs::LoggerProvider()); - - auto pr = - static_cast(provider.get()); - - pr->SetProcessor(processor); + new opentelemetry::sdk::logs::LoggerProvider(std::move(processor))); // Set the global trace provider opentelemetry::logs::Provider::SetLoggerProvider(provider); @@ -145,11 +139,24 @@ TEST(FluentdExporter, SendLogEvents) { std::string providerName = "MyInstrumentationName"; auto logger = provider->GetLogger(providerName); - // Span attributes - Properties attribs = {{"attrib1", 1}, {"attrib2", 2}}; - - logger->Log(logs::Severity::kDebug, "f2"); - logger->Log(logs::Severity::kDebug, "f3"); + auto f2 = logger->CreateLogRecord(); + f2->SetSeverity(opentelemetry::logs::Severity::kDebug); + f2->SetAttribute("attrib1", 1); + f2->SetAttribute("attrib2", 2); + f2->SetBody("f2"); + f2->SetTimestamp(std::chrono::system_clock::now()); + f2->SetEventId(2, "f2"); + + auto f3 = logger->CreateLogRecord(); + f3->SetSeverity(opentelemetry::logs::Severity::kDebug); + f3->SetAttribute("attrib1", 1); + f3->SetAttribute("attrib2", 2); + f3->SetBody("f3"); + f3->SetTimestamp(std::chrono::system_clock::now()); + f3->SetEventId(3, "f3"); + + logger->EmitLogRecord(std::move(f2)); + logger->EmitLogRecord(std::move(f3)); testServer.WaitForEvents(2, 200); // 2 batches must arrive in 200ms testServer.Stop(); diff --git a/exporters/fluentd/vcpkg.json b/exporters/fluentd/vcpkg.json new file mode 100644 index 000000000..7371ca786 --- /dev/null +++ b/exporters/fluentd/vcpkg.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "name": "opentelemetry-fluentd", + "version-semver": "2.0.0", + "description": "mdsd/fluentd exporter for OpenTelemetry C++", + "homepage": "https://github.com/niande-xbox/opentelemetry-cpp-contrib/tree/main/exporters/fluentd", + "license": "Apache-2.0", + "dependencies": [ + "curl", + "nlohmann-json", + "opentelemetry-cpp", + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] + } + \ No newline at end of file From 49a42a3bd950d3359f0b3921c13f6adc7cfc793a Mon Sep 17 00:00:00 2001 From: Nick Anderson <105019436+niande-xbox@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:35:16 -0700 Subject: [PATCH 62/77] Add install(EXPORT...) for the opentelemetry-fluentd-target. (#297) --- exporters/fluentd/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/exporters/fluentd/CMakeLists.txt b/exporters/fluentd/CMakeLists.txt index 21cdc569a..b70ce12a4 100644 --- a/exporters/fluentd/CMakeLists.txt +++ b/exporters/fluentd/CMakeLists.txt @@ -194,4 +194,10 @@ if (MAIN_PROJECT) NAMESPACE "${PROJECT_NAME}::" FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-target.cmake" ) + + install( + EXPORT "${PROJECT_NAME}-target" + NAMESPACE "${PROJECT_NAME}::" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + endif() From 7afa91952f08aad1fa79b8992f20a4b0cdaadaff Mon Sep 17 00:00:00 2001 From: Nick Anderson <105019436+niande-xbox@users.noreply.github.com> Date: Thu, 13 Jul 2023 11:43:03 -0700 Subject: [PATCH 63/77] Update to newer CMakeFindDependencyMacro macro to fix usage for vcpkg port. (#299) --- .../cmake/opentelemetry-cpp-fluentd-config.cmake.in | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/exporters/fluentd/cmake/opentelemetry-cpp-fluentd-config.cmake.in b/exporters/fluentd/cmake/opentelemetry-cpp-fluentd-config.cmake.in index 8a9da0a3b..46ec892a1 100644 --- a/exporters/fluentd/cmake/opentelemetry-cpp-fluentd-config.cmake.in +++ b/exporters/fluentd/cmake/opentelemetry-cpp-fluentd-config.cmake.in @@ -56,11 +56,8 @@ foreach(_TEST_TARGET IN LISTS _OPENTELEMETRY_CPP_FLUENTD_LIBRARIES_TEST_TARGETS) endif() endforeach() - # handle the QUIETLY and REQUIRED arguments and set opentelemetry-cpp_FOUND to # TRUE if all variables listed contain valid results, e.g. valid file paths. -include("FindPackageHandleStandardArgs") -find_package_handle_standard_args( - ${CMAKE_FIND_PACKAGE_NAME} - FOUND_VAR ${CMAKE_FIND_PACKAGE_NAME}_FOUND - REQUIRED_VARS OPENTELEMETRY_CPP_FLUENTD_INCLUDE_DIRS OPENTELEMETRY_CPP_FLUENTD_LIBRARIES) +include(CMakeFindDependencyMacro) +find_dependency(opentelemetry-cpp CONFIG) +find_dependency(nlohmann_json CONFIG) From 15d5363ddb71bec00ac9552dade0e8bf8d28ef1d Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 21 Jul 2023 01:00:15 -0700 Subject: [PATCH 64/77] Add WITH_BENCHMARK (#301) --- exporters/user_events/CMakeLists.txt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/exporters/user_events/CMakeLists.txt b/exporters/user_events/CMakeLists.txt index 0b83ec0ff..e782113b5 100644 --- a/exporters/user_events/CMakeLists.txt +++ b/exporters/user_events/CMakeLists.txt @@ -111,12 +111,14 @@ if(BUILD_TESTING) TEST_LIST user_events_logs_exporter_test) endif() -find_package(benchmark CONFIG REQUIRED) -add_executable(user_events_logger_benchmark benchmark/logger_benchmark.cc) -target_link_libraries( - user_events_logger_benchmark benchmark::benchmark ${CMAKE_THREAD_LIBS_INIT} - ${CMAKE_THREAD_LIBS_INIT} opentelemetry_logs - opentelemetry_exporter_user_events_logs) +if(WITH_BENCHMARK) + find_package(benchmark CONFIG REQUIRED) + add_executable(user_events_logger_benchmark benchmark/logger_benchmark.cc) + target_link_libraries( + user_events_logger_benchmark benchmark::benchmark ${CMAKE_THREAD_LIBS_INIT} + ${CMAKE_THREAD_LIBS_INIT} opentelemetry_logs + opentelemetry_exporter_user_events_logs) +endif() install( TARGETS opentelemetry_exporter_user_events_logs From ddc553dcb8db546a541b0c1cf7baaa3ae391c8e7 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Mon, 24 Jul 2023 11:08:17 -0700 Subject: [PATCH 65/77] [user_events exporter] Update exporter option type to PreferredAggregationTemporality (#303) --- .../user_events/metrics/exporter_options.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h b/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h index 6c42022f9..b17ec69a8 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/metrics/exporter_options.h @@ -3,9 +3,10 @@ #pragma once -#include "opentelemetry/version.h" #include +#include "opentelemetry/version.h" + OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { @@ -18,10 +19,11 @@ namespace sdk_metrics = opentelemetry::sdk::metrics; struct ExporterOptions { - sdk_metrics::AggregationTemporality aggregation_temporality = sdk_metrics::AggregationTemporality::kCumulative; + opentelemetry::exporter::otlp::PreferredAggregationTemporality aggregation_temporality = + opentelemetry::exporter::otlp::PreferredAggregationTemporality::kCumulative; }; -} // namespace metrics -} // namespace user_events -} // namespace exporter -OPENTELEMETRY_END_NAMESPACE \ No newline at end of file +} // namespace metrics +} // namespace user_events +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE From 866351ce2422a9d953ded4447bcdea0e587d6a53 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Tue, 25 Jul 2023 22:25:07 -0700 Subject: [PATCH 66/77] [user_events exporter] Disable building samples and tools from LinuxTracepoint (#305) --- exporters/user_events/CMakeLists.txt | 7 +++++-- exporters/user_events/third_party/LinuxTracepoints | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/exporters/user_events/CMakeLists.txt b/exporters/user_events/CMakeLists.txt index e782113b5..b7c8a48b9 100644 --- a/exporters/user_events/CMakeLists.txt +++ b/exporters/user_events/CMakeLists.txt @@ -10,12 +10,12 @@ endif() option(BUILD_EXAMPLE "Build example" ON) option(BUILD_TESTING "Build tests" ON) -set(MAIN_PROJECT OFF) - project(opentelemetry-user_events-exporter) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(MAIN_PROJECT ON) message(STATUS "${PROJECT_NAME} is main project") +else() + set(MAIN_PROJECT OFF) endif() if(MAIN_PROJECT) @@ -26,6 +26,9 @@ if(MAIN_PROJECT) find_package(opentelemetry-cpp REQUIRED) endif() +# don't build samples and tools from LinuxTracepoints. +set(BUILD_SAMPLES OFF) +set(BUILD_TOOLS OFF) add_subdirectory(third_party/LinuxTracepoints) include_directories(include) diff --git a/exporters/user_events/third_party/LinuxTracepoints b/exporters/user_events/third_party/LinuxTracepoints index 0561e730f..9378b2ff2 160000 --- a/exporters/user_events/third_party/LinuxTracepoints +++ b/exporters/user_events/third_party/LinuxTracepoints @@ -1 +1 @@ -Subproject commit 0561e730f84e56f2c0f5e9eec108f516e8d0ef88 +Subproject commit 9378b2ff28fb36924337acf88fe07b11ba5054b1 From e79688190144174ee17cad0f954ff90f9c74ecb8 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 1 Aug 2023 15:41:08 -0700 Subject: [PATCH 67/77] Upgrade fluentd exporter to use latest otel-cpp (#309) --- exporters/fluentd/CMakeLists.txt | 42 ++++++++++++------- exporters/fluentd/example/CMakeLists.txt | 14 ++++++- .../example/log/foo_library/foo_library.cc | 1 - .../exporters/fluentd/common/fluentd_common.h | 4 ++ .../exporters/fluentd/log/fluentd_exporter.h | 2 - .../exporters/fluentd/log/recordable.h | 2 - exporters/fluentd/src/log/fluentd_exporter.cc | 2 + exporters/fluentd/src/log/recordable.cc | 4 ++ .../fluentd/src/trace/fluentd_exporter.cc | 2 +- exporters/fluentd/src/trace/recordable.cc | 2 + .../fluentd/test/common/msgpack_timestamp.h | 2 +- 11 files changed, 53 insertions(+), 24 deletions(-) diff --git a/exporters/fluentd/CMakeLists.txt b/exporters/fluentd/CMakeLists.txt index b70ce12a4..61f98a73a 100644 --- a/exporters/fluentd/CMakeLists.txt +++ b/exporters/fluentd/CMakeLists.txt @@ -22,8 +22,6 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) project(opentelemetry-fluentd) set(MAIN_PROJECT ON) endif() -add_definitions(-DHAVE_CONSOLE_LOG) -add_definitions(-DENABLE_LOGS_PREVIEW) if (MAIN_PROJECT) find_package(opentelemetry-cpp CONFIG QUIET) @@ -34,7 +32,7 @@ if (MAIN_PROJECT) build_opentelemetry() set(OPENTELEMETRY_CPP_INCLUDE_DIRS "") set(OPENTELEMETRY_CPP_LIBRARIES "opentelemetry::libopentelemetry") - message("\nopentelemetry-cpp package was not found. Cloned from github") + message("opentelemetry-cpp package was not found. Cloned from github") endif() endif() @@ -48,7 +46,7 @@ else() set(nlohmann_json_SOURCE_DIR "${CMAKE_SOURCE_DIR}/nlohmann_json/single_include") include_directories(${nlohmann_json_SOURCE_DIR}) - message("\nnlohmann_json package was not found. Cloning from github") + message("nlohmann_json package was not found. Cloning from github") endif() find_package(CURL REQUIRED) @@ -58,12 +56,20 @@ include_directories(include) # create fluentd trace exporter add_library(opentelemetry_exporter_fluentd_trace src/trace/fluentd_exporter.cc src/trace/recordable.cc) -target_include_directories(opentelemetry_exporter_fluentd_trace +if(MAIN_PROJECT) + target_include_directories(opentelemetry_exporter_fluentd_trace PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) -target_link_libraries( - opentelemetry_exporter_fluentd_trace - PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES} - INTERFACE nlohmann_json::nlohmann_json) + target_link_libraries( + opentelemetry_exporter_fluentd_trace + PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES} + INTERFACE nlohmann_json::nlohmann_json) +else() + target_link_libraries( + opentelemetry_exporter_fluentd_trace + PUBLIC opentelemetry_trace opentelemetry_resources opentelemetry_common + INTERFACE nlohmann_json::nlohmann_json) +endif() + set_target_properties(opentelemetry_exporter_fluentd_trace PROPERTIES EXPORT_NAME trace) @@ -71,15 +77,21 @@ set_target_properties(opentelemetry_exporter_fluentd_trace add_library(opentelemetry_exporter_fluentd_logs src/log/fluentd_exporter.cc src/log/recordable.cc) -target_include_directories(opentelemetry_exporter_fluentd_logs +if(MAIN_PROJECT) + target_include_directories(opentelemetry_exporter_fluentd_logs PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) -target_link_libraries( - opentelemetry_exporter_fluentd_logs - PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES} - INTERFACE nlohmann_json::nlohmann_json) + target_link_libraries( + opentelemetry_exporter_fluentd_logs + PUBLIC ${OPENTELEMETRY_CPP_LIBRARIES} + INTERFACE nlohmann_json::nlohmann_json) +else() + target_link_libraries( + opentelemetry_exporter_fluentd_logs + PUBLIC opentelemetry_logs opentelemetry_resources opentelemetry_common + INTERFACE nlohmann_json::nlohmann_json) +endif() set_target_properties(opentelemetry_exporter_fluentd_logs PROPERTIES EXPORT_NAME logs) - if(nlohmann_json_clone) add_dependencies(opentelemetry_exporter_fluentd_trace nlohmann_json::nlohmann_json) diff --git a/exporters/fluentd/example/CMakeLists.txt b/exporters/fluentd/example/CMakeLists.txt index df1300ed5..1f3ea4c2e 100644 --- a/exporters/fluentd/example/CMakeLists.txt +++ b/exporters/fluentd/example/CMakeLists.txt @@ -6,8 +6,13 @@ target_link_libraries(foo_library_trace opentelemetry_exporter_fluentd_trace ${CMAKE_THREAD_LIBS_INIT}) add_executable(fluentd_example_trace trace/main.cc) -target_link_libraries(fluentd_example_trace ${CMAKE_THREAD_LIBS_INIT} +if(MAIN_PROJECT) + target_link_libraries(fluentd_example_trace ${CMAKE_THREAD_LIBS_INIT} foo_library_trace opentelemetry-cpp::trace) +else() + target_link_libraries(fluentd_example_trace ${CMAKE_THREAD_LIBS_INIT} + foo_library_trace opentelemetry_trace) +endif() add_library(foo_library_logs log/foo_library/foo_library.cc) @@ -15,5 +20,10 @@ target_link_libraries(foo_library_logs opentelemetry_exporter_fluentd_logs ${CMAKE_THREAD_LIBS_INIT}) add_executable(fluentd_example_logs log/main.cc) -target_link_libraries(fluentd_example_logs ${CMAKE_THREAD_LIBS_INIT} +if(MAIN_PROJECT) + target_link_libraries(fluentd_example_logs ${CMAKE_THREAD_LIBS_INIT} foo_library_logs opentelemetry-cpp::logs) +else() + target_link_libraries(fluentd_example_logs ${CMAKE_THREAD_LIBS_INIT} + foo_library_logs opentelemetry_logs) +endif() diff --git a/exporters/fluentd/example/log/foo_library/foo_library.cc b/exporters/fluentd/example/log/foo_library/foo_library.cc index 653628eff..361acbbfc 100644 --- a/exporters/fluentd/example/log/foo_library/foo_library.cc +++ b/exporters/fluentd/example/log/foo_library/foo_library.cc @@ -1,7 +1,6 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#define ENABLE_LOGS_PREVIEW #include "opentelemetry/logs/provider.h" namespace logs = opentelemetry::logs; diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h index a8a14790d..a5ec1c8e1 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/common/fluentd_common.h @@ -12,6 +12,10 @@ #include +#ifndef ENABLE_LOGS_PREVIEW +#define ENABLE_LOGS_PREVIEW 1 +#endif + OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { namespace fluentd { diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h index 67c1be171..05f661404 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/fluentd_exporter.h @@ -2,8 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once -#define ENABLE_LOGS_PREVIEW 1 - #include "opentelemetry/exporters/fluentd/common/socket_tools.h" #include "opentelemetry/exporters/fluentd/trace/recordable.h" diff --git a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h index 50f2bf384..9687f03e9 100644 --- a/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h +++ b/exporters/fluentd/include/opentelemetry/exporters/fluentd/log/recordable.h @@ -3,8 +3,6 @@ #pragma once -#define ENABLE_LOGS_PREVIEW 1 - #include "nlohmann/json.hpp" #include "opentelemetry/sdk/common/attribute_utils.h" #include "opentelemetry/sdk/logs/recordable.h" diff --git a/exporters/fluentd/src/log/fluentd_exporter.cc b/exporters/fluentd/src/log/fluentd_exporter.cc index 9dfa46815..569c82b57 100644 --- a/exporters/fluentd/src/log/fluentd_exporter.cc +++ b/exporters/fluentd/src/log/fluentd_exporter.cc @@ -1,6 +1,8 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +#ifndef HAVE_CONSOLE_LOG #define HAVE_CONSOLE_LOG +#endif #include "opentelemetry/exporters/fluentd/log/fluentd_exporter.h" #include "opentelemetry/exporters/fluentd/log/recordable.h" diff --git a/exporters/fluentd/src/log/recordable.cc b/exporters/fluentd/src/log/recordable.cc index 5af84d882..657f924d1 100644 --- a/exporters/fluentd/src/log/recordable.cc +++ b/exporters/fluentd/src/log/recordable.cc @@ -5,6 +5,10 @@ #include "opentelemetry/exporters/fluentd/common/fluentd_common.h" #include "opentelemetry/exporters/fluentd/common/fluentd_logging.h" +#include "opentelemetry/logs/severity.h" +#include "opentelemetry/trace/span_id.h" +#include "opentelemetry/trace/trace_id.h" + #include #include diff --git a/exporters/fluentd/src/trace/fluentd_exporter.cc b/exporters/fluentd/src/trace/fluentd_exporter.cc index 39546ac19..485f490da 100644 --- a/exporters/fluentd/src/trace/fluentd_exporter.cc +++ b/exporters/fluentd/src/trace/fluentd_exporter.cc @@ -248,7 +248,7 @@ bool FluentdExporter::Send(std::vector &packet) { return true; } - LOG_WARN("send failed, retrying %u ...", retryCount); + LOG_WARN("send failed, retrying %u ...", (unsigned int)retryCount); // Retry to connect and/or send } diff --git a/exporters/fluentd/src/trace/recordable.cc b/exporters/fluentd/src/trace/recordable.cc index 5c0a5ed9d..7b5c9b61c 100644 --- a/exporters/fluentd/src/trace/recordable.cc +++ b/exporters/fluentd/src/trace/recordable.cc @@ -5,6 +5,8 @@ #include "opentelemetry/exporters/fluentd/common/fluentd_common.h" #include "opentelemetry/exporters/fluentd/common/fluentd_logging.h" +#include "opentelemetry/sdk/resource/resource.h" + #include #include diff --git a/exporters/fluentd/test/common/msgpack_timestamp.h b/exporters/fluentd/test/common/msgpack_timestamp.h index 5d545a70c..1c16a9425 100644 --- a/exporters/fluentd/test/common/msgpack_timestamp.h +++ b/exporters/fluentd/test/common/msgpack_timestamp.h @@ -22,7 +22,7 @@ class binary_writer2 : public binary_writer { output_adapter_t oa = nullptr; /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); + const bool is_little_endian = this->little_endianess(); public: /* From 37e4466d882cbddff6f607a20fe327060de76166 Mon Sep 17 00:00:00 2001 From: gscalderonl <71537530+gscalderonl@users.noreply.github.com> Date: Fri, 4 Aug 2023 18:21:52 -0700 Subject: [PATCH 68/77] Example of OpenTelemetry FFI Bridge for Rust and C++ and Performance Benchmark (#313) --- examples/ffi/Cargo.toml | 10 +++++ examples/ffi/README.md | 37 ++++++++++++++++++ examples/ffi/cpprust/.gitignore | 2 + examples/ffi/cpprust/Cargo.toml | 15 ++++++++ examples/ffi/cpprust/README.md | 29 ++++++++++++++ examples/ffi/cpprust/build.rs | 9 +++++ examples/ffi/cpprust/src/animal.hpp | 8 ++++ examples/ffi/cpprust/src/lib.rs | 56 +++++++++++++++++++++++++++ examples/ffi/cpprust/src/main.cpp | 60 +++++++++++++++++++++++++++++ examples/ffi/src/lib.rs | 30 +++++++++++++++ 10 files changed, 256 insertions(+) create mode 100644 examples/ffi/Cargo.toml create mode 100644 examples/ffi/README.md create mode 100644 examples/ffi/cpprust/.gitignore create mode 100644 examples/ffi/cpprust/Cargo.toml create mode 100644 examples/ffi/cpprust/README.md create mode 100644 examples/ffi/cpprust/build.rs create mode 100644 examples/ffi/cpprust/src/animal.hpp create mode 100644 examples/ffi/cpprust/src/lib.rs create mode 100644 examples/ffi/cpprust/src/main.cpp create mode 100644 examples/ffi/src/lib.rs diff --git a/examples/ffi/Cargo.toml b/examples/ffi/Cargo.toml new file mode 100644 index 000000000..453ff3666 --- /dev/null +++ b/examples/ffi/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "ffi" +version = "0.1.0" +edition = "2021" + +[dependencies] +cxx = "1.0" + +[build-dependencies] +cxx-build = "1.0" \ No newline at end of file diff --git a/examples/ffi/README.md b/examples/ffi/README.md new file mode 100644 index 000000000..ea79bf0dd --- /dev/null +++ b/examples/ffi/README.md @@ -0,0 +1,37 @@ +# OpenTelemetry FFI Bridge for Rust and C++ + +This code demonstrates the creation of a Foreign Function Interface (FFI) bridge between Rust and C++ using the [cxx crate](https://github.com/dtolnay/cxx). The primary goal is to facilitate interoperability between Rust and C++ codebases, particularly in the context of OpenTelemetry. + +## Code Overview + +### Create an FFI Bridge + +The cxx crate is utilized to establish an FFI bridge between Rust and C++. A Rust module named ffi is defined using the #[cxx::bridge] attribute. Within this module, a Rust struct named TracerProvider is defined. This struct encapsulates a name field and serves as a data structure that can be accessed from C++. + +An FFI function named get_tracer_provider() is declared within the extern "Rust" block. This function is designed to be callable from C++ and is expected to return a reference to a TracerProvider instance. + +### Rust TracerProvider Implementation + +A Rust struct named RustTracerProvider is introduced. This struct is designed to manage a TracerProvider instance. It includes a new() method that initializes a new RustTracerProvider with a default TracerProvider. + +### Bridging Rust and C++ with a C Wrapper for OpenTelemetry Integration + +By now CXX has some types that are intended to be supported "soon" but are just not implemented yet. + +These types are necessary for the instrumentation and configuration of the C++ and Rust interaction within the context of OpenTelemetry. + +To mitigate these issues currently, we can follow an approach by creating a C wrapper that acts as an intermediary between Rust and C++. This wrapper will handle these specific types, ensuring a smooth interaction between the two languages. + +### Creating a C Wrapper for Rust and C++ Interaction + +To address the impending types and provide a way to bridge Rust and C++ effectively, we propose the following steps: + +1. **Define the C Interface**: Begin by defining a C interface that will be accessible from both Rust and C++ codebases. This interface should include functions and structures that mirror the expected types. These functions will serve as an abstraction layer for handling the complex types. + +2. **Implement the C Wrapper**: In a separate C source file, implement the functions defined in the C interface. The implementation will act as an intermediary between Rust and C++, converting the data structures as needed and making the interaction seamless. + +3. **Expose the C Wrapper to Rust and C++**: To access the C wrapper, expose its functions through the FFI mechanisms provided by Rust and C++. This involves creating external function declarations in Rust and including the C header in the C++ codebase. + +4. **Utilize the C Wrapper**: In both the Rust and C++ code, replace the direct usage of the "soon-to-be-supported" types with calls to the C wrapper's functions. This ensures that data is properly converted and handled, regardless of the current limitations of CXX. + +By adopting this approach, we can ensure a reliable and consistent interaction between Rust and C++ while awaiting the full support of the intended types in CXX. This strategy not only mitigates the current issues but also paves the way for a smoother transition once the desired types are officially implemented. \ No newline at end of file diff --git a/examples/ffi/cpprust/.gitignore b/examples/ffi/cpprust/.gitignore new file mode 100644 index 000000000..2ebc5ea07 --- /dev/null +++ b/examples/ffi/cpprust/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock \ No newline at end of file diff --git a/examples/ffi/cpprust/Cargo.toml b/examples/ffi/cpprust/Cargo.toml new file mode 100644 index 000000000..8c13cf27e --- /dev/null +++ b/examples/ffi/cpprust/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "cpprust" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +cxx = "1.0" +log = "0.4" +env_logger = "0.9" + +[build-dependencies] +cxx-build = "1.0" \ No newline at end of file diff --git a/examples/ffi/cpprust/README.md b/examples/ffi/cpprust/README.md new file mode 100644 index 000000000..ea28c9d7b --- /dev/null +++ b/examples/ffi/cpprust/README.md @@ -0,0 +1,29 @@ +# Rust and C++ Logging Interop Benchmark + +This section contains a benchmarking program that evaluates the performance of using the Foreign Function Interface (FFI) to pass logging data between Rust and C++. The primary focus is to compare the FFI cost when logging data from C++ to Rust against using a logging library directly in C++. + +## Benchmark Results + +The benchmark results showcase the execution time and CPU cycles for various logging scenarios. Each benchmark assesses the impact of using the Foreign Function Interface (FFI) to pass data between Rust and C++ for logging operations. + +| Benchmark | Time (ns) | CPU (ns) | Iterations | +|------------------------------------------|-----------|----------|----------------| +| BM_log_string_from_cpp_to_rust_log_crate | 0.821 | 0.758 | 924,897,039 | +| BM_log_int_from_cpp_to_rust_log_crate | 0.859 | 0.793 | 900,003,214 | +| BM_log_vector_from_cpp_to_rust_log_crate | 0.822 | 0.759 | 910,954,225 | +| BM_log_struct_from_cpp_to_rust_log_crate | 0.748 | 0.691 | 1,000,000,000 | +| BM_log_class_from_cpp_to_rust_log_crate | 1.92 | 1.78 | 388,112,879 | + +## Analysis + +### FFI Cost Comparison + +The benchmark results reveal that utilizing the Foreign Function Interface (FFI) to interface between Rust and C++ for logging introduces a moderate increase in execution time and CPU cycles, approximately 70-80% higher than directly using a logging library in C++. + +### Real-world Context + +In practical logging scenarios where logs are typically transmitted to files or over networks, the FFI overhead remains inconsequential. For instance, considering a situation where 1,000,000 log records are sent per second, the added FFI interop layer contributes a mere 3 to 12 CPU cycles per log API invocation. Cumulatively, this additional computational impact translates to approximately 1% of the total CPU cycles, which is highly affordable and well within acceptable limits for efficient logging operations. + +## Conclusion + +The findings from the benchmarking exercise underscore the efficiency and practicality of employing FFI for logging purposes. While there exists a measured increase in execution time and CPU cycles, the overall impact remains negligible and aligns well with real-world logging scenarios. The interoperation between Rust and C++ using FFI proves to be a viable and efficient solution, providing a seamless bridge for logging tasks with minimal performance overhead. diff --git a/examples/ffi/cpprust/build.rs b/examples/ffi/cpprust/build.rs new file mode 100644 index 000000000..1bcff3487 --- /dev/null +++ b/examples/ffi/cpprust/build.rs @@ -0,0 +1,9 @@ +fn main() +{ + cxx_build::bridge("src/lib.rs") + .file("src/animal.hpp") + .compile("cpp_from_rust"); + + println!("cargo:rerun-if-changed=src/lib.rs"); + println!("cargo:rerun-if-changed=src/animal.hpp"); +} \ No newline at end of file diff --git a/examples/ffi/cpprust/src/animal.hpp b/examples/ffi/cpprust/src/animal.hpp new file mode 100644 index 000000000..3fecd4642 --- /dev/null +++ b/examples/ffi/cpprust/src/animal.hpp @@ -0,0 +1,8 @@ +class Animal { + public: + Animal(int age) : value(age) {} + int get_age() const {return value;} + + private: + int value; +}; \ No newline at end of file diff --git a/examples/ffi/cpprust/src/lib.rs b/examples/ffi/cpprust/src/lib.rs new file mode 100644 index 000000000..bfcdbb3c4 --- /dev/null +++ b/examples/ffi/cpprust/src/lib.rs @@ -0,0 +1,56 @@ +#[macro_use] +extern crate log; +extern crate env_logger; +use cxx::{CxxString, CxxVector}; + +#[cxx::bridge] +mod ffi { + struct Animal { + value: i32, + } + + struct Person { + name: String, + age: i32, + } + + extern "Rust" { + fn log_string_from_cpp_to_rust_log_crate(message: &CxxString); + fn log_int_from_cpp_to_rust_log_crate(level: i32); + fn log_vector_from_cpp_to_rust_log_crate(attributes: &CxxVector); + fn log_struct_from_cpp_to_rust_log_crate(person: &Person); + fn log_class_from_cpp_to_rust_log_crate(animal: &Animal); + fn init_rust_logger() -> (); + } + + unsafe extern "C++" { + include!("cpprust/src/animal.hpp"); + type Animal; + fn get_age(&self) -> i32; + } +} + +pub fn log_string_from_cpp_to_rust_log_crate(message: &CxxString) { + info!("{}", message); +} + +pub fn log_int_from_cpp_to_rust_log_crate(level: i32) { + info!("{}", level); +} + +pub fn log_vector_from_cpp_to_rust_log_crate(attributes: &CxxVector) { + info!("{:?}", attributes); +} + +pub fn log_struct_from_cpp_to_rust_log_crate(person: &ffi::Person) { + info!("Received persons: {} who is {} years old", person.name, person.age); +} + +pub fn log_class_from_cpp_to_rust_log_crate(animal: &ffi::Animal) { + let value = animal.get_age(); + info!("{}", value); +} + +pub fn init_rust_logger() -> () { + env_logger::init(); +} \ No newline at end of file diff --git a/examples/ffi/cpprust/src/main.cpp b/examples/ffi/cpprust/src/main.cpp new file mode 100644 index 000000000..3c6970a04 --- /dev/null +++ b/examples/ffi/cpprust/src/main.cpp @@ -0,0 +1,60 @@ +#include "cpprust/src/lib.rs.h" +#include +#include +#include +#include + +static void BM_log_string_from_cpp_to_rust_log_crate(benchmark::State& state) { + std::string message = "Test"; + for (auto _ : state) { + log_string_from_cpp_to_rust_log_crate(message); + } +} + +static void BM_log_int_from_cpp_to_rust_log_crate(benchmark::State& state) { + int level = 1; + + for (auto _ : state) { + log_int_from_cpp_to_rust_log_crate(level); + } +} + +static void BM_log_vector_from_cpp_to_rust_log_crate(benchmark::State& state) { + std::vector names = {"Alice", "Bob", "Charlie"}; + + for (auto _ : state) { + log_vector_from_cpp_to_rust_log_crate(names); + } +} + +static void BM_log_struct_from_cpp_to_rust_log_crate(benchmark::State& state) { + Person p1; + p1.name = "John"; + p1.age = 30; + + for(auto _ : state) { + log_struct_from_cpp_to_rust_log_crate(p1); + } +} + +static void BM_log_class_from_cpp_to_rust_log_crate(benchmark::State& state) { + Animal dog(42); + + for(auto _ : state) { + log_class_from_cpp_to_rust_log_crate(dog); + } +} + +BENCHMARK(BM_log_string_from_cpp_to_rust_log_crate); +BENCHMARK(BM_log_int_from_cpp_to_rust_log_crate); +BENCHMARK(BM_log_vector_from_cpp_to_rust_log_crate); +BENCHMARK(BM_log_struct_from_cpp_to_rust_log_crate); +BENCHMARK(BM_log_class_from_cpp_to_rust_log_crate); + +int main(int argc, char** argv) { + init_rust_logger(); + ::benchmark::Initialize(&argc, argv); + ::benchmark::RunSpecifiedBenchmarks(); + + return 0; +} \ No newline at end of file diff --git a/examples/ffi/src/lib.rs b/examples/ffi/src/lib.rs new file mode 100644 index 000000000..6a0fab6c3 --- /dev/null +++ b/examples/ffi/src/lib.rs @@ -0,0 +1,30 @@ +use opentelemetry::sdk::trace::TracerProvider; + +#[cxx::bridge] +mod ffi { + struct TracerProvider { + name: String, + } + + extern "Rust" { + fn get_tracer_provider() -> &TracerProvider; + } +} + +#[derive(Default)] +pub struct RustTracerProvider { + provider: TracerProvider, +} + +impl RustTracerProvider { + pub fn new() -> Self { + Self { + provider: TracerProvider::default(), + } + } +} + +pub fn get_tracer_provider() -> *mut TracerProvider { + let provider = Box::new(RustTracerProvider::new().provider); + Box::into_raw(provider) +} \ No newline at end of file From 12c911f53c2ba8ed034fe4b72f3e4aa92286aa39 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Fri, 25 Aug 2023 23:31:40 -0700 Subject: [PATCH 69/77] Update opentelemetry-cpp to v1.11.0 (#319) --- exporters/geneva-trace/third_party/opentelemetry-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exporters/geneva-trace/third_party/opentelemetry-cpp b/exporters/geneva-trace/third_party/opentelemetry-cpp index 95f6c66de..11d5d9e0d 160000 --- a/exporters/geneva-trace/third_party/opentelemetry-cpp +++ b/exporters/geneva-trace/third_party/opentelemetry-cpp @@ -1 +1 @@ -Subproject commit 95f6c66de253e46d09b232facc840b311a4a354d +Subproject commit 11d5d9e0d8fd8ba876c8994714cc2647479b6574 From aaa51e2297bcb34297f3c7aa44fa790497d2f7f3 Mon Sep 17 00:00:00 2001 From: Muhammad Falak R Wani Date: Sun, 27 Aug 2023 13:19:49 +0530 Subject: [PATCH 70/77] instrumentation/nginx: include batch_span_processor_options to fix build (#314) Signed-off-by: Muhammad Falak R Wani --- instrumentation/nginx/src/otel_ngx_module.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/nginx/src/otel_ngx_module.cpp b/instrumentation/nginx/src/otel_ngx_module.cpp index b94b9725e..fa303dcae 100644 --- a/instrumentation/nginx/src/otel_ngx_module.cpp +++ b/instrumentation/nginx/src/otel_ngx_module.cpp @@ -27,6 +27,7 @@ extern ngx_module_t otel_ngx_module; #include #include #include +#include #include #include #include From 6bb1c6b962f6794281f28125432027a385c0ac01 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Mon, 11 Sep 2023 17:00:49 -0700 Subject: [PATCH 71/77] Fix missing the copy source folder for Geneva exporter INSTALL doc (#326) --- exporters/geneva/INSTALL.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exporters/geneva/INSTALL.md b/exporters/geneva/INSTALL.md index 04df8444e..4806b7880 100644 --- a/exporters/geneva/INSTALL.md +++ b/exporters/geneva/INSTALL.md @@ -102,9 +102,9 @@ for instructions. 1. Create the following directory structure in the root directory of the application. Clone the opentelemetry-cpp and opentelemetry-cpp-contrib under the `deps` directory as given below. And -copy the script and patch file from to the `tools` directory. +copy the script and patch file from the `build_tools` directory to the `tools` directory. - ``` + ```console # # | # - tools @@ -119,7 +119,7 @@ copy the script and patch file from to the `tools` directory. # - opentelemetry-cpp-contrib/exporters/geneva # ``` -2. Execute `build_geneva_metrics_exporter.sh` script from the `tools` directory +2. Execute `build_geneva_metrics_exporter.sh` script from the `tools` directory. ```console $ cd /tools && ./build_geneva_metrics_exporter.sh From fb746d76d3c8bd4a2dd88b9b65f9d3a6ab928787 Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Wed, 13 Sep 2023 19:46:06 +0800 Subject: [PATCH 72/77] Update prometheus to support otel-cpp 1.11.0 and bazel 6 (#295) * Update prometheus to support otel-cpp 1.9.1 and bazel 6 Signed-off-by: WenTao Ou * Fix dependency Signed-off-by: WenTao Ou * Use cmake to check MSVC building. Signed-off-by: WenTao Ou * Fix windows CI script Signed-off-by: WenTao Ou * Fix build directory conflict Signed-off-by: WenTao Ou * Fix OOM in ci jobs. Signed-off-by: WenTao Ou * Update otel to 1.11.0 for PrometheusPushExporter, add factory for PrometheusPushExporter --------- Signed-off-by: WenTao Ou --- .github/workflows/prometheus.yml | 57 ++-- exporters/prometheus/.clang-format | 61 ++++ exporters/prometheus/.cmake-format.py | 7 + exporters/prometheus/BUILD | 4 + exporters/prometheus/CMakeLists.txt | 10 +- exporters/prometheus/WORKSPACE | 4 + .../exporters/prometheus/push_exporter.h | 85 +++--- .../prometheus/push_exporter_factory.h | 34 +++ .../prometheus/push_exporter_options.h | 37 +++ exporters/prometheus/repository.bzl | 35 ++- exporters/prometheus/src/push_exporter.cc | 269 +++++++++++++++--- .../prometheus/src/push_exporter_factory.cc | 29 ++ .../prometheus/test/prometheus_test_helper.h | 190 ++++++++----- .../prometheus/test/push_exporter_test.cc | 93 ++++-- 14 files changed, 711 insertions(+), 204 deletions(-) create mode 100644 exporters/prometheus/.clang-format create mode 100644 exporters/prometheus/.cmake-format.py create mode 100644 exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_factory.h create mode 100644 exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_options.h create mode 100644 exporters/prometheus/src/push_exporter_factory.cc diff --git a/.github/workflows/prometheus.yml b/.github/workflows/prometheus.yml index cf9539e65..7aa9e8fd5 100644 --- a/.github/workflows/prometheus.yml +++ b/.github/workflows/prometheus.yml @@ -53,25 +53,44 @@ jobs: cd otel_cpp_contrib/exporters/prometheus bazel --output_user_root=$HOME/.cache/bazel build --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... bazel --output_user_root=$HOME/.cache/bazel test --copt=-DENABLE_TEST --@io_opentelemetry_cpp//api:with_abseil //... - prometheus_bazel_window: - name: Bazel on Windows + prometheus_cmake_window: + name: CMake on Windows runs-on: windows-latest steps: - name: checkout otel contrib prometheus uses: actions/checkout@v3 with: path: "otel_cpp_contrib" + - name: checkout otel cpp + uses: actions/checkout@v3 + with: + repository: "open-telemetry/opentelemetry-cpp" + ref: "v1.11.0" + path: "otel_cpp" + submodules: "recursive" - name: run tests shell: pwsh run: | New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" ` -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force - $RUNNER_ROOT_PATH = Split-Path (Split-Path (Get-Location)) - Set-Location otel_cpp_contrib/exporters/prometheus - & bazel --windows_enable_symlinks "--output_user_root=$RUNNER_ROOT_PATH/bazel_build" ` - build --copt=-DENABLE_TEST --copt=/utf-8 --sandbox_debug --@io_opentelemetry_cpp//api:with_abseil //... - & bazel --windows_enable_symlinks "--output_user_root=$RUNNER_ROOT_PATH/bazel_build" ` - test --copt=-DENABLE_TEST --copt=/utf-8 --sandbox_debug --@io_opentelemetry_cpp//api:with_abseil //... + vcpkg install "prometheus-cpp[pull,push]" nlohmann-json gtest benchmark --triplet=x64-windows-static-md + New-Item -Path "$ENV:GITHUB_WORKSPACE/otel_cpp/build_jobs_ci" -ItemType "directory" -Force + Set-Location "$ENV:GITHUB_WORKSPACE/otel_cpp/build_jobs_ci" + cmake .. -DWITH_PROMETHEUS=ON -DWITH_METRICS_PREVIEW=OFF -DCMAKE_BUILD_TYPE=Debug ` + -DVCPKG_TARGET_TRIPLET=x64-windows-static-md ` + "-DCMAKE_TOOLCHAIN_FILE=$ENV:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" ` + "-DCMAKE_INSTALL_PREFIX=$HOME/prebuilt-otel" ` + "-DBUILD_SHARED_LIBS=OFF" "-DBUILD_TESTING=OFF" "-DWITH_EXAMPLES=OFF" "-DWITH_FUNC_TESTS=OFF" + cmake --build . -j --config Debug || cmake --build . -j2 --config Debug || cmake --build . --config Debug + cmake --install . --prefix "$HOME/prebuilt-otel" --config Debug + New-Item -Path "$ENV:GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build_jobs_ci" -ItemType "directory" -Force + Set-Location "$ENV:GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build_jobs_ci" + cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" -DCMAKE_BUILD_TYPE=Debug ` + -DVCPKG_TARGET_TRIPLET=x64-windows-static-md ` + "-DCMAKE_TOOLCHAIN_FILE=$ENV:VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" ` + "-DBUILD_SHARED_LIBS=OFF" + cmake --build . -j --config Debug || cmake --build . -j2 --config Debug || cmake --build . --config Debug + ctest -VV -C Debug -R "opentelemetry_cpp_ecosystem_test.*" . prometheus_cmake_linux: name: CMake on Linux runs-on: ubuntu-latest @@ -84,7 +103,7 @@ jobs: uses: actions/checkout@v3 with: repository: "open-telemetry/opentelemetry-cpp" - ref: "v1.6.1" + ref: "v1.11.0" path: "otel_cpp" submodules: "recursive" - name: setup @@ -94,18 +113,20 @@ jobs: ca-certificates wget git valgrind lcov - name: run tests run: | - vcpkg install prometheus-cpp[pull,push] nlohmann-json GTest Benchmark --triplet=x64-linux - mkdir -p "$GITHUB_WORKSPACE/otel_cpp/build" - cd "$GITHUB_WORKSPACE/otel_cpp/build" + vcpkg install 'prometheus-cpp[pull,push]' nlohmann-json gtest benchmark --triplet=x64-linux + mkdir -p "$GITHUB_WORKSPACE/otel_cpp/build_jobs_ci" + cd "$GITHUB_WORKSPACE/otel_cpp/build_jobs_ci" cmake .. -DWITH_PROMETHEUS=ON -DWITH_METRICS_PREVIEW=OFF -DCMAKE_BUILD_TYPE=Debug \ -DVCPKG_TARGET_TRIPLET=x64-linux \ - "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" - cmake --build . -j --config Debug + "-DCMAKE_INSTALL_PREFIX=$HOME/prebuilt-otel" \ + "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" \ + "-DBUILD_TESTING=OFF" "-DWITH_EXAMPLES=OFF" "-DWITH_FUNC_TESTS=OFF" + cmake --build . -j --config Debug || cmake --build . -j2 --config Debug || cmake --build . --config Debug cmake --install . --prefix "$HOME/prebuilt-otel" --config Debug - mkdir -p "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build" - cd "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build" + mkdir -p "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build_jobs_ci" + cd "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/prometheus/build_jobs_ci" cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" -DCMAKE_BUILD_TYPE=Debug \ -DVCPKG_TARGET_TRIPLET=x64-linux \ - "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" - cmake --build . -j --config Debug + "-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" + cmake --build . -j --config Debug || cmake --build . -j2 --config Debug || cmake --build . --config Debug ctest -VV -R "opentelemetry_cpp_ecosystem_test.*" . diff --git a/exporters/prometheus/.clang-format b/exporters/prometheus/.clang-format new file mode 100644 index 000000000..2640295e6 --- /dev/null +++ b/exporters/prometheus/.clang-format @@ -0,0 +1,61 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# See Clang docs: http://clang.llvm.org/docs/ClangFormatStyleOptions.html +BasedOnStyle: Chromium + +# Allow double brackets such as std::vector>. +Standard: Cpp11 + +# Indent 2 spaces at a time. +IndentWidth: 2 + +# Keep lines under 100 columns long. +ColumnLimit: 100 + +# Always break before braces +BreakBeforeBraces: Custom +BraceWrapping: +# TODO(lujc) wait for clang-format-9 support in Chromium tools +# AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false + + # Keeps extern "C" blocks unindented. + AfterExternBlock: false + +# Indent case labels. +IndentCaseLabels: true + +# Right-align pointers and references +PointerAlignment: Right + +# ANGLE likes to align things as much as possible. +AlignOperands: true +AlignConsecutiveAssignments: true + +# Use 2 space negative offset for access modifiers +AccessModifierOffset: -2 + +# TODO(jmadill): Decide if we want this on. Doesn't have an "all or none" mode. +AllowShortCaseLabelsOnASingleLine: false + +# Useful for spacing out functions in classes +KeepEmptyLinesAtTheStartOfBlocks: true + +# Indent nested PP directives. +IndentPPDirectives: AfterHash + +# Include blocks style +IncludeBlocks: Preserve diff --git a/exporters/prometheus/.cmake-format.py b/exporters/prometheus/.cmake-format.py new file mode 100644 index 000000000..d232ac8eb --- /dev/null +++ b/exporters/prometheus/.cmake-format.py @@ -0,0 +1,7 @@ +# Copyright The OpenTelemetry Authors +# SPDX-License-Identifier: Apache-2.0 + +# If comment markup is enabled, don't reflow the first comment block in +# eachlistfile. Use this to preserve formatting of your +# copyright/licensestatements. +first_comment_is_literal = True diff --git a/exporters/prometheus/BUILD b/exporters/prometheus/BUILD index 0c25dab7e..b47b83129 100644 --- a/exporters/prometheus/BUILD +++ b/exporters/prometheus/BUILD @@ -4,9 +4,12 @@ cc_library( name = "prometheus_push_exporter", srcs = [ "src/push_exporter.cc", + "src/push_exporter_factory.cc", ], hdrs = [ "include/opentelemetry/exporters/prometheus/push_exporter.h", + "include/opentelemetry/exporters/prometheus/push_exporter_factory.h", + "include/opentelemetry/exporters/prometheus/push_exporter_options.h", ], strip_include_prefix = "include", tags = ["prometheus"], @@ -17,6 +20,7 @@ cc_library( "@io_opentelemetry_cpp//exporters/prometheus:prometheus_collector", "@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter_utils", "@io_opentelemetry_cpp//sdk:headers", + "@io_opentelemetry_cpp//sdk/src/metrics", ], ) diff --git a/exporters/prometheus/CMakeLists.txt b/exporters/prometheus/CMakeLists.txt index bf8b702a7..8b9439d3d 100644 --- a/exporters/prometheus/CMakeLists.txt +++ b/exporters/prometheus/CMakeLists.txt @@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.12) project( opentelemetry-cpp-contrib - VERSION "1.6.1" # opentelemetry-cpp-contrib 1.6.1 + VERSION "1.11.0" # opentelemetry-cpp-contrib 1.11.0 HOMEPAGE_URL "https://github.com/open-telemetry/opentelemetry-cpp-contrib" LANGUAGES CXX) @@ -79,7 +79,7 @@ if(BUILD_TESTING) endif() endif() -add_library(opentelemetry_prometheus_push_exporter src/push_exporter.cc) +add_library(opentelemetry_prometheus_push_exporter src/push_exporter.cc src/push_exporter_factory.cc) set_target_properties(opentelemetry_prometheus_push_exporter PROPERTIES EXPORT_NAME prometheus_push_exporter) @@ -93,6 +93,12 @@ target_link_libraries( PUBLIC opentelemetry-cpp::prometheus_exporter opentelemetry-cpp::metrics opentelemetry-cpp::resources prometheus-cpp::push prometheus-cpp::core) +target_compile_definitions( + opentelemetry_prometheus_push_exporter + PUBLIC "OPENTELEMTRY_CPP_MAJOR_VERSION=${opentelemetry-cpp_VERSION_MAJOR}" + "OPENTELEMTRY_CPP_MINOR_VERSION=${opentelemetry-cpp_VERSION_MINOR}" + "OPENTELEMTRY_CPP_PATCH_VERSION=${opentelemetry-cpp_VERSION_PATCH}") + if(DEFINED VCPKG_CMAKE_SYSTEM_NAME AND VCPKG_CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") set(OPENTELEMETRY_CPP_CONTRIB_TARGET_IS_WINDOWS ON) diff --git a/exporters/prometheus/WORKSPACE b/exporters/prometheus/WORKSPACE index 955b85663..01dc0aa5c 100644 --- a/exporters/prometheus/WORKSPACE +++ b/exporters/prometheus/WORKSPACE @@ -24,6 +24,10 @@ load("@io_opentelemetry_cpp//bazel:repository.bzl", "opentelemetry_cpp_deps") # Load dependencies of opentelemetry-cpp opentelemetry_cpp_deps() +load("@io_opentelemetry_cpp//bazel:extra_deps.bzl", "opentelemetry_extra_deps") + +opentelemetry_extra_deps() + # Load prometheus C++ dependencies. load("@com_github_jupp0r_prometheus_cpp//bazel:repositories.bzl", "prometheus_cpp_repositories") diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h index 3d6151475..de7e06378 100644 --- a/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter.h @@ -1,48 +1,49 @@ -// Copyright 2022, OpenTelemetry Authors +// Copyright 2023, OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #pragma once -# ifdef _WIN32 -# include // NOLINT -# include // NOLINT -# else -# include // NOLINT -# endif +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif -# include -# include -# include -# include +#ifndef NOMINMAX +# define NOMINMAX +#endif -# include "prometheus/gateway.h" +#ifdef _WIN32 +# include // NOLINT +# include // NOLINT +#else +# include // NOLINT +#endif + +#include +#include +#include +#include + +#include "prometheus/gateway.h" + +#include "opentelemetry/exporters/prometheus/exporter_utils.h" +#include "opentelemetry/exporters/prometheus/push_exporter_options.h" +#include "opentelemetry/nostd/span.h" +#include "opentelemetry/sdk/common/env_variables.h" +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/version.h" -# include "opentelemetry/exporters/prometheus/collector.h" -# include "opentelemetry/nostd/span.h" -# include "opentelemetry/sdk/common/env_variables.h" -# include "opentelemetry/sdk/metrics/metric_exporter.h" -# include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE -namespace exporter { -namespace metrics { -/** - * Struct to hold Prometheus exporter options. - */ -struct PrometheusPushExporterOptions { - std::string host; - std::string port; - std::string jobname; - ::prometheus::Labels labels; - std::string username; - std::string password; - - ::opentelemetry::sdk::metrics::AggregationTemporality aggregation_temporality = - ::opentelemetry::sdk::metrics::AggregationTemporality::kDelta; -}; +namespace exporter +{ +namespace metrics +{ + +class PrometheusPushCollector; -class PrometheusPushExporter : public ::opentelemetry::sdk::metrics::MetricExporter { - public: +class PrometheusPushExporter : public ::opentelemetry::sdk::metrics::PushMetricExporter +{ +public: /** * Constructor - binds an exposer and collector to the exporter * @param options: options for an exposer that exposes @@ -69,7 +70,8 @@ class PrometheusPushExporter : public ::opentelemetry::sdk::metrics::MetricExpor /** * Force flush the exporter. */ - bool ForceFlush(std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; + bool ForceFlush( + std::chrono::microseconds timeout = (std::chrono::microseconds::max)()) noexcept override; /** * Shuts down the exporter and does cleanup. @@ -81,17 +83,18 @@ class PrometheusPushExporter : public ::opentelemetry::sdk::metrics::MetricExpor bool Shutdown(std::chrono::microseconds timeout = std::chrono::microseconds(0)) noexcept override; /** - * @return: returns a shared_ptr to - * the PrometheusCollector instance + * Gets the maximum size of the collection. + * + * @return max collection size */ - std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector> &GetCollector(); + std::size_t GetMaxCollectionSize() const noexcept; /** * @return: Gets the shutdown status of the exporter */ bool IsShutdown() const; - private: +private: // The configuration options associated with this exporter. const PrometheusPushExporterOptions options_; /** @@ -103,7 +106,7 @@ class PrometheusPushExporter : public ::opentelemetry::sdk::metrics::MetricExpor * Pointer to a * PrometheusCollector instance */ - std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector> collector_; + std::shared_ptr collector_; /** * Pointer to an diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_factory.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_factory.h new file mode 100644 index 000000000..a529a3f53 --- /dev/null +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_factory.h @@ -0,0 +1,34 @@ +// Copyright 2023, OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include + +#include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace metrics +{ + +struct PrometheusPushExporterOptions; + +/** + * Factory class for PrometheusExporter. + */ +class PrometheusPushExporterFactory +{ +public: + /** + * Create a PrometheusExporter using the given options. + */ + static std::unique_ptr Create( + const PrometheusPushExporterOptions &options); +}; + +} // namespace metrics +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_options.h b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_options.h new file mode 100644 index 000000000..e6d8f2371 --- /dev/null +++ b/exporters/prometheus/include/opentelemetry/exporters/prometheus/push_exporter_options.h @@ -0,0 +1,37 @@ +// Copyright 2023, OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once + +#include +#include +#include + +#include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace metrics +{ + +/** + * Struct to hold Prometheus exporter options. + */ +struct PrometheusPushExporterOptions +{ + std::string host; + std::string port; + std::string jobname; + std::unordered_map labels; + std::string username; + std::string password; + + std::size_t max_collection_size = 2000; + + inline PrometheusPushExporterOptions() noexcept {} +}; + +} // namespace metrics +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/repository.bzl b/exporters/prometheus/repository.bzl index 6c6ef227e..440093048 100644 --- a/exporters/prometheus/repository.bzl +++ b/exporters/prometheus/repository.bzl @@ -19,10 +19,10 @@ def io_opentelemetry_cpp_contrib_deps(): maybe( http_archive, name = "io_opentelemetry_cpp", - sha256 = "1fc371be049b3220b8b9571c8b713f03e9a84f3c5684363f64ccc814638391a5", - strip_prefix = "opentelemetry-cpp-1.6.1", + sha256 = "f30cd88bf898a5726d245eba882b8e81012021eb00df34109f4dfb203f005cea", + strip_prefix = "opentelemetry-cpp-1.11.0", urls = [ - "https://github.com/open-telemetry/opentelemetry-cpp/archive/v1.6.1.tar.gz", + "https://github.com/open-telemetry/opentelemetry-cpp/archive/v1.11.0.tar.gz", ], ) @@ -30,10 +30,24 @@ def io_opentelemetry_cpp_contrib_deps(): maybe( http_archive, name = "com_github_jupp0r_prometheus_cpp", - sha256 = "593e028d401d3298eada804d252bc38d8cab3ea1c9e88bcd72095281f85e6d16", - strip_prefix = "prometheus-cpp-1.0.1", + sha256 = "b4eff62bcdba10efd6210b9fa8a5b2505ad8ea6c211968be79aeb2c4c2f97338", + # strip_prefix = "prometheus-cpp-1.1.0", + # 1.1.0 with bazel 6 support + strip_prefix = "prometheus-cpp-81e208c250748657f1d5dab247e82c4429a931af", urls = [ - "https://github.com/jupp0r/prometheus-cpp/archive/refs/tags/v1.0.1.tar.gz", + # "https://github.com/jupp0r/prometheus-cpp/archive/refs/tags/v1.1.0.tar.gz", + "https://github.com/jupp0r/prometheus-cpp/archive/81e208c250748657f1d5dab247e82c4429a931af.tar.gz", + ], + ) + + # bazel platforms + maybe( + http_archive, + name = "platforms", + sha256 = "5308fc1d8865406a49427ba24a9ab53087f17f5266a7aabbfc28823f3916e1ca", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.6/platforms-0.0.6.tar.gz", + "https://github.com/bazelbuild/platforms/releases/download/0.0.6/platforms-0.0.6.tar.gz", ], ) @@ -65,3 +79,12 @@ def io_opentelemetry_cpp_contrib_deps(): # "https://github.com/google/googletest/archive/release-1.10.0.tar.gz", ], ) + + # Some versions of GoogleTest depend com_googlesource_code_re2. + maybe( + http_archive, + name = "com_googlesource_code_re2", # 2023-06-01 + sha256 = "1726508efc93a50854c92e3f7ac66eb28f0e57652e413f11d7c1e28f97d997ba", + strip_prefix = "re2-03da4fc0857c285e3a26782f6bc8931c4c950df4", + urls = ["https://github.com/google/re2/archive/03da4fc0857c285e3a26782f6bc8931c4c950df4.zip"], + ) diff --git a/exporters/prometheus/src/push_exporter.cc b/exporters/prometheus/src/push_exporter.cc index 1a4ca1a61..cbd874816 100644 --- a/exporters/prometheus/src/push_exporter.cc +++ b/exporters/prometheus/src/push_exporter.cc @@ -1,23 +1,195 @@ -// Copyright 2022, OpenTelemetry Authors +// Copyright 2023, OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -# include "opentelemetry/exporters/prometheus/push_exporter.h" +#include "opentelemetry/exporters/prometheus/push_exporter.h" + +#include + +#include +#include +#include +#include OPENTELEMETRY_BEGIN_NAMESPACE -namespace exporter { -namespace metrics { +namespace exporter +{ +namespace metrics +{ + +namespace +{ +static std::string SanitizePrometheusNames(std::string name, bool label) +{ + constexpr const auto replacement = '_'; + constexpr const auto replacement_dup = '='; + + bool (*valid)(std::size_t, char); + if (label) + { + valid = [](std::size_t i, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9' && i > 0)) + { + return true; + } + return false; + }; + } + else + { + valid = [](std::size_t i, char c) { + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == ':' || + (c >= '0' && c <= '9' && i > 0)) + { + return true; + } + return false; + }; + } + + bool has_dup = false; + for (std::size_t i = 0; i < name.size(); ++i) + { + if (valid(i, name[i])) + { + continue; + } + if (i > 0 && (name[i - 1] == replacement || name[i - 1] == replacement_dup)) + { + has_dup = true; + name[i] = replacement_dup; + } + else + { + name[i] = replacement; + } + } + if (has_dup) + { + auto end = std::remove(name.begin(), name.end(), replacement_dup); + return std::string{name.begin(), end}; + } + + return name; +} +} // namespace + +class PrometheusPushCollector : public ::prometheus::Collectable +{ +public: + /** + * Default Constructor. + * + * This constructor initializes the collection for metrics to export + * in this class with default capacity + */ + explicit PrometheusPushCollector(std::size_t max_collection_size = 2048) + : max_collection_size_(max_collection_size) + { + metrics_to_collect_.reserve(max_collection_size_.load(std::memory_order_acquire)); + } + + /** + * Collects all metrics data from metricsToCollect collection. + * + * @return all metrics in the metricsToCollect snapshot + */ + std::vector<::prometheus::MetricFamily> Collect() const override + { + if (!collection_lock_.try_lock()) + { + return {}; + } + + // copy the intermediate collection, and then clear it + std::vector<::prometheus::MetricFamily> moved_data; + moved_data.swap(metrics_to_collect_); + metrics_to_collect_.reserve(max_collection_size_.load(std::memory_order_acquire)); + + collection_lock_.unlock(); + + return moved_data; + } + + /** + * This function is called by export() function and add the collection of + * records to the metricsToCollect collection + * + * @param records a collection of records to add to the metricsToCollect + * collection + */ + void AddMetricData(const ::opentelemetry::sdk::metrics::ResourceMetrics &data) + { + auto translated = + ::opentelemetry::exporter::metrics::PrometheusExporterUtils::TranslateToPrometheus(data); + + std::lock_guard guard{collection_lock_}; + + for (auto &item : translated) + { + if (metrics_to_collect_.size() + 1 <= max_collection_size_.load(std::memory_order_acquire)) + { + // We can not use initializer lists here due to broken variadic capture + // on GCC 4.8.5 + metrics_to_collect_.emplace_back(std::move(item)); + } + } + } + + /** + * Get the current collection in the collector. + * + * @return the current metricsToCollect collection + */ + std::vector<::prometheus::MetricFamily> &GetCollection() { return metrics_to_collect_; } + + /** + * Gets the maximum size of the collection. + * + * @return max collection size + */ + std::size_t GetMaxCollectionSize() const noexcept + { + return max_collection_size_.load(std::memory_order_acquire); + } + +private: + /** + * Collection of metrics data from the export() function, and to be export + * to user when they send a pull request. This collection is a pointer + * to a collection so Collect() is able to clear the collection, even + * though it is a const function. + */ + mutable std::vector<::prometheus::MetricFamily> metrics_to_collect_; + + /** + * Maximum size of the metricsToCollect collection. + */ + std::atomic max_collection_size_; + + /* + * Lock when operating the metricsToCollect collection + */ + mutable std::mutex collection_lock_; +}; + /** * Constructor - binds an exposer and collector to the exporter * @param address: an address for an exposer that exposes * an HTTP endpoint for the exporter to connect to */ PrometheusPushExporter::PrometheusPushExporter(const PrometheusPushExporterOptions &options) - : options_(options), is_shutdown_(false) { - gateway_ = std::unique_ptr<::prometheus::Gateway>(new ::prometheus::Gateway{ - options_.host, options_.port, options_.jobname, options_.labels, options_.username, options_.password}); - collector_ = std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector>( - new ::opentelemetry::exporter::metrics::PrometheusCollector); + : options_(options), is_shutdown_(false) +{ + ::prometheus::Labels labels; + for (auto &label : options_.labels) + { + labels[SanitizePrometheusNames(label.first, true)] = label.second; + } + gateway_ = std::unique_ptr<::prometheus::Gateway>( + new ::prometheus::Gateway{options_.host, options_.port, options_.jobname, labels, + options_.username, options_.password}); + collector_ = std::make_shared(options.max_collection_size); gateway_->RegisterCollectable(collector_); } @@ -26,28 +198,18 @@ PrometheusPushExporter::PrometheusPushExporter(const PrometheusPushExporterOptio * PrometheusPushExporter constructor with no parameters * Used for testing only */ -PrometheusPushExporter::PrometheusPushExporter() : is_shutdown_(false) { - collector_ = std::unique_ptr<::opentelemetry::exporter::metrics::PrometheusCollector>( - new ::opentelemetry::exporter::metrics::PrometheusCollector(3)); +PrometheusPushExporter::PrometheusPushExporter() : is_shutdown_(false) +{ + const_cast(options_).max_collection_size = 3; + collector_ = std::make_shared(options_.max_collection_size); } -::opentelemetry::sdk::metrics::AggregationTemporality PrometheusPushExporter::GetAggregationTemporality( - ::opentelemetry::sdk::metrics::InstrumentType instrument_type) const noexcept { - if (options_.aggregation_temporality == ::opentelemetry::sdk::metrics::AggregationTemporality::kCumulative) { - return options_.aggregation_temporality; - } - - switch (instrument_type) { - case ::opentelemetry::sdk::metrics::InstrumentType::kCounter: - case ::opentelemetry::sdk::metrics::InstrumentType::kObservableCounter: - case ::opentelemetry::sdk::metrics::InstrumentType::kHistogram: - case ::opentelemetry::sdk::metrics::InstrumentType::kObservableGauge: - return ::opentelemetry::sdk::metrics::AggregationTemporality::kDelta; - case ::opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter: - case ::opentelemetry::sdk::metrics::InstrumentType::kObservableUpDownCounter: - return ::opentelemetry::sdk::metrics::AggregationTemporality::kCumulative; - } - return ::opentelemetry::sdk::metrics::AggregationTemporality::kUnspecified; +::opentelemetry::sdk::metrics::AggregationTemporality + PrometheusPushExporter::GetAggregationTemporality( + ::opentelemetry::sdk::metrics::InstrumentType /*instrument_type*/) const noexcept +{ + // Prometheus exporter only support Cumulative + return ::opentelemetry::sdk::metrics::AggregationTemporality::kCumulative; } /** @@ -56,19 +218,29 @@ ::opentelemetry::sdk::metrics::AggregationTemporality PrometheusPushExporter::Ge * @return: returns a ReturnCode detailing a success, or type of failure */ ::opentelemetry::sdk::common::ExportResult PrometheusPushExporter::Export( - const ::opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept { - if (is_shutdown_) { + const ::opentelemetry::sdk::metrics::ResourceMetrics &data) noexcept +{ + if (is_shutdown_) + { return ::opentelemetry::sdk::common::ExportResult::kFailure; - } else if (collector_->GetCollection().size() + data.scope_metric_data_.size() > - static_cast(collector_->GetMaxCollectionSize())) { + } + else if (collector_->GetCollection().size() + data.scope_metric_data_.size() > + collector_->GetMaxCollectionSize()) + { return ::opentelemetry::sdk::common::ExportResult::kFailureFull; - } else if (data.scope_metric_data_.empty()) { + } + else if (data.scope_metric_data_.empty()) + { return ::opentelemetry::sdk::common::ExportResult::kFailureInvalidArgument; - } else { + } + else + { collector_->AddMetricData(data); - if (gateway_) { + if (gateway_) + { int http_code = gateway_->Push(); - if (http_code >= 200 && http_code < 300) { + if (http_code >= 200 && http_code < 300) + { return ::opentelemetry::sdk::common::ExportResult::kSuccess; } return ::opentelemetry::sdk::common::ExportResult::kFailure; @@ -77,7 +249,10 @@ ::opentelemetry::sdk::common::ExportResult PrometheusPushExporter::Export( } } -bool PrometheusPushExporter::ForceFlush(std::chrono::microseconds timeout) noexcept { return true; } +bool PrometheusPushExporter::ForceFlush(std::chrono::microseconds /*timeout*/) noexcept +{ + return true; +} /** * Shuts down the exporter and does cleanup. @@ -86,7 +261,8 @@ bool PrometheusPushExporter::ForceFlush(std::chrono::microseconds timeout) noexc * collection to to client an HTTP request being sent, * so we flush the data. */ -bool PrometheusPushExporter::Shutdown(std::chrono::microseconds timeout) noexcept { +bool PrometheusPushExporter::Shutdown(std::chrono::microseconds /*timeout*/) noexcept +{ is_shutdown_ = true; collector_->GetCollection().clear(); @@ -95,17 +271,22 @@ bool PrometheusPushExporter::Shutdown(std::chrono::microseconds timeout) noexcep } /** - * @return: returns a shared_ptr to - * the PrometheusCollector instance + * Gets the maximum size of the collection. + * + * @return max collection size */ -std::shared_ptr<::opentelemetry::exporter::metrics::PrometheusCollector> &PrometheusPushExporter::GetCollector() { - return collector_; +std::size_t PrometheusPushExporter::GetMaxCollectionSize() const noexcept +{ + return collector_->GetMaxCollectionSize(); } /** * @return: Gets the shutdown status of the exporter */ -bool PrometheusPushExporter::IsShutdown() const { return is_shutdown_; } +bool PrometheusPushExporter::IsShutdown() const +{ + return is_shutdown_; +} } // namespace metrics } // namespace exporter diff --git a/exporters/prometheus/src/push_exporter_factory.cc b/exporters/prometheus/src/push_exporter_factory.cc new file mode 100644 index 000000000..9ab365a33 --- /dev/null +++ b/exporters/prometheus/src/push_exporter_factory.cc @@ -0,0 +1,29 @@ +// Copyright 2023, OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/exporters/prometheus/push_exporter_factory.h" + +#include + +#include + +#include "opentelemetry/exporters/prometheus/push_exporter.h" +#include "opentelemetry/exporters/prometheus/push_exporter_options.h" + +OPENTELEMETRY_BEGIN_NAMESPACE + +namespace exporter +{ +namespace metrics +{ + +std::unique_ptr +PrometheusPushExporterFactory::Create(const PrometheusPushExporterOptions &options) +{ + return std::unique_ptr( + new PrometheusPushExporter(options)); +} + +} // namespace metrics +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/prometheus/test/prometheus_test_helper.h b/exporters/prometheus/test/prometheus_test_helper.h index fbc6b7bb6..35c7d6928 100644 --- a/exporters/prometheus/test/prometheus_test_helper.h +++ b/exporters/prometheus/test/prometheus_test_helper.h @@ -3,85 +3,103 @@ #pragma once -# include -# include +#include +#include -# include "opentelemetry/version.h" +#include "opentelemetry/version.h" -namespace metric_sdk = opentelemetry::sdk::metrics; -namespace nostd = opentelemetry::nostd; +namespace metric_sdk = opentelemetry::sdk::metrics; +namespace nostd = opentelemetry::nostd; namespace exportermetrics = opentelemetry::exporter::metrics; -namespace { // NOLINT +namespace +{ // NOLINT + +inline opentelemetry::sdk::resource::Resource &GetEmptyResource() +{ + static auto resource = opentelemetry::sdk::resource::Resource::Create( + opentelemetry::sdk::resource::ResourceAttributes{}); + return resource; +} + /** * Helper function to create ResourceMetrics */ -inline metric_sdk::ResourceMetrics CreateSumPointData() { +inline metric_sdk::ResourceMetrics CreateSumPointData() +{ metric_sdk::SumPointData sum_point_data{}; sum_point_data.value_ = 10.0; metric_sdk::SumPointData sum_point_data2{}; sum_point_data2.value_ = 20.0; metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", + "1.9.1"); metric_sdk::MetricData metric_data{ - metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", + metric_sdk::InstrumentType::kCounter, metric_sdk::InstrumentValueType::kDouble}, metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, opentelemetry::common::SystemTimestamp{}, - std::vector{{metric_sdk::PointAttributes{{"a1", "b1"}}, sum_point_data}, - {metric_sdk::PointAttributes{{"a2", "b2"}}, sum_point_data2}}}; + std::vector{ + {metric_sdk::PointAttributes{{"a1", "b1"}}, sum_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, sum_point_data2}}}; data.scope_metric_data_ = std::vector{ {instrumentation_scope.get(), std::vector{metric_data}}}; return data; } -inline metric_sdk::ResourceMetrics CreateHistogramPointData() { +inline metric_sdk::ResourceMetrics CreateHistogramPointData() +{ metric_sdk::HistogramPointData histogram_point_data{}; - histogram_point_data.boundaries_ = std::list{10.1, 20.2, 30.2}; - histogram_point_data.count_ = 3; - histogram_point_data.counts_ = {200, 300, 400, 500}; - histogram_point_data.sum_ = 900.5; + histogram_point_data.boundaries_ = std::vector{10.1, 20.2, 30.2}; + histogram_point_data.count_ = 3; + histogram_point_data.counts_ = {200, 300, 400, 500}; + histogram_point_data.sum_ = 900.5; metric_sdk::HistogramPointData histogram_point_data2{}; - histogram_point_data2.boundaries_ = std::list{10, 20, 30}; // NOLINT - histogram_point_data2.count_ = 3; - histogram_point_data2.counts_ = {200, 300, 400, 500}; - histogram_point_data2.sum_ = 900l; + histogram_point_data2.boundaries_ = std::vector{10, 20, 30}; // NOLINT + histogram_point_data2.count_ = 3; + histogram_point_data2.counts_ = {200, 300, 400, 500}; + histogram_point_data2.sum_ = static_cast(900); + metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", + "1.9.1"); metric_sdk::MetricData metric_data{ - metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kHistogram, + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", + metric_sdk::InstrumentType::kHistogram, metric_sdk::InstrumentValueType::kDouble}, metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, opentelemetry::common::SystemTimestamp{}, - std::vector{{metric_sdk::PointAttributes{{"a1", "b1"}}, histogram_point_data}, - {metric_sdk::PointAttributes{{"a2", "b2"}}, histogram_point_data2}}}; + std::vector{ + {metric_sdk::PointAttributes{{"a1", "b1"}}, histogram_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, histogram_point_data2}}}; data.scope_metric_data_ = std::vector{ {instrumentation_scope.get(), std::vector{metric_data}}}; return data; } -inline metric_sdk::ResourceMetrics CreateLastValuePointData() { +inline metric_sdk::ResourceMetrics CreateLastValuePointData() +{ metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", + "1.2.0"); metric_sdk::LastValuePointData last_value_point_data{}; - last_value_point_data.value_ = 10.0; + last_value_point_data.value_ = 10.0; last_value_point_data.is_lastvalue_valid_ = true; - last_value_point_data.sample_ts_ = opentelemetry::common::SystemTimestamp{}; + last_value_point_data.sample_ts_ = opentelemetry::common::SystemTimestamp{}; metric_sdk::LastValuePointData last_value_point_data2{}; - last_value_point_data2.value_ = 20l; + last_value_point_data2.value_ = static_cast(20); last_value_point_data2.is_lastvalue_valid_ = true; - last_value_point_data2.sample_ts_ = opentelemetry::common::SystemTimestamp{}; + last_value_point_data2.sample_ts_ = opentelemetry::common::SystemTimestamp{}; metric_sdk::MetricData metric_data{ - metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", + metric_sdk::InstrumentType::kCounter, metric_sdk::InstrumentValueType::kDouble}, metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, opentelemetry::common::SystemTimestamp{}, @@ -93,21 +111,24 @@ inline metric_sdk::ResourceMetrics CreateLastValuePointData() { return data; } -inline metric_sdk::ResourceMetrics CreateDropPointData() { +inline metric_sdk::ResourceMetrics CreateDropPointData() +{ metric_sdk::ResourceMetrics data; - auto resource = opentelemetry::sdk::resource::Resource::Create(opentelemetry::sdk::resource::ResourceAttributes{}); - data.resource_ = &resource; + data.resource_ = &GetEmptyResource(); auto instrumentation_scope = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", "1.2.0"); + opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("library_name", + "1.2.0"); metric_sdk::DropPointData drop_point_data{}; metric_sdk::DropPointData drop_point_data2{}; metric_sdk::MetricData metric_data{ - metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", metric_sdk::InstrumentType::kCounter, + metric_sdk::InstrumentDescriptor{"library_name", "description", "unit", + metric_sdk::InstrumentType::kCounter, metric_sdk::InstrumentValueType::kDouble}, metric_sdk::AggregationTemporality::kDelta, opentelemetry::common::SystemTimestamp{}, opentelemetry::common::SystemTimestamp{}, - std::vector{{metric_sdk::PointAttributes{{"a1", "b1"}}, drop_point_data}, - {metric_sdk::PointAttributes{{"a2", "b2"}}, drop_point_data2}}}; + std::vector{ + {metric_sdk::PointAttributes{{"a1", "b1"}}, drop_point_data}, + {metric_sdk::PointAttributes{{"a2", "b2"}}, drop_point_data2}}}; data.scope_metric_data_ = std::vector{ {instrumentation_scope.get(), std::vector{metric_data}}}; return data; @@ -115,75 +136,104 @@ inline metric_sdk::ResourceMetrics CreateDropPointData() { } // namespace OPENTELEMETRY_BEGIN_NAMESPACE -namespace sdk { -namespace metrics { -inline bool operator==(const metric_sdk::MetricData &lhs, const metric_sdk::MetricData &rhs) { - if (lhs.start_ts != rhs.start_ts) { +namespace sdk +{ +namespace metrics +{ +inline bool operator==(const metric_sdk::MetricData &lhs, const metric_sdk::MetricData &rhs) +{ + if (lhs.start_ts != rhs.start_ts) + { return false; } - if (lhs.end_ts != rhs.end_ts) { + if (lhs.end_ts != rhs.end_ts) + { return false; } - if (lhs.instrument_descriptor.description_ != rhs.instrument_descriptor.description_) { + if (lhs.instrument_descriptor.description_ != rhs.instrument_descriptor.description_) + { return false; } - if (lhs.instrument_descriptor.name_ != rhs.instrument_descriptor.name_) { + if (lhs.instrument_descriptor.name_ != rhs.instrument_descriptor.name_) + { return false; } - if (lhs.instrument_descriptor.type_ != rhs.instrument_descriptor.type_) { + if (lhs.instrument_descriptor.type_ != rhs.instrument_descriptor.type_) + { return false; } - if (lhs.instrument_descriptor.unit_ != rhs.instrument_descriptor.unit_) { + if (lhs.instrument_descriptor.unit_ != rhs.instrument_descriptor.unit_) + { return false; } - if (lhs.instrument_descriptor.value_type_ != rhs.instrument_descriptor.value_type_) { + if (lhs.instrument_descriptor.value_type_ != rhs.instrument_descriptor.value_type_) + { return false; } - if (lhs.point_data_attr_.size() != rhs.point_data_attr_.size()) { + if (lhs.point_data_attr_.size() != rhs.point_data_attr_.size()) + { return false; } - for (uint32_t idx = 0; idx < lhs.point_data_attr_.size(); ++idx) { - if (lhs.point_data_attr_.at(idx).attributes != rhs.point_data_attr_.at(idx).attributes) { + for (uint32_t idx = 0; idx < lhs.point_data_attr_.size(); ++idx) + { + if (lhs.point_data_attr_.at(idx).attributes != rhs.point_data_attr_.at(idx).attributes) + { return false; } auto &lhs_point_data = lhs.point_data_attr_.at(idx).point_data; auto &rhs_point_data = rhs.point_data_attr_.at(idx).point_data; - if (nostd::holds_alternative(lhs_point_data)) { + if (nostd::holds_alternative(lhs_point_data)) + { if (nostd::get(lhs_point_data).value_ != - nostd::get(rhs_point_data).value_) { + nostd::get(rhs_point_data).value_) + { return false; } - } else if (nostd::holds_alternative(lhs_point_data)) { - if (!nostd::holds_alternative(rhs_point_data)) { + } + else if (nostd::holds_alternative(lhs_point_data)) + { + if (!nostd::holds_alternative(rhs_point_data)) + { return false; } - } else if (nostd::holds_alternative(lhs_point_data)) { + } + else if (nostd::holds_alternative(lhs_point_data)) + { auto &lhs_histogram_d = nostd::get(lhs_point_data); auto &rhs_histogram_d = nostd::get(rhs_point_data); - if (lhs_histogram_d.count_ != rhs_histogram_d.count_) { + if (lhs_histogram_d.count_ != rhs_histogram_d.count_) + { return false; } - if (lhs_histogram_d.counts_ != rhs_histogram_d.counts_) { + if (lhs_histogram_d.counts_ != rhs_histogram_d.counts_) + { return false; } - if (lhs_histogram_d.boundaries_ != rhs_histogram_d.boundaries_) { + if (lhs_histogram_d.boundaries_ != rhs_histogram_d.boundaries_) + { return false; } - if (lhs_histogram_d.sum_ != rhs_histogram_d.sum_) { + if (lhs_histogram_d.sum_ != rhs_histogram_d.sum_) + { return false; } - } else if (nostd::holds_alternative(lhs_point_data)) { + } + else if (nostd::holds_alternative(lhs_point_data)) + { auto &lhs_last_value_d = nostd::get(lhs_point_data); auto &rhs_last_value_d = nostd::get(rhs_point_data); - if (lhs_last_value_d.is_lastvalue_valid_ != rhs_last_value_d.is_lastvalue_valid_) { + if (lhs_last_value_d.is_lastvalue_valid_ != rhs_last_value_d.is_lastvalue_valid_) + { return false; } - if (lhs_last_value_d.sample_ts_ != rhs_last_value_d.sample_ts_) { + if (lhs_last_value_d.sample_ts_ != rhs_last_value_d.sample_ts_) + { return false; } - if (lhs_last_value_d.value_ != rhs_last_value_d.value_) { + if (lhs_last_value_d.value_ != rhs_last_value_d.value_) + { return false; } } diff --git a/exporters/prometheus/test/push_exporter_test.cc b/exporters/prometheus/test/push_exporter_test.cc index f070a677e..77e0f203d 100644 --- a/exporters/prometheus/test/push_exporter_test.cc +++ b/exporters/prometheus/test/push_exporter_test.cc @@ -1,39 +1,59 @@ // Copyright 2022, OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -# include +#include -# include -# include -# include -# include +#include +#include +#include +#include -# include "opentelemetry/exporters/prometheus/collector.h" +#include "opentelemetry/exporters/prometheus/collector.h" -# include "opentelemetry/exporters/prometheus/push_exporter.h" -# include "prometheus_test_helper.h" +#include "opentelemetry/exporters/prometheus/push_exporter.h" +#include "opentelemetry/exporters/prometheus/push_exporter_factory.h" +#include "opentelemetry/exporters/prometheus/push_exporter_options.h" +#include "prometheus_test_helper.h" + +using opentelemetry::exporter::metrics::PrometheusCollector; +using opentelemetry::exporter::metrics::PrometheusPushExporter; +using opentelemetry::exporter::metrics::PrometheusPushExporterFactory; +using opentelemetry::exporter::metrics::PrometheusPushExporterOptions; +using opentelemetry::sdk::common::ExportResult; OPENTELEMETRY_BEGIN_NAMESPACE -namespace exporter { -namespace metrics { -class PrometheusPushExporterTest { // : public ::testing::Test - public: +namespace exporter +{ +namespace metrics +{ +class PrometheusPushExporterTest +{ // : public ::testing::Test +public: PrometheusPushExporter GetExporter() { return PrometheusPushExporter(); } + + void CheckFactory(PrometheusPushExporter &exporter, const PrometheusPushExporterOptions &options) + { + ASSERT_EQ(exporter.options_.host, options.host); + ASSERT_EQ(exporter.options_.port, options.port); + ASSERT_EQ(exporter.options_.jobname, options.jobname); + ASSERT_EQ(exporter.options_.username, options.username); + ASSERT_EQ(exporter.options_.password, options.password); + ASSERT_EQ(exporter.options_.max_collection_size, options.max_collection_size); + ASSERT_EQ(exporter.options_.labels.size(), options.labels.size()); + } }; } // namespace metrics } // namespace exporter OPENTELEMETRY_END_NAMESPACE -using opentelemetry::exporter::metrics::PrometheusCollector; -using opentelemetry::sdk::common::ExportResult; -using opentelemetry::exporter::metrics::PrometheusPushExporter; using opentelemetry::exporter::metrics::PrometheusPushExporterTest; /** * When a PrometheusPushExporter is initialized, * isShutdown should be false. */ -TEST(PrometheusPushExporter, InitializeConstructorIsNotShutdown) { +TEST(PrometheusPushExporter, InitializeConstructorIsNotShutdown) +{ PrometheusPushExporterTest p; PrometheusPushExporter exporter = p.GetExporter(); @@ -44,7 +64,8 @@ TEST(PrometheusPushExporter, InitializeConstructorIsNotShutdown) { /** * The shutdown() function should set the isShutdown field to true. */ -TEST(PrometheusPushExporter, ShutdownSetsIsShutdownToTrue) { +TEST(PrometheusPushExporter, ShutdownSetsIsShutdownToTrue) +{ PrometheusPushExporterTest p; PrometheusPushExporter exporter = p.GetExporter(); @@ -65,7 +86,8 @@ TEST(PrometheusPushExporter, ShutdownSetsIsShutdownToTrue) { * The Export() function should return kSuccess = 0 * when data is exported successfully. */ -TEST(PrometheusPushExporter, ExportSuccessfully) { +TEST(PrometheusPushExporter, ExportSuccessfully) +{ PrometheusPushExporterTest p; PrometheusPushExporter exporter = p.GetExporter(); @@ -80,7 +102,8 @@ TEST(PrometheusPushExporter, ExportSuccessfully) { * If the exporter is shutdown, it cannot process * any more export requests and returns kFailure = 1. */ -TEST(PrometheusPushExporter, ExporterIsShutdown) { +TEST(PrometheusPushExporter, ExporterIsShutdown) +{ PrometheusPushExporterTest p; PrometheusPushExporter exporter = p.GetExporter(); @@ -100,7 +123,8 @@ TEST(PrometheusPushExporter, ExporterIsShutdown) { * or when the collection is not full but does not have enough * space to hold the batch data. */ -TEST(PrometheusPushExporter, CollectionNotEnoughSpace) { +TEST(PrometheusPushExporter, CollectionNotEnoughSpace) +{ PrometheusPushExporterTest p; PrometheusPushExporter exporter = p.GetExporter(); @@ -108,12 +132,13 @@ TEST(PrometheusPushExporter, CollectionNotEnoughSpace) { // one close to max size and another one that, when added // to the first, will exceed the size of the collection - int max_collection_size = exporter.GetCollector()->GetMaxCollectionSize(); + int max_collection_size = exporter.GetMaxCollectionSize(); // send export request to fill the // collection in the collector ExportResult code = ExportResult::kSuccess; - for (int count = 1; count <= max_collection_size; ++count) { + for (int count = 1; count <= max_collection_size; ++count) + { auto res = exporter.Export(CreateSumPointData()); ASSERT_EQ(res, code); } @@ -132,7 +157,8 @@ TEST(PrometheusPushExporter, CollectionNotEnoughSpace) { * kFailureInvalidArgument = 3 when an empty collection * of records is passed to the Export() function. */ -TEST(PrometheusPushExporter, InvalidArgumentWhenPassedEmptyRecordCollection) { +TEST(PrometheusPushExporter, InvalidArgumentWhenPassedEmptyRecordCollection) +{ PrometheusPushExporterTest p; PrometheusPushExporter exporter = p.GetExporter(); @@ -147,3 +173,24 @@ TEST(PrometheusPushExporter, InvalidArgumentWhenPassedEmptyRecordCollection) { ExportResult code = ExportResult::kFailureInvalidArgument; ASSERT_EQ(res, code); } + +TEST(PrometheusPushExporterFactory, Create) +{ + PrometheusPushExporterOptions options; + options.host = "localhost"; + options.port = 4138; + options.jobname = "jobname"; + options.labels["test_label"] = "test_value"; + options.username = "user"; + options.password = "pawword"; + options.max_collection_size = 2345; + + PrometheusPushExporterTest p; + auto exporter = PrometheusPushExporterFactory::Create(options); + ASSERT_TRUE(!!exporter); + + ASSERT_EQ(static_cast(exporter.get())->GetMaxCollectionSize(), + options.max_collection_size); + + p.CheckFactory(*static_cast(exporter.get()), options); +} From fb1f7a9af968d5c91c823ffbd443f966f60091ac Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Mon, 25 Sep 2023 11:17:03 -0700 Subject: [PATCH 73/77] [user_events exporter] Remove ENABLE_LOGS_PREVIEW macro as it was removed in the main repo (#327) --- .../user_events/benchmark/logger_benchmark.cc | 42 +++++++++---------- .../user_events/example/logs/foo_library.cc | 10 ++--- .../exporters/user_events/logs/exporter.h | 16 +++---- .../user_events/logs/exporter_options.h | 8 +--- .../exporters/user_events/logs/recordable.h | 20 ++++----- exporters/user_events/src/logs_exporter.cc | 10 ++--- .../user_events/test/logs_exporter_test.cc | 16 +++---- 7 files changed, 47 insertions(+), 75 deletions(-) diff --git a/exporters/user_events/benchmark/logger_benchmark.cc b/exporters/user_events/benchmark/logger_benchmark.cc index 3a54d10ec..7e8561ea3 100644 --- a/exporters/user_events/benchmark/logger_benchmark.cc +++ b/exporters/user_events/benchmark/logger_benchmark.cc @@ -1,27 +1,25 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifdef ENABLE_LOGS_PREVIEW - -# include "opentelemetry/common/timestamp.h" -# include "opentelemetry/logs/logger.h" -# include "opentelemetry/logs/provider.h" -# include "opentelemetry/nostd/shared_ptr.h" - -# include "opentelemetry/exporters/user_events/logs/exporter.h" -# include "opentelemetry/logs/provider.h" -# include "opentelemetry/sdk/logs/logger_provider_factory.h" -# include "opentelemetry/sdk/logs/processor.h" -# include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" - -# include -# include -# include -# include -# include -# include - -# include +#include "opentelemetry/common/timestamp.h" +#include "opentelemetry/logs/logger.h" +#include "opentelemetry/logs/provider.h" +#include "opentelemetry/nostd/shared_ptr.h" + +#include "opentelemetry/exporters/user_events/logs/exporter.h" +#include "opentelemetry/logs/provider.h" +#include "opentelemetry/sdk/logs/logger_provider_factory.h" +#include "opentelemetry/sdk/logs/processor.h" +#include "opentelemetry/sdk/logs/simple_log_record_processor_factory.h" + +#include +#include +#include +#include +#include +#include + +#include using opentelemetry::logs::EventId; using opentelemetry::logs::Logger; @@ -167,5 +165,3 @@ int main(int argc, char **argv) benchmark::Initialize(&argc, argv); benchmark::RunSpecifiedBenchmarks(); } - -#endif diff --git a/exporters/user_events/example/logs/foo_library.cc b/exporters/user_events/example/logs/foo_library.cc index e4ff82308..21f3bd40b 100644 --- a/exporters/user_events/example/logs/foo_library.cc +++ b/exporters/user_events/example/logs/foo_library.cc @@ -1,11 +1,9 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifdef ENABLE_LOGS_PREVIEW - -# include "opentelemetry/logs/event_id.h" -# include "opentelemetry/logs/provider.h" -# include "opentelemetry/sdk/version/version.h" +#include "opentelemetry/logs/event_id.h" +#include "opentelemetry/logs/provider.h" +#include "opentelemetry/sdk/version/version.h" namespace logs = opentelemetry::logs; namespace nostd = opentelemetry::nostd; @@ -42,5 +40,3 @@ void sell_fruit(std::string_view fruit) {{"fruit_name", fruit.data()}, {"fruit_price", static_cast(fruit_inventory[fruit.data()])}})); } - -#endif diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h index 3cb4e27f8..dea60e989 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter.h @@ -3,15 +3,13 @@ #pragma once -#ifdef ENABLE_LOGS_PREVIEW +#include "exporter_options.h" +#include "opentelemetry/common/spin_lock_mutex.h" +#include "opentelemetry/sdk/logs/exporter.h" -# include "exporter_options.h" -# include "opentelemetry/common/spin_lock_mutex.h" -# include "opentelemetry/sdk/logs/exporter.h" - -# include -# include -# include +#include +#include +#include OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -66,5 +64,3 @@ class Exporter final : public opentelemetry::sdk::logs::LogRecordExporter } // namespace user_events } // namespace exporter OPENTELEMETRY_END_NAMESPACE - -#endif \ No newline at end of file diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h index ae9042b01..67724f44a 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/exporter_options.h @@ -3,10 +3,8 @@ #pragma once -#ifdef ENABLE_LOGS_PREVIEW - -# include -# include "opentelemetry/version.h" +#include +#include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -22,5 +20,3 @@ struct ExporterOptions } // namespace user_events } // namespace exporter OPENTELEMETRY_END_NAMESPACE - -#endif \ No newline at end of file diff --git a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h index 99b646cb1..2adbb5961 100644 --- a/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h +++ b/exporters/user_events/include/opentelemetry/exporters/user_events/logs/recordable.h @@ -3,17 +3,15 @@ #pragma once -#ifdef ENABLE_LOGS_PREVIEW +#include "opentelemetry/nostd/string_view.h" +#include "opentelemetry/logs/severity.h" +#include "opentelemetry/sdk/common/attribute_utils.h" +#include "opentelemetry/sdk/logs/recordable.h" +#include "opentelemetry/version.h" +#include "utils.h" -# include "opentelemetry/nostd/string_view.h" -# include "opentelemetry/logs/severity.h" -# include "opentelemetry/sdk/common/attribute_utils.h" -# include "opentelemetry/sdk/logs/recordable.h" -# include "opentelemetry/version.h" -# include "utils.h" - -# include -# include +#include +#include OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter @@ -129,5 +127,3 @@ class Recordable final : public opentelemetry::sdk::logs::Recordable } // namespace user_events } // namespace exporter OPENTELEMETRY_END_NAMESPACE - -#endif // ENABLE_LOGS_PREVIEW diff --git a/exporters/user_events/src/logs_exporter.cc b/exporters/user_events/src/logs_exporter.cc index 7121f5cf5..4bf8a73e1 100644 --- a/exporters/user_events/src/logs_exporter.cc +++ b/exporters/user_events/src/logs_exporter.cc @@ -1,11 +1,9 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifdef ENABLE_LOGS_PREVIEW - -# include "opentelemetry/exporters/user_events/logs/exporter.h" -# include "opentelemetry/exporters/user_events/logs/recordable.h" -# include "opentelemetry/sdk_config.h" +#include "opentelemetry/exporters/user_events/logs/exporter.h" +#include "opentelemetry/exporters/user_events/logs/recordable.h" +#include "opentelemetry/sdk_config.h" namespace nostd = opentelemetry::nostd; namespace sdklogs = opentelemetry::sdk::logs; @@ -92,5 +90,3 @@ bool Exporter::isShutdown() const noexcept } // namespace user_events } // namespace exporter OPENTELEMETRY_END_NAMESPACE - -#endif \ No newline at end of file diff --git a/exporters/user_events/test/logs_exporter_test.cc b/exporters/user_events/test/logs_exporter_test.cc index 97b2388c3..b706141fc 100644 --- a/exporters/user_events/test/logs_exporter_test.cc +++ b/exporters/user_events/test/logs_exporter_test.cc @@ -1,16 +1,14 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -#ifdef ENABLE_LOGS_PREVIEW +#include +#include +#include +#include -# include -# include -# include -# include +#include "opentelemetry/exporters/user_events/logs/exporter.h" -# include "opentelemetry/exporters/user_events/logs/exporter.h" - -# include +#include namespace sdk_logs = opentelemetry::sdk::logs; namespace user_events_logs = opentelemetry::exporter::user_events::logs; @@ -31,5 +29,3 @@ TEST(UserEventsLogRecordExporter, Shutdown) EXPECT_TRUE(exporter->Shutdown()); } - -#endif \ No newline at end of file From d30eb603d88aed3c33b77a0d4efde4a6ed881407 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 27 Sep 2023 16:13:10 -0700 Subject: [PATCH 74/77] Build with otel-cpp v1.11.0 & use Cumulative temporality for UpDownCounter (#329) --- .github/workflows/geneva_metrics.yml | 18 ++++++++++-------- exporters/geneva/example/example_metrics.cc | 12 ++++++------ exporters/geneva/example/stress_test_linux.cc | 2 ++ .../exporters/geneva/metrics/exporter.h | 3 +++ exporters/geneva/src/exporter.cc | 6 +++++- .../geneva/test/common/generate_metrics.h | 5 +++-- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/.github/workflows/geneva_metrics.yml b/.github/workflows/geneva_metrics.yml index a6834b8cb..4b28545bf 100644 --- a/.github/workflows/geneva_metrics.yml +++ b/.github/workflows/geneva_metrics.yml @@ -11,8 +11,8 @@ on: paths: - "exporters/geneva/**" - ".github/workflows/geneva_metrics.yml" - - cmake_linux: +jobs: + cmake_linux: name: CMake on Linux runs-on: ubuntu-latest steps: @@ -24,7 +24,7 @@ on: uses: actions/checkout@v3 with: repository: "open-telemetry/opentelemetry-cpp" - ref: "v1.8.2" + ref: "v1.11.0" path: "otel_cpp" submodules: "recursive" - name: setup @@ -34,13 +34,15 @@ on: ca-certificates wget git valgrind lcov - name: run tests run: | + sudo $GITHUB_WORKSPACE/otel_cpp/ci/setup_cmake.sh mkdir -p "$GITHUB_WORKSPACE/otel_cpp/build" cd "$GITHUB_WORKSPACE/otel_cpp/build" - cmake .. -DCMAKE_BUILD_TYPE=Debug - cmake --build . -j --config Debug - cmake --install . --prefix "$HOME/prebuilt-otel" --config Debug + cmake .. -DOPENTELEMETRY_INSTALL=ON + cmake --build . -j${nproc} + cmake --install . --prefix "$HOME/prebuilt-otel" mkdir -p "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/geneva/build" cd "$GITHUB_WORKSPACE/otel_cpp_contrib/exporters/geneva/build" - cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" -DCMAKE_BUILD_TYPE=Debug \ + cmake .. "-DCMAKE_PREFIX_PATH=$HOME/prebuilt-otel" \ -DBUILD_TESTING=ON -DBUILD_EXAMPLE=ON - cmake --build . -j --config Debug \ No newline at end of file + cmake --build . -j${nproc} + ctest diff --git a/exporters/geneva/example/example_metrics.cc b/exporters/geneva/example/example_metrics.cc index efbac42fa..1f9d42b39 100644 --- a/exporters/geneva/example/example_metrics.cc +++ b/exporters/geneva/example/example_metrics.cc @@ -55,11 +55,11 @@ void initMetrics(const std::string &name, const std::string &account_name) { std::string counter_name = name + "_counter"; std::unique_ptr instrument_selector{ new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kCounter, - counter_name)}; + counter_name, "")}; std::unique_ptr meter_selector{ new metric_sdk::MeterSelector(name, version, schema)}; std::unique_ptr sum_view{new metric_sdk::View{ - name, "description", metric_sdk::AggregationType::kSum}}; + name, "description", "", metric_sdk::AggregationType::kSum}}; p->AddView(std::move(instrument_selector), std::move(meter_selector), std::move(sum_view)); @@ -68,11 +68,11 @@ void initMetrics(const std::string &name, const std::string &account_name) { std::unique_ptr observable_instrument_selector{new metric_sdk::InstrumentSelector( metric_sdk::InstrumentType::kObservableCounter, - observable_counter_name)}; + observable_counter_name, "")}; std::unique_ptr observable_meter_selector{ new metric_sdk::MeterSelector(name, version, schema)}; std::unique_ptr observable_sum_view{new metric_sdk::View{ - name, "description", metric_sdk::AggregationType::kSum}}; + name, "description", "", metric_sdk::AggregationType::kSum}}; p->AddView(std::move(observable_instrument_selector), std::move(observable_meter_selector), std::move(observable_sum_view)); @@ -81,7 +81,7 @@ void initMetrics(const std::string &name, const std::string &account_name) { std::string histogram_name = name + "_histogram"; std::unique_ptr histogram_instrument_selector{ new metric_sdk::InstrumentSelector(metric_sdk::InstrumentType::kHistogram, - histogram_name)}; + histogram_name, "")}; std::unique_ptr histogram_meter_selector{ new metric_sdk::MeterSelector(name, version, schema)}; std::shared_ptr @@ -92,7 +92,7 @@ void initMetrics(const std::string &name, const std::string &account_name) { ->boundaries_ = std::vector{0.0, 50.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 10000.0}; std::unique_ptr histogram_view{new metric_sdk::View{ - name, "description", metric_sdk::AggregationType::kHistogram, + name, "description", "", metric_sdk::AggregationType::kHistogram, aggregation_config}}; p->AddView(std::move(histogram_instrument_selector), std::move(histogram_meter_selector), std::move(histogram_view)); diff --git a/exporters/geneva/example/stress_test_linux.cc b/exporters/geneva/example/stress_test_linux.cc index 3145821ea..d1c5a197c 100644 --- a/exporters/geneva/example/stress_test_linux.cc +++ b/exporters/geneva/example/stress_test_linux.cc @@ -28,9 +28,11 @@ #include #include +#ifdef HAVE_BOOST #include #include #include +#endif namespace metrics_sdk = opentelemetry::sdk::metrics; namespace nostd = opentelemetry::nostd; diff --git a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h index edb407057..926c87ffb 100644 --- a/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h +++ b/exporters/geneva/include/opentelemetry/exporters/geneva/metrics/exporter.h @@ -4,10 +4,13 @@ #pragma once #include "opentelemetry/common/spin_lock_mutex.h" +#include "opentelemetry/common/timestamp.h" #include "opentelemetry/exporters/geneva/metrics/connection_string_parser.h" #include "opentelemetry/exporters/geneva/metrics/data_transport.h" #include "opentelemetry/exporters/geneva/metrics/exporter_options.h" #include "opentelemetry/sdk/metrics/push_metric_exporter.h" +#include "opentelemetry/sdk/metrics/data/metric_data.h" + OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { diff --git a/exporters/geneva/src/exporter.cc b/exporters/geneva/src/exporter.cc index f2bd0f302..ee57bdf07 100644 --- a/exporters/geneva/src/exporter.cc +++ b/exporters/geneva/src/exporter.cc @@ -7,7 +7,7 @@ #ifdef _WIN32 #include "opentelemetry/exporters/geneva/metrics/etw_data_transport.h" #endif -#include "opentelemetry/metrics/meter_provider.h" +#include "opentelemetry/sdk/metrics/export/metric_producer.h" #include "opentelemetry/sdk_config.h" #include @@ -46,6 +46,10 @@ Exporter::Exporter(const ExporterOptions &options) sdk::metrics::AggregationTemporality Exporter::GetAggregationTemporality( sdk::metrics::InstrumentType instrument_type) const noexcept { + if (instrument_type == sdk::metrics::InstrumentType::kUpDownCounter) + { + return sdk::metrics::AggregationTemporality::kCumulative; + } return sdk::metrics::AggregationTemporality::kDelta; } diff --git a/exporters/geneva/test/common/generate_metrics.h b/exporters/geneva/test/common/generate_metrics.h index 67a3eb6d7..0e7b3d2fb 100644 --- a/exporters/geneva/test/common/generate_metrics.h +++ b/exporters/geneva/test/common/generate_metrics.h @@ -2,6 +2,7 @@ #include "opentelemetry/sdk/metrics/export/metric_producer.h" #include "opentelemetry/sdk/metrics/instruments.h" #include "opentelemetry/sdk/resource/resource.h" +#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" #include @@ -178,7 +179,7 @@ GenerateSumDataLongMetricsNonMonotonic( kUpDownCounterLongInstrumentUnit, opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter, opentelemetry::sdk::metrics::InstrumentValueType::kLong}, - opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::sdk::metrics::AggregationTemporality::kCumulative, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ @@ -233,7 +234,7 @@ GenerateSumDataDoubleMetricsNonMonotonic( kUpDownCounterDoubleInstrumentUnit, opentelemetry::sdk::metrics::InstrumentType::kUpDownCounter, opentelemetry::sdk::metrics::InstrumentValueType::kDouble}, - opentelemetry::sdk::metrics::AggregationTemporality::kDelta, + opentelemetry::sdk::metrics::AggregationTemporality::kCumulative, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, opentelemetry::common::SystemTimestamp{std::chrono::system_clock::now()}, std::vector{ From adad337c7f6c8d93b29ad6c00cbfc24eb0808c97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tarjei=20Hus=C3=B8y?= Date: Wed, 25 Oct 2023 18:02:36 +0200 Subject: [PATCH 75/77] Fix mixed readme descriptions (#333) --- instrumentation/otel-webserver-module/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 0b8201b12..dd4a8c757 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -51,8 +51,8 @@ Monitoring individual modules is crucial to the instrumentation of Apache web se |*ApacheModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports| |*ApacheModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled| |*ApacheModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | -|*ApacheModuleServiceName* | | REQUIRED: A namespace for the ServiceName| -|*ApacheModuleServiceNamespace* | | REQUIRED: Logical name of the service | +|*ApacheModuleServiceName* | | REQUIRED: Logical name of the service | +|*ApacheModuleServiceNamespace* | | REQUIRED: A namespace for the ServiceName | |*ApacheModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | |*ApacheModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log| |*ApacheModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| @@ -166,8 +166,8 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get |*NginxModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports| |*NginxModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled| |*NginxModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | -|*NginxModuleServiceName* | | REQUIRED: A namespace for the ServiceName| -|*NginxModuleServiceNamespace* | | REQUIRED: Logical name of the service | +|*NginxModuleServiceName* | | REQUIRED: Logical name of the service | +|*NginxModuleServiceNamespace* | | REQUIRED: A namespace for the ServiceName | |*NginxModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | |*NginxModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log| |*NginxModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| From 0930baa6316b13bedb2eaa4413038717ad7f6931 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Wed, 25 Oct 2023 16:08:46 -0700 Subject: [PATCH 76/77] Fix status mapping in fluentd exporter (#335) --- exporters/fluentd/src/trace/recordable.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/exporters/fluentd/src/trace/recordable.cc b/exporters/fluentd/src/trace/recordable.cc index 7b5c9b61c..010c02d4e 100644 --- a/exporters/fluentd/src/trace/recordable.cc +++ b/exporters/fluentd/src/trace/recordable.cc @@ -25,12 +25,13 @@ template static inline json create_message(T ts, json body) { } // constexpr needs keys to be constexpr, const is next best to use. -static const std::map +static const std::map kSpanKindMap = { - {opentelemetry::trace::SpanKind::kClient, "CLIENT"}, - {opentelemetry::trace::SpanKind::kServer, "SERVER"}, - {opentelemetry::trace::SpanKind::kConsumer, "CONSUMER"}, - {opentelemetry::trace::SpanKind::kProducer, "PRODUCER"}, + {opentelemetry::trace::SpanKind::kInternal, 0}, + {opentelemetry::trace::SpanKind::kServer, 1}, + {opentelemetry::trace::SpanKind::kClient, 2}, + {opentelemetry::trace::SpanKind::kProducer, 3}, + {opentelemetry::trace::SpanKind::kConsumer, 4}, }; // @@ -91,10 +92,11 @@ void Recordable::AddLink( void Recordable::SetStatus(opentelemetry::trace::StatusCode code, nostd::string_view description) noexcept { + options_[FLUENT_FIELD_SUCCESS] = code != opentelemetry::trace::StatusCode::kError; if (code != opentelemetry::trace::StatusCode::kUnset) { options_["tags"]["otel.status_code"] = code; if (code == opentelemetry::trace::StatusCode::kError) { - options_["tags"]["error"] = description; + options_[FLUENT_FIELD_STATUSMESSAGE] = description; } } } From 130c6e62ee6602b1fc034969a2156670910e37f1 Mon Sep 17 00:00:00 2001 From: Aryan Ishan <54237311+aryanishan1001@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:43:45 +0530 Subject: [PATCH 77/77] Commit for the changes to upgrade nginx version to 1.24.0 and 1.25.3 (#340) * commit for the changes to upgrade nginx version to 1.24.0 and 1.25.3 * readme.md updated --- .../otel-webserver-module/README.md | 4 ++-- .../docker/centos7/Dockerfile | 4 ++-- .../docker/ubuntu20.04/Dockerfile | 4 ++-- .../include/core/api/Payload.h | 22 +++++++++---------- .../otel-webserver-module/version.properties | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index dd4a8c757..cc8367596 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -150,7 +150,7 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get | Library | Present Version | | ---------------------------------------------- | ----------- | -| Nginx | 1.22.0, 1.23.0,1.23.1 | +| Nginx | 1.24.0, 1.25.3 | | Apr | 1.7.0 | | Apr-util | 1.6.1 | @@ -182,7 +182,7 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get - Docker Desktop should be installed on the system #### Platform Supported -- Supports both stable(1.22.0) and mainline(1.23.1). +- Supports both stable(1.24.0) and mainline(1.25.3). - Earlier support of v1.18.0 is deprecated. - The build is supported for **x86-64** platforms. - OS support: **Centos6**, **Centos7, ubuntu20.04**. diff --git a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile index a6ffe2023..ffbac410e 100644 --- a/instrumentation/otel-webserver-module/docker/centos7/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/centos7/Dockerfile @@ -26,7 +26,7 @@ ARG AUTOMAKE_VERSION="1.16.3" ARG PERL_VERSION="5.20.2" ARG PERL_CPANVERSION="5.0" ARG PCRE_VERSION="8.44" -ARG NGINX_VERSION="1.22.0" +ARG NGINX_VERSION="1.24.0" # create default non-root user RUN groupadd -r swuser && useradd -u 1000 -g swuser -m -s /sbin/nologin -c "default non-root user" swuser @@ -290,7 +290,7 @@ RUN cd /otel-webserver-module/build \ && cd / RUN cp /otel-webserver-module/conf/nginx/opentelemetry_module.conf /opt/ \ - && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.22.0/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '8i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.24.0/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ && cd / diff --git a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile index 81d717668..7df79b246 100644 --- a/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile +++ b/instrumentation/otel-webserver-module/docker/ubuntu20.04/Dockerfile @@ -38,7 +38,7 @@ ARG APRUTIL_VERSION="1.6.1" ARG LOG4CXX_VERSION="0.11.0" ARG GTEST_VERSION="1.10.0" ARG PCRE_VERSION="8.44" -ARG NGINX_VERSION="1.22.0" +ARG NGINX_VERSION="1.24.0" # Install GRPC RUN git clone --shallow-submodules --depth 1 --recurse-submodules -b v${GRPC_VERSION} \ @@ -213,7 +213,7 @@ RUN cd /otel-webserver-module/build \ RUN cd /otel-webserver-module/build \ && cp ../conf/nginx/opentelemetry_module.conf /opt/ \ - && sed -i '5i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.22.0/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ + && sed -i '5i load_module /opt/opentelemetry-webserver-sdk/WebServerModule/Nginx/1.24.0/ngx_http_opentelemetry_module.so;' /etc/nginx/nginx.conf \ && sed -i '33i include /opt/opentelemetry_module.conf;' /etc/nginx/nginx.conf \ && cd /opt/opentelemetry-webserver-sdk \ && ./install.sh \ diff --git a/instrumentation/otel-webserver-module/include/core/api/Payload.h b/instrumentation/otel-webserver-module/include/core/api/Payload.h index a3325e0b2..e1cf2fe37 100644 --- a/instrumentation/otel-webserver-module/include/core/api/Payload.h +++ b/instrumentation/otel-webserver-module/include/core/api/Payload.h @@ -71,18 +71,18 @@ class RequestPayload void set_port(long aPort) {port = aPort; } - std::string get_uri() { return uri; } - std::string get_request_protocol() { return request_protocol; } - std::string get_http_get_parameter() { return http_get_parameter; } - std::string get_http_post_parameter() { return http_post_parameter; } - std::string get_http_request_method() { return http_request_method; } + std::string& get_uri() { return uri; } + std::string& get_request_protocol() { return request_protocol; } + std::string& get_http_get_parameter() { return http_get_parameter; } + 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; } + 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; } std::unordered_map& get_request_headers() { return request_headers; diff --git a/instrumentation/otel-webserver-module/version.properties b/instrumentation/otel-webserver-module/version.properties index 8e477b32d..d0fb52b5c 100644 --- a/instrumentation/otel-webserver-module/version.properties +++ b/instrumentation/otel-webserver-module/version.properties @@ -1,4 +1,4 @@ server-module-version=1.0.3 release=GA -nginxSupportedVersions=1.22.0,1.23.0,1.23.1 +nginxSupportedVersions=1.24.0,1.25.3 CPP-SDK-version=1.2.0