diff --git a/instrumentation/otel-webserver-module/.gitignore b/instrumentation/otel-webserver-module/.gitignore
new file mode 100644
index 000000000..259148fa1
--- /dev/null
+++ b/instrumentation/otel-webserver-module/.gitignore
@@ -0,0 +1,32 @@
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
diff --git a/instrumentation/otel-webserver-module/Dockerfile b/instrumentation/otel-webserver-module/Dockerfile
new file mode 100644
index 000000000..3ed5381b4
--- /dev/null
+++ b/instrumentation/otel-webserver-module/Dockerfile
@@ -0,0 +1,245 @@
+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
+
+# 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 2.7.8
+RUN wget http://www.python.org/ftp/python/2.7.8/Python-2.7.8.tar.xz \
+ && unxz Python-2.7.8.tar.xz \
+ && tar -xf Python-2.7.8.tar \
+ && cd Python-2.7.8 && ./configure --prefix=/usr/local && make && make install \
+ && cd .. \
+ && rm -rf Python-2.7.8.tar.xz && rm -rf Python-2.7.8.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/v3.20/cmake-3.20.0-linux-x86_64.tar.gz \
+ && tar -xvf cmake-3.20.0-linux-x86_64.tar.gz \
+ && cd cmake-3.20.0-linux-x86_64 \
+ && cp -rf * /usr/local/ \
+ && cd .. && rm -rf cmake-3.20.0-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/v1.36.4 -b v1.36.4 \
+ && 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 mkdir -p dependencies/boost/1.75.0/ \
+ && git clone https://github.com/boostorg/boost \
+ && cd boost/ && git checkout tags/boost-1.75.0 -b boost-1.75.0 \
+ && git submodule update --init --recursive \
+ && ./bootstrap.sh --with-libraries=filesystem,system --prefix=/dependencies/boost/1.75.0 \
+ && ./b2 install define=BOOST_ERROR_CODE_HEADER_ONLY link=static threading=multi cxxflags="-fvisibility=hidden -fPIC -D_GLIBCXX_USE_CXX11_ABI=0" cflags="-fvisibility=hidden -fPIC" \
+ && cd .. && rm -rf boost
+
+#install Apr
+RUN mkdir -p dependencies/apr/1.7.0 \
+ && wget https://dlcdn.apache.org//apr/apr-1.7.0.tar.gz --no-check-certificate \
+ && tar -xf apr-1.7.0.tar.gz \
+ && cd apr-1.7.0 \
+ && ./configure --prefix=/dependencies/apr/1.7.0 --enable-static=yes --enable-shared=no --with-pic && echo $? \
+ && make -j 6 \
+ && make install \
+ && cd ../ && rm -rf apr-1.7.0 && rm -rf apr-1.7.0.tar.gz
+
+# install libexpat
+RUN mkdir -p dependencies/expat/2.3.0 \
+ && wget https://github.com/libexpat/libexpat/releases/download/R_2_3_0/expat-2.3.0.tar.gz --no-check-certificate \
+ && tar -xf expat-2.3.0.tar.gz \
+ && cd expat-2.3.0 \
+ && ./configure --prefix=/dependencies/expat/2.3.0 --enable-static=yes --enable-shared=no --with-pic && echo $? \
+ && make -j 6 \
+ && make install \
+ && cd ../ && rm -rf expat-2.3.0 && rm -rf expat-2.3.0.tar.gz
+
+# install Apr-util
+RUN mkdir -p dependencies/apr-util/1.6.1 \
+ && wget https://dlcdn.apache.org//apr/apr-util-1.6.1.tar.gz --no-check-certificate \
+ && tar -xf apr-util-1.6.1.tar.gz \
+ && cd apr-util-1.6.1 \
+ && ./configure --prefix=/dependencies/apr-util/1.6.1 --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-1.6.1 && rm -rf apr-util-1.6.1.tar.gz
+
+# install m4
+RUN yum install m4 -y
+
+# install autoconf
+RUN wget --no-check-certificate https://ftp.gnu.org/gnu/autoconf/autoconf-2.68.tar.gz \
+ && tar xzf autoconf-2.68.tar.gz \
+ && cd autoconf-2.68 \
+ && ./configure --prefix=/usr/ && make -j && make install && autoconf -V \
+ && cd .. && rm -rf autoconf-2.68.tar.gz
+
+# install automake
+RUN wget --no-check-certificate https://ftp.gnu.org/gnu/automake/automake-1.16.3.tar.gz \
+ && tar xzf automake-1.16.3.tar.gz \
+ && cd automake-1.16.3 \
+ && ./configure --prefix=/usr --libdir=/usr/lib64 \
+ && make -j && make install \
+ && automake --version \
+ && cd .. && rm -rf automake-1.16.3.tar.gz
+
+# install libtool
+RUN wget --no-check-certificate https://ftpmirror.gnu.org/libtool/libtool-2.4.6.tar.gz \
+ && tar xzf libtool-2.4.6.tar.gz \
+ && cd libtool-2.4.6 \
+ && ./configure --prefix=/usr \
+ && make -j 6 \
+ && make install \
+ && libtool --version \
+ && cd .. && rm -rf libtool-2.4.6.tar.gz
+
+#install log4cxx
+RUN mkdir -p dependencies/apache-log4cxx/0.11.0 \
+ && wget https://archive.apache.org/dist/logging/log4cxx/0.11.0/apache-log4cxx-0.11.0.tar.gz --no-check-certificate \
+ && tar -xf apache-log4cxx-0.11.0.tar.gz \
+ && cd apache-log4cxx-0.11.0 \
+ && ./configure --prefix=/dependencies/apache-log4cxx/0.11.0/ --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-0.11.0.tar.gz && rm -rf apache-log4cxx-0.11.0
+
+# install opentelemetry
+RUN mkdir -p dependencies/opentelemetry/1.0.0-rc1/lib \
+ && mkdir -p dependencies/opentelemetry/1.0.0-rc1/include \
+ && git clone https://github.com/open-telemetry/opentelemetry-cpp \
+ && cd opentelemetry-cpp/ \
+ && git checkout tags/v1.0.0-rc1 -b v1.0.0-rc1 \
+ && 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/1.0.0-rc1 \
+ && cmake --build . --target all \
+ && cd .. \
+ && find . -name "*.so" -type f -exec cp {} /dependencies/opentelemetry/1.0.0-rc1/lib/ \; \
+ && cp build/libopentelemetry_proto.a /dependencies/opentelemetry/1.0.0-rc1/lib \
+ && cp -r api/include/ /dependencies/opentelemetry/1.0.0-rc1/ \
+ && for dir in exporters/*; do if [ -d "$dir" ]; then cp -rf "$dir/include" /dependencies/opentelemetry/1.0.0-rc1/; fi; done \
+ && cp -r sdk/include/ /dependencies/opentelemetry/1.0.0-rc1/ \
+ && cp -r build/generated/third_party/opentelemetry-proto/opentelemetry/proto/ /dependencies/opentelemetry/1.0.0-rc1/include/opentelemetry/ \
+ && cd .. && rm -rf opentelemetry-cpp
+
+# install googletest
+RUN mkdir -p dependencies/googletest/1.10.0/ \
+ && wget https://github.com/google/googletest/archive/refs/tags/release-1.10.0.tar.gz --no-check-certificate \
+ && tar -xf release-1.10.0.tar.gz \
+ && cd googletest-release-1.10.0/ \
+ && mkdir build && cd build \
+ && cmake .. -DCMAKE_INSTALL_PREFIX=/dependencies/googletest/1.10.0/ \
+ && make \
+ && make install \
+ && cd ../.. && rm -rf release-1.10.0.tar.gz && rm -rf googletest-release-1.10.0/
+
+
+#Installing Apache and apr source code
+RUN mkdir build-dependencies \
+ && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-1.5.2.tar.gz \
+ && tar -xf apr-1.5.2.tar.gz \
+ && mv -f apr-1.5.2 build-dependencies \
+ && wget --no-check-certificate https://archive.apache.org/dist/apr/apr-util-1.5.4.tar.gz \
+ && tar -xf apr-util-1.5.4.tar.gz \
+ && mv -f apr-util-1.5.4 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
+
+# Build Webserver Module
+RUN git clone https://github.com/cisco-open/otel-webserver-module.git \
+ && cp -r /dependencies /otel-webserver-module/ \
+ && cp -r /build-dependencies /otel-webserver-module/ \
+ && cd otel-webserver-module \
+ && ./gradlew assembleApacheModule
+
+# install webserver module
+RUN cd /otel-webserver-module/build \
+ && tar -xf opentelemetry-webserver-sdk-x64-linux.tgz \
+ && mv -f opentelemetry-webserver-sdk /opt/ \
+ && cd ../ \
+ && cp opentelemetry_module.conf /etc/httpd/conf.d/ \
+ && cd /opt/opentelemetry-webserver-sdk \
+ && ./install.sh \
+ && cd /
+
+# Remove unwanted files
+RUN rm -rf grpc && rm -rf autoconf-2.68 && rm -rf automake-1.16.3 && rm -rf cmake-3.20.0-linux-x86_64 \
+ && rm -rf libtool-2.4.6 && rm -rf Python-2.7.8 \
+ && rm -f apr-1.5.2.tar.gz && rm -f apr-util-1.5.4.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/LICENSE b/instrumentation/otel-webserver-module/LICENSE
new file mode 100644
index 000000000..261eeb9e9
--- /dev/null
+++ b/instrumentation/otel-webserver-module/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/instrumentation/otel-webserver-module/Makefile b/instrumentation/otel-webserver-module/Makefile
new file mode 100644
index 000000000..9c770d525
--- /dev/null
+++ b/instrumentation/otel-webserver-module/Makefile
@@ -0,0 +1,18 @@
+COMMON_MAKEFILE := $(CURDIR)/$(lastword $(MAKEFILE_LIST))
+
+DOCKER_COMPOSE_LINUX := docker-compose -f docker-compose.yml
+
+docker-clean:
+ $(DOCKER_COMPOSE) down --rmi local -v
+ $(DOCKER_COMPOSE) rm -f -v
+
+LINUX_x64 := $(DOCKER_COMPOSE_LINUX) run -w /webserver_agent apache_agent_centos6-x64
+
+setup-linux:
+ $(DOCKER_COMPOSE_LINUX) build
+
+clean-linux: DOCKER_COMPOSE = $(DOCKER_COMPOSE_LINUX)
+clean-linux: docker-clean
+
+build-x64: clean-linux setup-linux
+ $(DOCKER_COMPOSE_LINUX) up
diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md
index e69de29bb..09fd8580e 100644
--- a/instrumentation/otel-webserver-module/README.md
+++ b/instrumentation/otel-webserver-module/README.md
@@ -0,0 +1,99 @@
+# otel-webserver-module
+
+The OTEL webserver module comprises only Apache webserver module currently. Further support for Nginx webserver would be added in future.
+
+## Apache Webserver Module
+
+The Apache Module enables tracing of incoming requests to the server by injecting instrumentation into the Apache server at runtime. Along with the above mentioned capability, the Apache web server module has capabilities to capture the response time of many modules (including mod_proxy) involved in an incoming request, thereby including the hierarchical time consumption by each module.
+
+### Module wise Monitoring
+
+Monitoring individual modules is crucial to the instrumentation of Apache web server. As the HTTP request flows through individual modules, delay in execution or errors might occur at any of the modules involved in the request. To identify the root cause of any delay or errors in request processing, module wise information (such as response time of individual modules) would enhance the debuggability of the Apache web server.
+
+#### Some of the Modules monitored by Apache Module
+| Some of the use cases handled by Apache Module | Module used |
+| ---------------------------------------------- | ----------- |
+| Monitor each module in the login phase | mod_sso |
+| Monitor php application running on the same machine | mod_php|
+| Monitor requests to remote server | mod_dav |
+| Monitor reverse proxy requests | mod_proxy |
+| Monitor the reverse proxy load balancer | mod_proxy_balancer |
+
+### 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.0.0-rc1 |
+| Googletest | 1.10.0 |
+
+*There are some libraries which are just used to generate Apache Header files
+
+| Library | Present Version |
+| ---------------------------------------------- | ----------- |
+| Httpd | 2.4.23, 2.2.31 |
+| Apr | 1.5.2 |
+| Apr-util | 1.5.4 |
+
+### Configuration
+| Configuration Directives | Default Values | Remarks |
+| ---------------------------------------------- | --------------- | ------------------------------------------ |
+|*ApacheModuleEnabled* | ON | OPTIONAL: Needed for instrumenting Apache Webserver |
+|*ApacheModuleOtelSpanExporter* | otlp | OPTIONAL: Specify the span exporter to be used. Supported values are "otlp" and "ostream". All other supported values would be added in future. |
+|*ApacheModuleOtelExporterEndpoint:* | | REQUIRED: The endpoint otel exporter exports to. Example "docker.for.mac.localhost:4317" |
+|*ApacheModuleOtelSpanProcessor* | batch | OPTIONAL: Specify the processor to select to. Supported values are "simple" and "batch".|
+|*ApacheModuleOtelSampler* | AlwaysOn | OPTIONAL: Supported values are "AlwaysOn" and "AlwaysOff" |
+|*ApacheModuleOtelMaxQueueSize* | 2048 | OPTIONAL: The maximum queue size. After the size is reached spans are dropped|
+|*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 |
+|*ApacheModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance |
+|*ApacheModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log|
+|*ApacheModuleWebserverContext* | | OPTIONAL: Virtual Host Configuration|
+|*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|
+
+A sample configuration is mentioned in [opentelemetry_module.conf](https://github.com/cisco-open/otel-webserver-module/blob/main/opentelemetry_module.conf)
+
+### Build and Installation
+#### Prerequisites
+- Docker Desktop should be installed on the system
+
+#### Platform Supported
+- Currently, it is built and tested on CentOS 6
+- Other platform support: TBD
+
+#### 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 build
+docker-compose up
+```
+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
+
+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 build
+docker-compose 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.
+
+### 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
new file mode 100644
index 000000000..e3439b33e
--- /dev/null
+++ b/instrumentation/otel-webserver-module/build.gradle
@@ -0,0 +1,509 @@
+apply plugin: 'cpp'
+apply from: 'common.gradle'
+
+def coverageEnabled = System.getProperty('enableCoverage')
+
+project.ext {
+ // To do a 32-bit build, pass "-Dos.arch=x86"
+ platBuildDir = "${buildDir}/${osName}-${osArch}"
+ modDepDir = "${platBuildDir}/module-dependencies"
+
+ debug = false
+ if (!Project.hasProperty('buildType')) {
+ buildType = 'release'
+ }
+
+ if (buildType != 'release') {
+ buildType = 'debug'
+ debug = true;
+ }
+
+ ansdkOsName = osName
+ ansdkArch = (osArch == 'x86' ? 'i686' : osArch)
+ gccArchFlag = (osArch == 'x86' ? '-m32' : '-m64')
+ headSHA1 = ""
+
+ try {
+ def p = "git log -1 --pretty=%H".execute(null, new File("."))
+ p.waitFor()
+ headSHA1 = p.text.trim()
+ } catch (e) {
+ // Ignore the exception
+ headSHA1 = System.getenv('HEAD_SHA')
+ }
+
+ def props = new Properties()
+ props.load(new FileInputStream(file("version.properties")))
+ moduleVersion = props.get("server-module-version")
+ moduleRelease = props.get("release")
+ moduleName = "WebServer Module"
+ buildType = "Release Build"
+ fullVersion = "${moduleName} ${moduleVersion} ${moduleRelease} ${headSHA1}: ${buildType}"
+
+ gypPath = "$projectDir/scripts/gyp/r1919/gyp"
+ gypType = 'make'
+
+ scriptExt = 'sh'
+ sharedLibraryExt = 'so'
+
+ apache22Version = "2.2.31"
+ apache24Version = "2.4.23"
+
+ boostDir = "${modDepDir}/boost/1.55.0"
+ libraryStageDir = "${platBuildDir}/opentelemetry-webserver-sdk"
+ apacheStageDir = "${libraryStageDir}/WebServerModule/Apache"
+
+ coverageCompilerFlags = '-g -fprofile-arcs -ftest-coverage'
+ coverageLinkerFlags = '-lgcov --coverage'
+
+ COVERAGE_DIR = "${platBuildDir}/coverage"
+ LCOV_RAW_INFO = "${COVERAGE_DIR}/lcov-raw.info"
+ LCOV_INFO = "${COVERAGE_DIR}/lcov.info"
+}
+
+task extractANSDK(type: Copy) {
+ from "dependencies"
+ into modDepDir
+}
+
+task generateModuleVersionHeader(type: Copy) {
+ group = 'SDK Library'
+ description = 'Generate the module_version.h header'
+
+ def headerFile = file("src/sdk_lib/include/core/module_version.h")
+
+ from "src/module_version_template.h"
+ into "include/core"
+ rename { String f -> "module_version.h" }
+ expand(
+ headSHA1: headSHA1,
+ moduleVersion: moduleVersion,
+ moduleRelease: moduleRelease,
+ fullVersion: fullVersion)
+}
+
+task generateVersionFile(type: Copy) {
+ group = 'SDK Library'
+ description = 'Generate the VERSION.txt file'
+
+ from "dist/VERSION.txt"
+ into libraryStageDir
+ expand(
+ headSHA1: headSHA1,
+ moduleVersion: moduleVersion,
+ moduleRelease: moduleRelease,
+ fullVersion: fullVersion)
+}
+
+task generateSources {
+ group = 'SDK Library'
+ description = 'Generate all sources'
+
+ dependsOn generateVersionFile, generateModuleVersionHeader
+}
+
+// clean {
+ // Delete the platform-specific build dir
+ //delete platBuildDir
+
+ // Created by generateProtos
+ //delete 'src/sdk_lib/protos'
+
+ // Created by generateModuleVersionHeader
+ //delete 'src/sdk_lib/src/agent_version.h'
+
+ // Created by generateVersionFile
+ //delete 'scripts/VERSION.txt'
+// }
+
+task gypLibrary(type: Exec) {
+ group = 'SDK Library'
+ description = 'Run gyp to generate the platform-specific build scripts'
+
+ dependsOn extractANSDK, generateSources
+
+ inputs.file "src/build.gyp"
+
+ outputs.file "${platBuildDir}/Makefile"
+
+ ext.libraryBuildEnvironment = [
+ ARCH_FLAG: gccArchFlag,
+ ANSDK_DIR: modDepDir,
+ COMPILER_FLAGS: (coverageEnabled) ? coverageCompilerFlags : '',
+ LINKER_FLAGS: (coverageEnabled) ? coverageLinkerFlags : '',
+ ]
+
+ environment libraryBuildEnvironment
+ workingDir 'src'
+ commandLine gypPath, "--generator-output=${platBuildDir}", '--toplevel-dir=.', '--depth=./', '-f', gypType, 'build.gyp'
+}
+
+task buildLibrary(type: Exec) {
+ group = 'SDK Library'
+ description = 'Compile the SDK library'
+
+ dependsOn gypLibrary
+ inputs.property "buildType", buildType
+ inputs.dir 'src/util'
+
+ outputs.file "${platBuildDir}/out/Default/lib.target/libopentelemetry_webserver_sdk.so"
+
+ args = ['make', 'V=1', '-j', Runtime.runtime.availableProcessors()]
+
+ environment gypLibrary.libraryBuildEnvironment
+ workingDir "${platBuildDir}"
+ commandLine args
+}
+
+task stageLibrary(type: Copy) {
+ group = 'SDK Library'
+ description = 'Stage the SDK library distribution'
+
+ doLast {
+ def logDir = file("${libraryStageDir}/logs")
+ logDir.mkdirs()
+ logDir.setWritable(true)
+ }
+
+ 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.0.0-rc1/lib/libopentelemetry_common.so") { it.into "sdk_lib/lib" }
+ from("${modDepDir}/opentelemetry/1.0.0-rc1/lib/libopentelemetry_resources.so") { it.into "sdk_lib/lib" }
+ from("${modDepDir}/opentelemetry/1.0.0-rc1/lib/libopentelemetry_trace.so") { it.into "sdk_lib/lib" }
+ from("${modDepDir}/opentelemetry/1.0.0-rc1/lib/libopentelemetry_exporter_ostream_span.so") { it.into "sdk_lib/lib" }
+ from("${modDepDir}/opentelemetry/1.0.0-rc1/lib/libopentelemetry_exporter_otprotocol.so") { it.into "sdk_lib/lib" }
+ from("dist/appdynamics_sdk_log4cxx.xml.template") { it.into "conf" }
+ from("dist/install.${scriptExt}") { it.fileMode 0700 }
+
+ into libraryStageDir
+}
+
+task stripLibrary(type: Exec) {
+ group = 'SDK Library'
+ description = 'Strip the production library'
+
+ onlyIf { !debug }
+
+ inputs.dir stageLibrary
+ outputs.dir "${libraryStageDir}/sdk_lib/lib/libopentelemetry_webserver_sdk.${sharedLibraryExt}"
+
+ workingDir "${libraryStageDir}/sdk_lib/lib"
+ commandLine 'strip', '-x', "libopentelemetry_webserver_sdk.${sharedLibraryExt}"
+}
+
+task assembleLibrary(type: Tar) {
+ group = 'SDK Library'
+ description = 'Assemble the library (tgz)'
+
+ dependsOn stripLibrary
+
+ from stageLibrary
+ baseName 'opentelemetry-webserver-sdk'
+ into 'opentelemetry-webserver-sdk'
+ destinationDir buildDir
+ compression Compression.GZIP
+}
+
+// Apache
+
+task extractApache(type: Copy) {
+ from "build-dependencies"
+ into buildDir
+}
+
+task bundleAprSources {
+ inputs.files extractApache
+ outputs.dir "${platBuildDir}/httpd-${apache22Version}"
+ outputs.dir "${platBuildDir}/httpd-${apache24Version}"
+
+ doLast {
+ copy {
+ from "${buildDir}/httpd-${apache22Version}"
+ into "${platBuildDir}/httpd-${apache22Version}"
+ }
+
+ copy {
+ from "${buildDir}/httpd-${apache24Version}"
+ into "${platBuildDir}/httpd-${apache24Version}"
+ }
+
+ copy {
+ from "${buildDir}/apr-1.5.2"
+ into "${platBuildDir}/httpd-${apache22Version}/srclib/apr"
+ }
+
+ copy {
+ from "${buildDir}/apr-1.5.2"
+ into "${platBuildDir}/httpd-${apache24Version}/srclib/apr"
+ }
+
+ copy {
+ from "${buildDir}/apr-util-1.5.4"
+ into "${platBuildDir}/httpd-${apache22Version}/srclib/apr-util"
+ }
+
+ copy {
+ from "${buildDir}/apr-util-1.5.4"
+ into "${platBuildDir}/httpd-${apache24Version}/srclib/apr-util"
+ }
+ }
+}
+
+task configureApache22(type: Exec) {
+ inputs.dir bundleAprSources
+
+ workingDir "${platBuildDir}/httpd-${apache22Version}"
+ commandLine './configure', '--with-included-apr'
+}
+
+task configureApache24(type: Exec) {
+ inputs.dir extractApache
+
+ workingDir "${platBuildDir}/httpd-${apache24Version}"
+ commandLine './configure', '--with-included-apr'
+}
+
+task gypApacheModule(type: Exec) {
+ group = 'Apache Web Server Module'
+ description = 'Run gyp to generate the build files for Apache Web Server Module'
+
+ dependsOn stageLibrary
+ dependsOn configureApache22
+ dependsOn configureApache24
+
+ inputs.file "src/apache/apache.gyp"
+ outputs.file "${platBuildDir}/apache/Makefile"
+
+ ext.apacheBuildEnvironment = [
+ ARCH_FLAG: gccArchFlag,
+ APACHE22_INCLUDE_DIR: "${platBuildDir}/httpd-${apache22Version}/include",
+ APACHE24_INCLUDE_DIR: "${platBuildDir}/httpd-${apache24Version}/include",
+ APPD_SDK_LIB_DIR: "${libraryStageDir}/sdk_lib",
+ ANSDK_DIR: modDepDir,
+ COMPILER_FLAGS: (coverageEnabled) ? coverageCompilerFlags : '',
+ LINKER_FLAGS: (coverageEnabled) ? coverageLinkerFlags : '',
+ ]
+
+ environment apacheBuildEnvironment
+ workingDir 'src/apache'
+ commandLine gypPath, "--generator-output=${platBuildDir}/apache", '--toplevel-dir=.', '--depth=./', '-f', gypType, 'apache.gyp'
+}
+
+task buildApacheModule(type: Exec) {
+ group = 'Apache Web Server Module'
+ description = 'Build the Apache Web Server Module'
+
+ dependsOn gypApacheModule
+ inputs.dir 'src/util'
+ inputs.dir 'src/apache'
+ inputs.dir 'src/core'
+
+ outputs.file "${platBuildDir}/apache/out/Default/lib.target/libmod_apache_otel.so"
+ outputs.file "${platBuildDir}/apache/out/Default/lib.target/libmod_apache_otel22.so"
+
+ args = ['make', 'V=1', '-j', Runtime.runtime.availableProcessors()]
+
+ environment gypApacheModule.apacheBuildEnvironment
+ workingDir "${platBuildDir}/apache"
+ commandLine args
+}
+
+task stageApacheModule(type: Copy) {
+ group = 'Apache Web Server Module'
+ description = 'Stage the Apache Web Server Module distribution directory'
+
+ dependsOn stageLibrary
+
+ from buildApacheModule
+ into apacheStageDir
+}
+
+stageApacheModule.mustRunAfter assembleLibrary
+
+task stripApacheModule(type: Exec) {
+ group = 'Apache Web Server Module'
+ description = 'Strip the production Apache Web Server Module'
+
+ dependsOn stageApacheModule
+
+ onlyIf { !debug }
+
+ inputs.dir stageApacheModule
+ outputs.dir "${apacheStageDir}/libopentelemetry_webserver_sdk.${sharedLibraryExt}"
+
+ workingDir apacheStageDir
+ commandLine 'strip', '-x', "libmod_apache_otel.${sharedLibraryExt}"
+ commandLine 'strip', '-x', "libmod_apache_otel22.${sharedLibraryExt}"
+}
+
+task assembleApacheModule(type: Tar) {
+ group = 'Apache Web Server Module'
+ description = 'Assemble the Apache Web Server module artifact (tgz)'
+
+ dependsOn stripApacheModule
+
+ from libraryStageDir
+ baseName "opentelemetry-webserver-sdk-${osArch}-${osName}"
+ into 'opentelemetry-webserver-sdk'
+ destinationDir file(buildDir)
+ compression Compression.GZIP
+}
+
+// Tests
+
+task gypUnitTest(type: Exec) {
+ dependsOn stageLibrary
+
+ inputs.file 'test/unit/unit_test.gyp'
+ outputs.file "${platBuildDir}/unit_test/Makefile"
+
+ ext.testBuildEnvironment = [
+ APPD_SDK_LIB_DIR: "${libraryStageDir}/sdk_lib",
+ ANSDK_DIR: modDepDir
+ ]
+
+ environment testBuildEnvironment
+ workingDir 'test/unit'
+ commandLine gypPath, "--generator-output=${platBuildDir}/unit_test", '--toplevel-dir=.', '--depth=./', '-f', gypType, 'unit_test.gyp'
+}
+
+task makeUnitTest(type: Exec) {
+ dependsOn gypUnitTest
+
+ inputs.dir 'test/unit'
+
+ outputs.file "${platBuildDir}/unit_test/out/Default/unit_test"
+
+ environment gypUnitTest.testBuildEnvironment
+ workingDir "${platBuildDir}/unit_test"
+ commandLine 'make', 'V=1'
+}
+
+task runUnitTest(type: Exec) {
+ dependsOn makeUnitTest
+ environment gypUnitTest.testBuildEnvironment
+
+ environment "LD_LIBRARY_PATH", "${libraryStageDir}/sdk_lib/lib/"
+
+ workingDir "${platBuildDir}/unit_test/out/Default"
+ commandLine './unit_test'
+}
+
+task runApacheServer(type: Exec) {
+ dependsOn assembleApacheModule
+
+ workingDir 'test'
+ commandLine './ApacheTesting.sh'
+}
+
+// Code Coverage
+
+task lcovCapture(type: Exec) {
+ group = 'Code Coverage'
+ description = 'capture coverage info'
+
+ dependsOn runApacheServer
+ dependsOn runUnitTest
+
+ ext.tracefile = file(LCOV_RAW_INFO)
+
+ outputs.file tracefile
+
+ executable 'lcov'
+ args '--output-file', tracefile, // resulting tracefile
+ '--capture', // capture counts for a user space program
+ '--directory', "${platBuildDir}" // location where the program was compiled
+// '--no-external' // ignore data for external files
+}
+
+task lcov(type: Exec) {
+ group = 'Code Coverage'
+ description = 'remove noise from captured coverage info'
+
+ dependsOn lcovCapture
+
+ ext.tracefile = file(LCOV_INFO)
+
+ inputs.file lcovCapture.tracefile
+ outputs.file tracefile
+
+ executable 'lcov'
+ args '--quiet', // do not print progress messages
+ '--output-file', tracefile, // resulting tracefile
+ '--remove', lcovCapture.tracefile, // remove files matching patterns from tracefile
+ '*/prebuilt/*', '*.pb.*' // list of patterns
+}
+
+task coverageHtml(type: Exec) {
+ group = 'Code Coverage'
+ description = 'generate html coverage report'
+
+ dependsOn lcov
+
+ inputs.file lcov.tracefile
+ outputs.dir COVERAGE_DIR
+
+ executable 'genhtml'
+ args '--quiet', // do not print progress messages
+ '--output-directory', COVERAGE_DIR, // write HTML to this directory
+ '--show-details', // generate detailed directory view
+ '--keep-descriptions', // do not remove unused test descriptions
+ '--title', project.name, // display the specified title in header of all pages
+ '--demangle-cpp', // show user-friendly function names
+ lcov.tracefile
+}
+
+model {
+ buildTypes {
+ debug
+ release
+ }
+ platforms {
+ x86 {
+ architecture "x86"
+ }
+ x64 {
+ architecture "x86_64"
+ }
+ }
+
+ binaries {
+ all {
+ tasks.withType(CppCompile) {
+ dependsOn ':vendor:boost:assemble'
+ }
+
+ if (toolChain in Clang) {
+ cppCompiler.args "-fcolor-diagnostics"
+ }
+
+ if (toolChain in Clang || toolChain in Gcc) {
+ cppCompiler.args "-Wall", "-std=c++11", "-g"
+
+ if (buildType == buildTypes.debug) {
+ cppCompiler.args "-g"
+ }
+ }
+ else if (toolChain in VisualCpp) {
+ cppCompiler.args "/Wall"
+ }
+ }
+ }
+
+ repositories {
+ libs(PrebuiltLibraries) { libs ->
+ appd {
+ headers.srcDirs "${libraryStageDir}/sdk_lib"
+ // See FIXME on sources.cpp.lib library: 'appd' above
+ // binaries.withType(SharedLibraryBinary) {
+ // sharedLibraryFile = file("${libraryStageDir}/sdk_lib/lib/libopentelemetry_webserver_sdk.so")
+ // }
+ }
+ }
+ }
+
+ tasks {
+ }
+}
diff --git a/instrumentation/otel-webserver-module/build.sh b/instrumentation/otel-webserver-module/build.sh
new file mode 100755
index 000000000..7814ee040
--- /dev/null
+++ b/instrumentation/otel-webserver-module/build.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+
+git clone https://github.com/cisco-open/otel-webserver-module.git
+cp -r /dependencies /otel-webserver-module/
+
+cp -r /build-dependencies /otel-webserver-module/
+
+# change gradle script to include build-dependencies folder
+
+# Building the otel-webserver-module
+
+cd otel-webserver-module
+./gradlew assembleApacheModule -PbuildType=debug
+
+#Changing the httpd.conf and Adding Opentelemetry.conf
+cd build
+tar -xf opentelemetry-webserver-sdk-x64-linux.tgz
+mv opentelemetry-webserver-sdk /opt/
+cd ../
+cp opentelemetry_module.conf /etc/httpd/conf.d/
+
+# Installing
+
+cd /opt/opentelemetry-webserver-sdk
+./install.sh
+
+# Runing Apache
+
+httpd
+curl localhost:80
+
+
+
diff --git a/instrumentation/otel-webserver-module/common.gradle b/instrumentation/otel-webserver-module/common.gradle
new file mode 100644
index 000000000..cc5707768
--- /dev/null
+++ b/instrumentation/otel-webserver-module/common.gradle
@@ -0,0 +1,145 @@
+import org.gradle.internal.os.OperatingSystem
+
+apply plugin: 'cpp'
+apply plugin: "visual-studio"
+
+defaultTasks 'build'
+
+ext {
+ ARCH = ''
+ switch (System.properties['os.arch'].toLowerCase()) {
+ case "amd64":
+ case "x86_64":
+ ARCH = "x64"
+ break
+ case "x86":
+ case "i386":
+ case "i586":
+ case "i686":
+ ARCH = "x86"
+ break
+ default:
+ println "ERROR: unknown architecture " + System.properties['os.arch'].toLowerCase()
+ }
+
+ OS = OperatingSystem.current().getFamilyName().replaceAll("\\s", "")
+ COMPILE = System.getProperty('libagent.vendor.compile') == 'true'
+
+ HEAD_SHA1 = ""
+ try {
+ def p = "git log -1 --pretty=%H".execute(null, new File("."))
+ p.waitFor()
+ HEAD_SHA1 = p.text.trim()
+ } catch (e) {
+ }
+
+ os = OperatingSystem.current()
+ osArch = System.properties['os.arch']
+
+ osName = 'linux'
+
+ if (osArch == 'i386' || osArch == 'i586' || osArch == 'i686') {
+ osArch = 'x86'
+ } else if (osArch == 'x86_64' || osArch == 'amd64') {
+ osArch = 'x64'
+ }
+
+ BUILD_SHA1 = System.getenv('BUILD_SHA')
+ SHA1 = (BUILD_SHA1 && BUILD_SHA1.length()) ? BUILD_SHA1 : HEAD_SHA1
+
+ TEAMCITY_BUILD_NUMBER = System.getenv('BUILD_NUMBER') ?: ''
+}
+
+model {
+ visualStudio {
+ projects.all {
+ projectFile.location = "${buildDir}/vs/${name}.vcxproj"
+ filtersFile.location = "${buildDir}/vs/${name}.vcxproj.filters"
+ }
+ }
+}
+
+if (!rootProject.ext.has('LINUX_TOOL_CHAIN')) {
+ rootProject.ext.TOOL_CHAIN_FROZEN = false
+ rootProject.ext.LINUX_TOOL_CHAIN = 'gcc'
+}
+
+if (OperatingSystem.current().isLinux() && !rootProject.ext.has('LINUX_LIBC')){
+ def stdout = new ByteArrayOutputStream()
+ def stderror = new ByteArrayOutputStream()
+ exec {
+ commandLine 'ldd', '--version'
+ standardOutput stdout
+ errorOutput stderror
+ ignoreExitValue true
+ }
+ def lddOutput = stdout.toString() + "|" + stderror.toString()
+ if (lddOutput.contains("musl")) {
+ rootProject.ext.LINUX_LIBC = "musl"
+ }
+ else {
+ rootProject.ext.LINUX_LIBC = "glibc"
+ }
+ println "Detected clib: ${rootProject.ext.LINUX_LIBC}"
+}
+
+ext.selectDefaulToolChain = {toolchain ->
+ if (rootProject.ext.TOOL_CHAIN_FROZEN) {
+ println "Toolchain ${rootProject.ext.LINUX_TOOL_CHAIN} already frozen. Skip selection for ${toolchain}"
+ }
+
+ rootProject.ext.LINUX_TOOL_CHAIN = System.getProperty("toolchain")
+ if (!rootProject.ext.LINUX_TOOL_CHAIN) {
+ rootProject.ext.LINUX_TOOL_CHAIN = toolchain
+ }
+ if (!rootProject.ext.LINUX_TOOL_CHAIN) {
+ rootProject.ext.LINUX_TOOL_CHAIN = "gcc"
+ }
+ println "Selected toolchain: ${rootProject.ext.LINUX_TOOL_CHAIN}"
+}
+
+ext.freezeToolChain = { ->
+ if (!rootProject.ext.LINUX_TOOL_CHAIN) {
+ selectDefaulToolChain('')
+ }
+ rootProject.ext.TOOL_CHAIN_FROZEN = true
+}
+
+def callClagFormat(validate) {
+ def srcPaths = fileTree('include/') + fileTree('src/') + fileTree('test/');
+ def srcFiles = srcPaths.matching {
+ include '**/*.cc'
+ include '**/*.cpp'
+ include '**/*.h'
+ include '**/*.hpp'
+ }
+ srcFiles.each { srcFile ->
+ new ByteArrayOutputStream().withStream { os ->
+ exec {
+ commandLine 'clang-format'
+ args '-i', srcFile.absoluteFile
+ if (validate){
+ args '-output-replacements-xml'
+ standardOutput os
+ }
+ }
+ if (validate && os.toString().contains('replacement ')) {
+ throw new GradleException("Invalid formatting in ${srcFile.absoluteFile}. Please call format task.")
+ }
+ }
+ }
+}
+
+task format {
+ description = 'run clang-format on all source files'
+ doLast {
+ callClagFormat(false)
+ }
+}
+
+task validateFormat {
+ description = 'validate that clang-format was called on all source files'
+ doLast {
+ callClagFormat(true)
+ }
+}
diff --git a/instrumentation/otel-webserver-module/dist/Install_Native.txt b/instrumentation/otel-webserver-module/dist/Install_Native.txt
new file mode 100644
index 000000000..65fdbfbd6
--- /dev/null
+++ b/instrumentation/otel-webserver-module/dist/Install_Native.txt
@@ -0,0 +1,27 @@
+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/VERSION.txt b/instrumentation/otel-webserver-module/dist/VERSION.txt
new file mode 100644
index 000000000..6754eb3ef
--- /dev/null
+++ b/instrumentation/otel-webserver-module/dist/VERSION.txt
@@ -0,0 +1 @@
+${moduleVersion}${moduleRelease}-${headSHA1}
diff --git a/instrumentation/otel-webserver-module/dist/appdynamics_sdk_log4cxx.xml.template b/instrumentation/otel-webserver-module/dist/appdynamics_sdk_log4cxx.xml.template
new file mode 100755
index 000000000..345f38c4b
--- /dev/null
+++ b/instrumentation/otel-webserver-module/dist/appdynamics_sdk_log4cxx.xml.template
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/instrumentation/otel-webserver-module/dist/install.sh b/instrumentation/otel-webserver-module/dist/install.sh
new file mode 100755
index 000000000..413e47c81
--- /dev/null
+++ b/instrumentation/otel-webserver-module/dist/install.sh
@@ -0,0 +1,175 @@
+#!/bin/sh
+#
+#
+# Copyright 2014 AppDynamics.
+# All rights reserved.
+#
+#
+# Install script for AppDynamics WebServer agent
+#
+usage() {
+cat << EOF
+ Usage: `basename $0`
+ Options:
+ -h,--help Show Help
+ --ignore-permissions Ignores lack of write permissions on log and read permissions on the sdk folder
+EOF
+}
+
+canonicalNameOfThisFile=`readlink -f "$0"`
+containingDir=`dirname "$canonicalNameOfThisFile"`
+agentVersionId=$(cat ${containingDir}/VERSION.txt)
+ignoreFilePermissions="false"
+ok=1
+optspec=":h-:"
+
+while getopts "$optspec" optchar; do
+ case "${optchar}" in
+ -)
+ case "${OPTARG}" in
+ help)
+ usage
+ exit 1
+ ;;
+ ignore-permissions)
+ ignoreFilePermissions="true"
+ ;;
+ *)
+ ok=0
+ echo "Invalid option: '--${OPTARG}'" >&2
+ ;;
+ esac
+ ;;
+ h)
+ usage
+ exit 1
+ ;;
+ esac
+done
+if [ "$ok" != 1 ]; then
+ usage
+ rm -f ${install_log}
+ exit 1
+fi
+################################################################################
+# Define functions
+################################################################################
+
+log() {
+ echo "$@" >> ${install_log}
+ if [ -z "${APPD_AUTO_MODE}" ]; then
+ echo "$@"
+ fi
+}
+
+log_error() {
+ echo "[Error] $@" >> ${install_log}
+ echo "[Error] $@" >&2
+}
+
+fatal_error() {
+ log_error $1
+ cat >&2 </dev/null)
+ if [ -z "${findResult}" ] ; then
+ __result="${currentPath}"
+ break
+ fi
+ currentPath=$(dirname "${currentPath}")
+ done
+ eval $__resultVarName="$__result"
+}
+
+if [ -z "${APPD_LOCATION}" ]; then
+ APPD_LOCATION=$containingDir
+ APPD_PACKAGE=0
+else
+ APPD_PACKAGE=1
+fi
+
+datestamp=`date +%Y_%m_%d_%H_%M_%S 2>/dev/null`
+install_log=/tmp/appd_install_${datestamp}.log
+rm -f $install_log > /dev/null 2>&1
+cat > $install_log </dev/null`
+
+Hostname: `hostname`
+Location: ${APPD_LOCATION}
+System: `uname -a 2>/dev/null`
+User: `id`
+Environment:
+################################################################################
+`env | sort`
+################################################################################
+EOF
+
+echo "Install script for AppDynamics WebServer Agent ${agentVersionId}"
+
+# Check for SELinux
+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."
+ fi
+fi
+
+## Installed files locations
+log4cxxFile="${containingDir}/conf/appdynamics_sdk_log4cxx.xml"
+
+rootDirCheck=
+checkPathIsAccessible rootDirCheck "${containingDir}"
+if [ -n "${rootDirCheck}" ] ; then
+ if [ "${ignoreFilePermissions}" = "true" ] ; then
+ log "WebServer directory '${containingDir}' is not readable by all users"
+ else
+ log_error "WebServer directory '${containingDir}' is not readable by all users"
+ fatal_error "Change the permissions of '${rootDirCheck}' or specify --ignore-permissions"
+ fi
+fi
+
+agentLogDir="${containingDir}/logs"
+
+chmod 0777 "$agentLogDir"
+#chmod 0770 "${containingDir}/proxy/conf" "${containingDir}/proxy/logs" "${containingDir}/runSDKProxy.sh" "${containingDir}/proxy/runProxy"
+
+# write log4cxx file
+escapeForSedReplacement agentLogDir "${agentLogDir}"
+log4cxxTemplate="${log4cxxFile}.template"
+log4cxxTemplateOwner=$(stat "--format=%u" "${log4cxxTemplate}")
+log4cxxTemplateGroup=$(stat "--format=%g" "${log4cxxTemplate}")
+log "Writing '${log4cxxFile}'"
+cat "${log4cxxTemplate}" | \
+ sed -e "s/__agent_log_dir__/${agentLogDir}/g" \
+ > "${log4cxxFile}"
+if [ $? -ne 0 ] ; then
+ fatal_error "Unable to write '${log4cxxFile}'"
+fi
+
+chown "${log4cxxTemplateOwner}" "${log4cxxFile}"
+chgrp "${log4cxxTemplateGroup}" "${log4cxxFile}"
+chmod a+r "${log4cxxFile}"
diff --git a/instrumentation/otel-webserver-module/docker-compose.yml b/instrumentation/otel-webserver-module/docker-compose.yml
new file mode 100644
index 000000000..3817805db
--- /dev/null
+++ b/instrumentation/otel-webserver-module/docker-compose.yml
@@ -0,0 +1,38 @@
+version: "3.9"
+networks:
+ default:
+ name: webserver-network
+services:
+ webserver:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: apache
+ hostname: webserver
+ container_name: webserver
+ command: bash -c " httpd -k start && tail -f /dev/null "
+ ports:
+ - "8000:80"
+ depends_on:
+ - otel-collector
+# Collector
+ otel-collector:
+ image: otel/opentelemetry-collector:latest
+ container_name: collector
+ command: ["--config=/etc/otel-config.yml", "--log-level=DEBUG", "${OTELCOL_ARGS}"]
+ volumes:
+ - ./otel-config.yml:/etc/otel-config.yml
+ ports:
+ - "4317:4317" # grpc
+ - "55678:55678"
+ - "55679:55679"
+ depends_on:
+ - zipkin
+
+# Zipkin
+ zipkin:
+ image: openzipkin/zipkin:latest
+ container_name: zipkin
+ ports:
+ - "9411:9411"
+ - "9410:9410"
diff --git a/instrumentation/otel-webserver-module/entrypoint.sh b/instrumentation/otel-webserver-module/entrypoint.sh
new file mode 100755
index 000000000..41bc41529
--- /dev/null
+++ b/instrumentation/otel-webserver-module/entrypoint.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+export PATH="/opt/rh/devtoolset-7/root/usr/bin:/usr/local/sbin:/usr/local/bin:$PATH"
+
+exec gosu root "$@"
diff --git a/instrumentation/otel-webserver-module/gradle.properties b/instrumentation/otel-webserver-module/gradle.properties
new file mode 100644
index 000000000..915b9f326
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle.properties
@@ -0,0 +1,3 @@
+org.gradle.configureondemand=true
+org.gradle.caching=true
+org.gradle.parallel=true
diff --git a/instrumentation/otel-webserver-module/gradle/conf/checkstyle/checkstyle.xml b/instrumentation/otel-webserver-module/gradle/conf/checkstyle/checkstyle.xml
new file mode 100644
index 000000000..64601168c
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle/conf/checkstyle/checkstyle.xml
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/instrumentation/otel-webserver-module/gradle/conf/checkstyle/checkstyle.xsl b/instrumentation/otel-webserver-module/gradle/conf/checkstyle/checkstyle.xsl
new file mode 100644
index 000000000..1a3217377
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle/conf/checkstyle/checkstyle.xsl
@@ -0,0 +1,100 @@
+
+
+
+
+
+ AppDynamics Java CheckStyle Report
+
+
+
+
AppDynamics Java CheckStyle Report
+
+
+
+
+ Summary
+ |
+
+
+ Total files checked |
+
+
+ |
+
+
+ Files with errors or warnings |
+
+
+ |
+
+
+ Total errors and warnings |
+
+
+ |
+
+
+ Average errors or warnings per file |
+
+
+ |
+
+
+
+ The following are violations of the
+
+ AppDynamics Java Coding Style Guide:
+
+
+
+
+
+
+
+
+
+
+ File |
+
+
+ |
+
+
+ Line Number |
+ Severity |
+ Error Message |
+
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
\ No newline at end of file
diff --git a/instrumentation/otel-webserver-module/gradle/conf/checkstyle/suppressions.xml b/instrumentation/otel-webserver-module/gradle/conf/checkstyle/suppressions.xml
new file mode 100644
index 000000000..f4fe2dd5a
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle/conf/checkstyle/suppressions.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/instrumentation/otel-webserver-module/gradle/conf/dependency-check/suppressions.xml b/instrumentation/otel-webserver-module/gradle/conf/dependency-check/suppressions.xml
new file mode 100644
index 000000000..5967cec67
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle/conf/dependency-check/suppressions.xml
@@ -0,0 +1,346 @@
+
+
+
+
+
+
+
+
+
+
+ 057BBDC0B4472D1ACF5CDB7455F4E21A786F43DE
+ cpe:/a:adobe:adobe_air:-
+
+
+
+ 057BBDC0B4472D1ACF5CDB7455F4E21A786F43DE
+ cpe:/a:adobe:air:-
+
+
+
+ 4F5D696041780C11B4AB897A0632E85BE4DE089D
+ cpe:/a:webkit:webkit:-
+
+
+
+
+
+
+
+ E274F02832A28646C3B4DB50361D4FEAFC56F420
+ cpe:/a:sonatype:nexus:1.0
+
+
+
+ 32BEAC9F09FB1626840A579815773F3D115B5BBD
+ cpe:/a:sonatype:nexus:1.0
+
+
+
+ A5B6EF3535614EA6D5332123E2B5083CEF52A4EA
+ cpe:/a:sonatype:nexus:1.0
+
+
+
+ 098EEAA489DFBF6C336157D03EF2737A84AFA408
+ cpe:/a:sonatype:nexus:1.0.5
+
+
+
+ C53F20F540FA651C1E25EF4B76EA4D18F21F8BB3
+ cpe:/a:sonatype:nexus:1.2.15
+
+
+
+ 5C7B4B099CA2F9FDB6B6B9A370051D7510D2865B
+ cpe:/a:sonatype:nexus:2.2
+
+
+
+ DD56441BC483FEE61FD3990BFAD8DB5A2FEF7F59
+ cpe:/a:sonatype:nexus:1.3.3
+
+
+
+ 59757E934E7F8D51A8E1B21E03476BA0C906EFF4
+ cpe:/a:sonatype:nexus:1.6.0.13
+
+
+
+ AC846AFAD6E4543D8B89FEC531E461A953CEEE2F
+ cpe:/a:sonatype:nexus:2.0
+
+
+
+ 9DD990B47D794904DD0B3FD8159C8EB9D3DCF9C0
+ cpe:/a:sonatype:nexus:1.3
+
+
+
+ E91A355D337A0B1991F54181627D63C9973624C3
+ cpe:/a:sonatype:nexus:1.6.4
+
+
+
+ 0EADCFDAA573CD5F163103DDFD46FF6457F35F54
+ cpe:/a:sonatype:nexus:2.7.1::~~open_source~~~
+
+
+
+ 868C0792233FC78D8C9BAC29AC79ADE988301318
+ cpe:/a:sonatype:nexus:2.7.1::~~open_source~~~
+
+
+
+
+
+ 9dbac6cb2e05715b5b55f92187e7dc52f8c718e1
+ CVE-2014-3577
+
+
+
+
+
+
+ 4aa88b0c7facf3f2cd54d8575e9ddfeb6e73e428
+ cpe:/a:apache:httpclient:3.1.2
+
+
+
+
+
+
+ 761ea405b9b37ced573d2df0d1e3a4e0f9edc668
+ CVE-2015-6420
+
+
+
+
+
+
+ 01b2502e29da1ebaade2357cd1de35a855fa3755
+ CVE-2014-0085
+
+
+
+
+
+
+ 0232abfe1f919127e9cfcd6e4e2c6324bb394535
+ CVE-2015-2808
+
+
+
+ 0232abfe1f919127e9cfcd6e4e2c6324bb394535
+ CVE-2013-2566
+
+
+
+
+ a50914ff519682e185bca4385b4313b8c8a81775
+ CVE-2015-2808
+
+
+
+ a50914ff519682e185bca4385b4313b8c8a81775
+ CVE-2013-2566
+
+
+
+
+
+
+ E4A43DFF399B7164307C5B386656FD05DBC41C97
+ cpe:/a:microsoft:silverlight:-
+
+
+
+ 108D7C8A4F753F55433E1C195BB9E8F548BD627D
+ cpe:/a:microsoft:silverlight:-
+
+
+
+ E89D5608B9FF88A3078B00FC642240B5DE3C352E
+ cpe:/a:microsoft:silverlight:-
+
+
+
+ E89D5608B9FF88A3078B00FC642240B5DE3C352E
+ cpe:/a:microsoft:visual_studio:-
+
+
+
+ E8D46980845D785615C7687FE51FB85D141F5297
+ cpe:/a:microsoft:silverlight:-
+
+
+
+ E8D46980845D785615C7687FE51FB85D141F5297
+ cpe:/a:microsoft:visual_studio:-
+
+
+
+
+
+ D07EAC49E1E8309021482E09C22915570A1AFE90
+ cpe:/a:mono:mono:-
+
+
+
+
+
+ AD76F0EEB93B3C31DCCABBAADAA0D6407C052BA3
+ cpe:/a:nlog:nlog:-
+
+
+
+ 14D4E4F12776C25AE2AC12501EC6B2CE69BD245B
+ cpe:/a:nlog:nlog:-
+
+
+
+ F394D360B39FFB99F3B9B30D2F8FD92EC4966408
+ cpe:/a:bzip:bzip2:-
+
+
+
+
+ 475D635C24F067E8B0282FB2467704A7140B1780
+ cpe:/a:docker:docker:0.9.0
+
+
+
+
+ CBA7E76DF24964A58A820D436B6057F7C0510C90
+ cpe:/a:mysql:mysql:5.1.13
+
+
+
+
+ D9B2A7AF24A8C6E1A1DA8EC25602577BEF4FE32D
+ cpe:/a:ibm:db2:4.16.53
+
+
+
+
+ F05906F45C3D3949A418DE5FF26CC1756429B029
+ cpe:/a:jruby:jruby:0.3.0
+
+
diff --git a/instrumentation/otel-webserver-module/gradle/custom-settings/example.gradle b/instrumentation/otel-webserver-module/gradle/custom-settings/example.gradle
new file mode 100644
index 000000000..734bbf63d
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle/custom-settings/example.gradle
@@ -0,0 +1,10 @@
+def run(settings, groupProjects) {
+ settings.with {
+ include 'utils'
+ include 'dbmon:dbmon-api'
+ include 'analytics:analytics-shared-rest'
+ include 'controller:controller-api:agent'
+
+ // add all your includes...
+ }
+}
diff --git a/instrumentation/otel-webserver-module/gradle/wrapper/gradle-wrapper.jar b/instrumentation/otel-webserver-module/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..1948b9074
Binary files /dev/null and b/instrumentation/otel-webserver-module/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/instrumentation/otel-webserver-module/gradle/wrapper/gradle-wrapper.properties b/instrumentation/otel-webserver-module/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..d76b502e2
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/instrumentation/otel-webserver-module/gradlew b/instrumentation/otel-webserver-module/gradlew
new file mode 100755
index 000000000..cccdd3d51
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/instrumentation/otel-webserver-module/gradlew.bat b/instrumentation/otel-webserver-module/gradlew.bat
new file mode 100644
index 000000000..f9553162f
--- /dev/null
+++ b/instrumentation/otel-webserver-module/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h
new file mode 100644
index 000000000..9e72af3b2
--- /dev/null
+++ b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h
@@ -0,0 +1,289 @@
+/*
+* 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 APPD_APACHECONFIG_H
+#define APPD_APACHECONFIG_H
+#define SIZE 5 //Fixed SIZE (intermediate value chosen as 5) for masking private data if any before logging into Apache logs
+
+#include
+#include
+#include
+#include "httpd.h" // request_rec
+#include "http_config.h" // cmd_parms
+
+class appd_cfg
+{
+public:
+ void init();
+ bool validate(const request_rec *r);
+
+ int getAppdEnabled() { return appdEnabled; }
+ int getAppdEnabledInitialized() { return appdEnabled_initialized; }
+
+ const char* getOtelExporterType() { return otelExporterType; }
+ int getOtelExporterTypeInitialized() { return otelExporterType_initialized; }
+
+ const char* getOtelExporterEndpoint() { return otelExporterEndpoint; }
+ int getOtelExporterEndpointInitialized() { return otelExporterEndpoint_initialized; }
+
+ int getOtelSslEnabled() { return otelSslEnabled; }
+ int getOtelSslEnabledInitialized() { return otelSslEnabled_initialized; }
+
+ const char* getOtelSslCertificatePath() { return otelSslCertificatePath; }
+ int getOtelSslCertificatePathInitialized() { return otelSslCertificatePath_initialized; }
+
+ const char* getOtelProcessorType() { return otelProcessorType; }
+ int getOtelProcessorTypeInitialized() { return otelProcessorType_initialized; }
+
+ const char* getOtelSamplerType() { return otelSamplerType; }
+ int getOtelSamplerTypeInitialized() { return otelSamplerType_initialized; }
+
+ const char* getServiceNamespace() { return serviceNamespace; }
+ int getServiceNamespaceInitialized() { return serviceNamespace_initialized; }
+
+ const char* getServiceName() { return serviceName; }
+ int getServiceNameInitialized() { return serviceName_initialized; }
+
+ const char* getServiceInstanceId() { return serviceInstanceId; }
+ int getServiceInstanceIdInitialized() { return serviceInstanceId_initialized; }
+
+ const char* getOtelMaxQueueSize() { return otelMaxQueueSize; }
+ int getOtelMaxQueueSizeInitialized() { return otelMaxQueueSize_initialized; }
+
+ const char* getOtelScheduledDelay() { return otelScheduledDelay; }
+ int getOtelScheduledDelayInitialized() { return otelScheduledDelay_initialized; }
+
+ const char* getOtelExportTimeout() { return otelExportTimeout; }
+ int getOtelExportTimeoutInitialized() { return otelExportTimeout_initialized; }
+
+ const char* getOtelMaxExportBatchSize() { return otelMaxExportBatchSize; }
+ int getOtelMaxExportBatchSizeInitialized() { return otelMaxExportBatchSize_initialized; }
+
+ int getResolveBackends() { return resolveBackends; }
+ int getResolveBackendsInitialized() { return resolveBackends_initialized; }
+
+ int getTraceAsError() { return traceAsError; }
+ int getTraceAsErrorInitialized() { return traceAsError_initialized; }
+
+ int getReportAllInstrumentedModules() { return reportAllInstrumentedModules; }
+ int getReportAllInstrumentedModulesInitialized() { return reportAllInstrumentedModules_initialized; }
+
+ char* getLoc() { return loc; }
+
+ int getMaskCookie() { return maskCookie; }
+ int getMaskCookieInitialized() { return maskCookie_initialized; }
+
+ const char* getCookiePattern() { return cookiePattern; }
+ int getCookiePatternInitialized() { return cookiePattern_initialized; }
+
+ int getMaskSmUser() { return maskSmUser; }
+ int getMaskSmUserInitialized() { return maskSmUser_initialized; }
+
+ const char* getDelimiter() { return delimiter; }
+ int getDelimiterInitialized() { return delimiter_initialized; }
+
+ const char* getSegment() { return segment; }
+ int getSegmentInitialized() { return segment_initialized; }
+
+ const char* getMatchFilter() { return matchFilter; }
+ int getMatchFilterInitialized() { return matchFilter_initialized; }
+
+ const char* getMatchPattern() { return matchPattern; }
+ int getMatchPatternInitialized() { return matchPattern_initialized; }
+
+ const char* getSegmentType() { return segmentType; }
+ int getSegmentTypeInitialized() { return segmentType_initialized; }
+
+ const char* getSegmentParameter() { return segmentParameter; }
+ int getSegmentParameterInitialized() { return segmentParameter_initialized; }
+
+ friend class ApacheConfigHandlers;
+
+private:
+ // Agent to Controller Connection Configuration
+ int appdEnabled; // OPTIONAL: 0 for false, 1 for true (defaults to true)
+ int appdEnabled_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
+ int otelExporterEndpoint_initialized;
+
+ int otelSslEnabled; // OPTIONAL: Decision whether connection to the Exporter endpoint is secured
+ int otelSslEnabled_initialized;
+
+ const char *otelSslCertificatePath; // OPTIONAL: Certificate path to be mentioned if OtelSslEnabled is set;
+ int otelSslCertificatePath_initialized;
+
+ const char *otelProcessorType; // OPTIONAL: Decision on how to pass finished and export-friendly span data representation to configured span exporter
+ int otelProcessorType_initialized;
+
+ 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
+ int serviceNamespace_initialized;
+
+ const char *serviceName; // REQUIRED: Logical name of the service; equivalent to your AppDynamics tier name
+ int serviceName_initialized;
+
+ const char *serviceInstanceId; // REQUIRED: The string ID of the service instance. Distinguish between instances of a service
+ int serviceInstanceId_initialized;
+
+ const char *otelMaxQueueSize; // OPTIONAL: The maximum queue size. After the size is reached spans are dropped
+ int otelMaxQueueSize_initialized;
+
+ const char *otelScheduledDelay; // OPTIONAL: The delay interval in milliseconds between two consecutive exports
+ int otelScheduledDelay_initialized;
+
+ const char *otelExportTimeout; // OPTIONAL: How long the export can run in milliseconds before it is cancelled
+ int otelExportTimeout_initialized;
+
+ const char *otelMaxExportBatchSize; // OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize
+ int otelMaxExportBatchSize_initialized;
+
+ int resolveBackends; // OPTIONAL: Resolve backends as a tier
+ int resolveBackends_initialized;
+
+ int traceAsError; // OPTIONAL: Determine whether we put all diagnostic output to error_log
+ int traceAsError_initialized;
+
+ int reportAllInstrumentedModules; // OPTIONAL: Report ALL modules as backends instead of only HANDLER modules
+ int reportAllInstrumentedModules_initialized;
+
+ // variables for tracing calls
+ char *loc; // Location to which this record applies.
+
+ // GDPR: cookie masking
+ int maskCookie; // OPTIONAL: Mask Coookies
+ int maskCookie_initialized;
+
+ const char *cookiePattern; // OPTIONAL: Required only if there is a need to mask part of cookie, otherwise it will mask whole cookie if maskCookie is enabled
+ int cookiePattern_initialized;
+
+ int maskSmUser; // OPTIONAL: Mask SM_USER
+ int maskSmUser_initialized;
+
+ // URL redaction
+ const char *delimiter; // OPTIONAL: Required only if there is a need to redact certain URL segments
+ int delimiter_initialized;
+
+ const char *segment; // OPTIONAL: Required only if there is a need to redact certain URL segments
+ int segment_initialized;
+
+ const char *matchFilter; // OPTIONAL: Required only if there is a need to redact certain URL segments
+ int matchFilter_initialized;
+
+ const char *matchPattern; // OPTIONAL: Required only if there is a need to redact certain URL segments
+ int matchPattern_initialized;
+
+ // Rules on how the span/BT name would be created.
+ const char *segmentType; // OPTIONAL: Possible Values are FIRST, LAST, CUSTOM..
+ int segmentType_initialized;
+
+ const char *segmentParameter; // OPTIONAL: Should be specified if segmentType is provided.
+ int segmentParameter_initialized; // if FIRST/LAST is choosen above, segment count should be provided.
+ // if CUSTOM is choosen, segment numbers should be provided such as 2,3
+
+};
+
+class WebserverContext
+{
+public:
+ std::string m_serviceNamespace;
+ std::string m_serviceName;
+ std::string m_serviceInstanceId;
+ // TODO: in future we may need to put in controller host/port, account name, access key, etc
+
+ WebserverContext(const char* serviceNamespace, const char* serviceName, const char* serviceInstanceId)
+ : m_serviceNamespace(serviceNamespace), m_serviceName(serviceName), m_serviceInstanceId(serviceInstanceId) {};
+
+private:
+ WebserverContext() {};
+};
+
+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(
+ 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 appd_cfg* getConfig(const request_rec* r);
+ static appd_cfg* getProcessConfig(const request_rec* r);
+
+ static std::string computeContextName(const appd_cfg* cfg);
+
+ static std::string hashPassword(const char* arg);
+
+ static void traceConfig(const request_rec* r, const appd_cfg* cfg);
+
+private:
+ static appd_cfg* our_dconfig(const request_rec *r);
+
+ static const char* helperChar(
+ cmd_parms* cmd,
+ appd_cfg* cfg,
+ const char* arg,
+ const char*& var,
+ int& inherit,
+ const char* varName);
+ static const char* helperInt(
+ cmd_parms* cmd,
+ appd_cfg* cfg,
+ const char* arg,
+ int& var,
+ int& inherit,
+ const char* varName);
+ static void insertWebserverContext(cmd_parms* cmd, const appd_cfg* cfg);
+};
+
+#endif
diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h
new file mode 100644
index 000000000..1ba75db79
--- /dev/null
+++ b/instrumentation/otel-webserver-module/include/apache/ApacheHooks.h
@@ -0,0 +1,220 @@
+/*
+* 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.
+*/
+
+// This file includes are apache module hook functions
+#ifndef APPD_APACHEHOOKS_H
+#define APPD_APACHEHOOKS_H
+
+#include
+#include
+#include "HookContainer.h"
+#include "ExcludedModules.h"
+
+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 int LOWEST_HTTP_ERROR_CODE = 400;
+ static const std::initializer_list httpHeaders;
+ static void registerHooks(apr_pool_t *p);
+
+ 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 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);
+
+ // Callback to start an Interaction
+
+ // The HANDLER stage does not always run all the hooks. After a hook returns "OK", the stage
+ // will end and the remaining hooks are ignored. We use this behavior to ignore any backend calls
+ // that do not go out to another tier. Thus, if we hit any of the backend_end hook in HANDLER,
+ // 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(
+ request_rec *r,
+ HookContainer::appd_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 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);
+
+ // 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);
+};
+
+class ApacheHooksForStage
+{
+public:
+ // 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**);
+
+ /*
+ function prototypes for the apache module hook callbacks according to different stages
+ */
+ typedef int (*processRequestHooks) (request_rec*); // create_request, post_read_request, header_parser,
+ // translate_name, map_to_storage, access_checker_ex, access_checker, check_user_id, auth_checker,
+ // type_checker, fixups, handler, log_transaction
+ typedef int (*quickHandlerHooks) (request_rec*, int); // quick_handler
+ typedef void (*filterHooks) (request_rec*); // insert_filter, insert_error_filter
+
+ /*
+ 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.
+ */
+ 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;
+
+ template
+ static void insertHooksForStage(
+ apr_pool_t* p,
+ hook_get_t getModules,
+ T setHook,
+ const std::vector &beginHandlers,
+ const std::vector &indexes,
+ S endHandler,
+ const std::string& stage);
+};
+#endif
diff --git a/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h b/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h
new file mode 100644
index 000000000..80179b994
--- /dev/null
+++ b/instrumentation/otel-webserver-module/include/apache/ExcludedModules.h
@@ -0,0 +1,48 @@
+/*
+* 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 APPD_EXCLUDEDMODULES_H
+#define APPD_EXCLUDEDMODULES_H
+
+#include
+#include
+#include
+#include
+#include "HookContainer.h"
+
+// hook_get_t is a pointer to a function that takes void as an argument and
+// returns a pointer to an apr_array_header_t.
+typedef apr_array_header_t *(
+*hook_get_t) (void);
+
+class ExcludedModules
+{
+public:
+ static const std::unordered_set excludedAlways; // modules that can never be instumented.
+ static std::unordered_set userSpecified; // modules requested by user
+ static const std::unordered_set excluded24; // Apache 2.4 excluded module list
+ static const std::unordered_set excluded22; // Apache 2.2 excluded module list
+
+ // Find the modules that we want to instrument for a stage.
+ // Include modules that are specified by the user and modules NOT in the exclude lists.
+ static void findHookPoints(
+ std::vector &hooks_found,
+ hook_get_t getHooks,
+ const std::string& stage);
+ static void getUserSpecifiedModules(const char* modules);
+};
+
+#endif
diff --git a/instrumentation/otel-webserver-module/include/apache/HookContainer.h b/instrumentation/otel-webserver-module/include/apache/HookContainer.h
new file mode 100644
index 000000000..839f052db
--- /dev/null
+++ b/instrumentation/otel-webserver-module/include/apache/HookContainer.h
@@ -0,0 +1,125 @@
+/*
+* 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 APPD_HOOKSCONTAINER_H
+#define APPD_HOOKSCONTAINER_H
+
+#include