diff --git a/.circleci/config.yml b/.circleci/config.yml
index 54268aa8..48f01909 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -1,13 +1,34 @@
version: 2
jobs:
- build:
+ system_testing:
machine: true
steps:
- checkout
- run:
- name: Build nginx-opentracing-ci Docker image
- command: docker build -t nginx-opentracing-ci ci
+ name: system.testing
+ command: |
+ pyenv global 3.5.2
+ python3 --version
+ pip3.5 --version
+ pip3.5 install setuptools
+ pip3.5 install docker
+ pip3.5 install docker-compose
+ sudo mkdir /test-log
+ sudo chmod a+rwx /test-log
+ export LOG_DIR=/test-log
+ ./ci/do_ci.sh system.testing
+ - store_artifacts:
+ path: /test-log
+ docker_image:
+ machine: true
+ steps:
+ - checkout
- run:
- name: Build and Test
- command: ./ci/run_ci_docker.sh './ci/do_ci.sh'
+ command: docker build -t opentracing/nginx-opentracing .
+workflows:
+ version: 2
+ build_test_and_deploy:
+ jobs:
+ - system_testing
+ - docker_image
diff --git a/docker/Dockerfile b/Dockerfile
similarity index 84%
rename from docker/Dockerfile
rename to Dockerfile
index 662ad670..7374c7d4 100644
--- a/docker/Dockerfile
+++ b/Dockerfile
@@ -2,12 +2,13 @@ ARG NGINX_LABEL=latest
FROM nginx:${NGINX_LABEL}
-ARG OPENTRACING_CPP_VERSION=v1.2.0
-ARG ZIPKIN_CPP_VERSION=v0.2.0
-ARG LIGHTSTEP_VERSION=v0.6.1
-ARG JAEGER_CPP_VERSION=v0.2.0
+ARG OPENTRACING_CPP_VERSION=v1.4.0
+ARG ZIPKIN_CPP_VERSION=v0.3.1
+ARG LIGHTSTEP_VERSION=v0.7.0
+ARG JAEGER_CPP_VERSION=v0.4.1
ARG GRPC_VERSION=v1.4.x
-ARG NGINX_OPENTRACING_VERSION=v0.2.1
+
+COPY . /src
RUN set -x \
# install nginx-opentracing package dependencies
@@ -59,16 +60,18 @@ RUN set -x \
&& cmake -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF .. \
&& make && make install \
&& cd "$tempDir" \
+ && ln -s /usr/local/lib/libzipkin_opentracing.so /usr/local/lib/libzipkin_opentracing_plugin.so \
### Build Jaeger cpp-client
&& git clone -b $JAEGER_CPP_VERSION https://github.com/jaegertracing/cpp-client.git jaeger-cpp-client \
&& cd jaeger-cpp-client \
&& mkdir .build && cd .build \
&& cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
- -DJAEGERTRACING_WITH_YAML_CPP=OFF .. \
+ -DJAEGERTRACING_WITH_YAML_CPP=ON .. \
&& make && make install \
&& export HUNTER_INSTALL_DIR=$(cat _3rdParty/Hunter/install-root-dir) \
&& cd "$tempDir" \
+ && ln -s /usr/local/lib/libjaegertracing.so /usr/local/lib/libjaegertracing_plugin.so \
### Build gRPC
&& git clone -b $GRPC_VERSION https://github.com/grpc/grpc \
&& cd grpc \
@@ -83,8 +86,8 @@ RUN set -x \
&& cmake -DBUILD_SHARED_LIBS=1 -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF .. \
&& make && make install \
&& cd "$tempDir" \
+ && ln -s /usr/local/lib/liblightstep_tracer.so /usr/local/lib/liblightstep_tracer_plugin.so \
### Build nginx-opentracing modules
- && git clone -b $NGINX_OPENTRACING_VERSION https://github.com/opentracing-contrib/nginx-opentracing.git \
&& NGINX_VERSION=`nginx -v 2>&1` && NGINX_VERSION=${NGINX_VERSION#*nginx/} \
&& echo "deb-src http://nginx.org/packages/mainline/debian/ stretch nginx" >> /etc/apt/sources.list \
&& apt-get update \
@@ -95,18 +98,14 @@ RUN set -x \
&& NGINX_MODULES_PATH=$(nginx -V 2>&1 | grep -oP "modules-path=\K[^\s]*") \
&& auto/configure \
--with-compat \
- --add-dynamic-module=${tempDir}/nginx-opentracing/opentracing \
- --add-dynamic-module=${tempDir}/nginx-opentracing/zipkin \
- --add-dynamic-module=${tempDir}/nginx-opentracing/lightstep \
- --add-dynamic-module=${tempDir}/nginx-opentracing/jaeger \
+ --add-dynamic-module=/src/opentracing \
--with-cc-opt="-I$HUNTER_INSTALL_DIR/include" \
--with-ld-opt="-L$HUNTER_INSTALL_DIR/lib" \
+ --with-debug \
&& make modules \
&& cp objs/ngx_http_opentracing_module.so $NGINX_MODULES_PATH/ \
- && cp objs/ngx_http_zipkin_module.so $NGINX_MODULES_PATH/ \
- && cp objs/ngx_http_lightstep_module.so $NGINX_MODULES_PATH/ \
- && cp objs/ngx_http_jaeger_module.so $NGINX_MODULES_PATH/ \
# if we have leftovers from building, let's purge them (including extra, unnecessary build deps)
+ && rm -rf /src \
&& rm -rf $HOME/.hunter \
&& if [ -n "$tempDir" ]; then \
apt-get purge -y --auto-remove \
diff --git a/Dockerfile-test b/Dockerfile-test
new file mode 100644
index 00000000..910bb4c8
--- /dev/null
+++ b/Dockerfile-test
@@ -0,0 +1,55 @@
+FROM ubuntu:18.04
+
+ARG OPENTRACING_CPP_VERSION=v1.4.0
+ARG NGINX_VERSION=1.13.12
+
+COPY . /src
+
+RUN set -x \
+ && apt-get update \
+ && apt-get install --no-install-recommends --no-install-suggests -y \
+ build-essential \
+ gettext \
+ cmake \
+ git \
+ gnupg2 \
+ software-properties-common \
+ curl \
+ python3 \
+ jq \
+ ca-certificates \
+ wget \
+ libpcre3 libpcre3-dev \
+ zlib1g-dev \
+ gcc-8 \
+ g++-8 \
+### Use gcc-8 (the default gcc has this problem when using with address sanitizer:
+### https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84428)
+ && update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 800 --slave /usr/bin/g++ g++ /usr/bin/g++-8 \
+### Build opentracing-cpp
+ && cd / \
+ && git clone -b $OPENTRACING_CPP_VERSION https://github.com/opentracing/opentracing-cpp.git \
+ && cd opentracing-cpp \
+ && mkdir .build && cd .build \
+ && cmake -DCMAKE_BUILD_TYPE=Debug \
+ -DCMAKE_CXX_FLAGS="-fno-omit-frame-pointer -fsanitize=address" \
+ -DCMAKE_SHARED_LINKER_FLAGS="-fno-omit-frame-pointer -fsanitize=address" \
+ -DCMAKE_EXE_LINKER_FLAGS="-fno-omit-frame-pointer -fsanitize=address" \
+ -DBUILD_TESTING=OFF .. \
+ && make && make install \
+### Build nginx
+ && cd /src \
+ && wget -O nginx-release-${NGINX_VERSION}.tar.gz https://github.com/nginx/nginx/archive/release-${NGINX_VERSION}.tar.gz \
+ && tar zxf nginx-release-${NGINX_VERSION}.tar.gz \
+ && cd /src/nginx-release-${NGINX_VERSION} \
+ # Temporarily disable leak sanitizer to get around false positives in build
+ && export ASAN_OPTIONS=detect_leaks=0 \
+ && export CFLAGS="-Wno-error" \
+ && auto/configure \
+ --with-compat \
+ --with-debug \
+ --with-cc-opt="-O1 -g -fno-omit-frame-pointer -fsanitize=address" \
+ --with-ld-opt="-g -fno-omit-frame-pointer -fsanitize=address" \
+ --add-dynamic-module=/src/opentracing \
+ && make && make install
+CMD ["/usr/local/nginx/sbin/nginx", "-g", "daemon off;"]
diff --git a/README.md b/README.md
index aae789c5..7c83f7c3 100644
--- a/README.md
+++ b/README.md
@@ -23,42 +23,68 @@ Building
```
$ tar zxvf nginx-1.9.x.tar.gz
$ cd nginx-1.9.x
-$ ./configure --add-dynamic-module=/absolute/path/to/nginx-opentracing/opentracing \
- # To enable tracing with Jaeger
- --add-dynamic-module=/absolute/path/to/nginx-opentracing/jaeger \
- # To enable tracing with Zipkin
- --add-dynamic-module=/absolute/path/to/nginx-opentracing/zipkin \
- # To enable tracing with LightStep
- --add-dynamic-module=/absolute/path/to/nginx-opentracing/lightstep
+$ ./configure --add-dynamic-module=/absolute/path/to/nginx-opentracing/opentracing
$ make && sudo make install
```
+You will also need to install a C++ tracer for either [Jaeger](https://github.com/jaegertracing/jaeger-client-cpp), [LightStep](
+https://github.com/lightstep/lightstep-tracer-cpp), or [Zipkin](https://github.com/rnburn/zipkin-cpp-opentracing). For linux x86-64, portable binary plugins are available:
+```
+# Jaeger
+wget https://github.com/jaegertracing/jaeger-client-cpp/releases/download/v0.4.0/libjaegertracing_plugin.linux_amd64.so -O /usr/local/lib/libjaegertracing_plugin.so
+
+# LightStep
+wget -O - https://github.com/lightstep/lightstep-tracer-cpp/releases/download/v0.7.0/linux-amd64-liblightstep_tracer_plugin.so.gz | gunzip -c > /usr/local/lib/liblightstep_tracer_plugin.so
+
+# Zipkin
+wget -O - https://github.com/rnburn/zipkin-cpp-opentracing/releases/download/v0.3.1/linux-amd64-libzipkin_opentracing_plugin.so.gz gunzip -c > /usr/local/lib/libzipkin_opentracing_plugin.so
+
+```
Getting Started
---------------
+First, write a configuration for the tracer used. Below's an example of what
+a Jaeger configuration might look like:
+
+/etc/jaeger-nginx-config.json
+```
+{
+ "service_name": "nginx",
+ "sampler": {
+ "type": "const",
+ "param": 1
+ },
+ "reporter": {
+ "localAgentHostPort": "jaeger:6831"
+ },
+ "headers": {
+ "jaegerDebugHeader": "jaeger-debug-id",
+ "jaegerBaggageHeader": "jaeger-baggage",
+ "traceBaggageHeaderPrefix": "uberctx-",
+ },
+ "baggage_restrictions": {
+ "denyBaggageOnInitializationFailure": false,
+ "hostPort": ""
+ }
+}
+```
+
+See the vendor documentation for details on what options are available.
+
+You can then set up NGINX for distributed tracing by adding the following to
+nginx.conf:
```
# Load the OpenTracing dynamic module.
load_module modules/ngx_http_opentracing_module.so;
-# Load a vendor OpenTracing dynamic module.
-# For example,
-# load_module modules/ngx_http_jaeger_module.so;
-# or
-# load_module modules/ngx_http_zipkin_module.so;
-# or
-# load_module modules/ngx_http_lightstep_module.so;
-
http {
- # Configure your vendor's tracer.
- # For example,
- # jaeger_service_name my-nginx-server;
- # ...
- # or
- # zipkin_collector_host localhost;
- # ...
- # or
- # lightstep_access_token ACCESSTOKEN;
- # ....
+ # Load a vendor tracer
+ opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so /etc/jaeger-nginx-config.json;
+
+ # or
+ # opentracing_load_tracer /usr/local/lib/liblightstep_tracer_plugin.so /path/to/config;
+ # or
+ # opentracing_load_tracer /usr/local/lib/libzipkin_opentracing_plugin.so /path/to/config;
# Enable tracing for all requests.
opentracing on;
@@ -66,20 +92,25 @@ http {
# Optionally, set additional tags.
opentracing_tag http_user_agent $http_user_agent;
- location ~ \.php$ {
+ upstream backend {
+ server app-service:9001;
+ }
+
+ location ~ {
# The operation name used for spans defaults to the name of the location
# block, but you can use this directive to customize it.
opentracing_operation_name $uri;
- fastcgi_pass 127.0.0.1:1025;
+ # Propagate the active span context upstream, so that the trace can be
+ # continued by the backend.
+ # See http://opentracing.io/documentation/pages/api/cross-process-tracing.html
+ opentracing_propagate_context;
+
+ proxy_pass http://backend;
}
}
```
See [Tutorial](doc/Tutorial.md) for a more complete example,
-[Reference](doc/Directives.md) for a list of available OpenTracing-related
-directives, and [Jaeger](jaeger/doc/Directives.md),
-[Zipkin](zipkin/doc/Directives.md), and
-[LightStep](lightstep/doc/Directives.md) for a list of vendor tracing
+[Reference](doc/Reference.md) for a list of available OpenTracing-related
directives.
-
diff --git a/ci/Dockerfile b/ci/Dockerfile
deleted file mode 100644
index a8b78331..00000000
--- a/ci/Dockerfile
+++ /dev/null
@@ -1,35 +0,0 @@
-ARG NGINX_LABEL=latest
-
-FROM nginx:${NGINX_LABEL}
-
-ARG OPENTRACING_CPP_VERSION=v1.3.0
-
-RUN set -x \
- && apt-get update \
- && apt-get install --no-install-recommends --no-install-suggests -y \
- build-essential \
- gettext \
- cmake \
- git \
- curl \
- python3 \
- jq \
- ca-certificates \
- wget \
- && mkdir /src \
-### Build opentracing-cpp
- && cd /src \
- && git clone -b $OPENTRACING_CPP_VERSION https://github.com/opentracing/opentracing-cpp.git \
- && cd opentracing-cpp \
- && mkdir .build && cd .build \
- && cmake -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_TESTING=OFF .. \
- && make && make install \
-### Get nginx sources
- && cd /src \
- && NGINX_VERSION=`nginx -v 2>&1` && NGINX_VERSION=${NGINX_VERSION#*nginx/} \
- && echo "deb-src http://nginx.org/packages/mainline/debian/ stretch nginx" >> /etc/apt/sources.list \
- && apt-get update \
- && apt-get build-dep -y nginx=${NGINX_VERSION} \
- && wget -O nginx-release-${NGINX_VERSION}.tar.gz https://github.com/nginx/nginx/archive/release-${NGINX_VERSION}.tar.gz \
- && tar zxf nginx-release-${NGINX_VERSION}.tar.gz \
diff --git a/ci/do_ci.sh b/ci/do_ci.sh
index 59d76627..cdb7ad33 100755
--- a/ci/do_ci.sh
+++ b/ci/do_ci.sh
@@ -2,22 +2,12 @@
set -e
-NGINX_VERSION=`nginx -v 2>&1` && NGINX_VERSION=${NGINX_VERSION#*nginx/}
-NGINX_MODULES_PATH=$(nginx -V 2>&1 | grep -oP "modules-path=\K[^\s]*")
-cd /src/nginx-release-${NGINX_VERSION}
-auto/configure \
- --with-compat \
- --add-dynamic-module=/src/nginx-opentracing/opentracing
-make modules
-cp objs/ngx_http_opentracing_module.so $NGINX_MODULES_PATH/
-cd /src/nginx-opentracing
-export MOCKTRACER_LIBRARY=/usr/local/lib/libopentracing_mocktracer.so
-export NGINX_OPENTRACING_MODULE="$NGINX_MODULES_PATH/ngx_http_opentracing_module.so"
-export NGINX_OPENTRACING_TEST_DIR=/nginx-opentracing-test
-mkdir $NGINX_OPENTRACING_TEST_DIR
-chmod a+rwx $NGINX_OPENTRACING_TEST_DIR
-cd test
-for i in *;
-do
- "$i/run.sh"
-done
+[ -z "${SRC_DIR}" ] && export SRC_DIR="`pwd`"
+
+if [[ "$1" == "system.testing" ]]; then
+ docker build -t nginx-opentracing-test/nginx -f Dockerfile-test .
+ cd test
+ docker build -t nginx-opentracing-test/backend -f Dockerfile-backend .
+ python3 nginx_opentracing_test.py
+ exit 0
+fi
diff --git a/ci/run_ci_docker.sh b/ci/run_ci_docker.sh
deleted file mode 100755
index fa92f3dd..00000000
--- a/ci/run_ci_docker.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-set -e
-
-BUILD_IMAGE=nginx-opentracing-ci
-docker image inspect "$BUILD_IMAGE" &> /dev/null || {
- docker build -t "$BUILD_IMAGE" ci
-}
-
-if [ -n "$1" ]; then
- docker run -v "$PWD":/src/nginx-opentracing -w /src/nginx-opentracing -it "$BUILD_IMAGE" /bin/bash -lc "$1"
-else
- docker run -v "$PWD":/src/nginx-opentracing -w /src/nginx-opentracing --privileged -it "$BUILD_IMAGE" /bin/bash -l
-fi
diff --git a/doc/Directives.md b/doc/Reference.md
similarity index 78%
rename from doc/Directives.md
rename to doc/Reference.md
index ce07d64b..7f6cc5cf 100644
--- a/doc/Directives.md
+++ b/doc/Reference.md
@@ -1,3 +1,6 @@
+Directives
+----------
+
### `opentracing`
- **syntax** `opentracing on|off`
@@ -13,6 +16,14 @@ Enables or disables OpenTracing for NGINX requests.
Dynamicaly loads in a tracer implementing the OpenTracing dynamic loading interface.
+### `opentracing_propagate_context`
+
+- **syntax** `opentracing_propagate_context`
+- **context**: `location`
+
+Propagates the active span context for upstream requests. (See
+[cross-process-tracing](http://opentracing.io/documentation/pages/api/cross-process-tracing.html))
+
### `opentracing_trace_locations`
- **syntax** `opentracing_trace_locations on|off`
@@ -54,3 +65,12 @@ Enables or disables using OpenTracing spans from incoming requests as parent for
Sets a [tag](https://github.com/opentracing/specification/blob/master/specification.md#set-a-span-tag)
with the given `key` and `value` for an NGINX span.
+
+Variables
+---------
+
+### `opentracing_context_`*name*
+
+Expands to the a value of the active span context; the last part of the variable
+name is the span context's header converted to lower case with dashes replaced by
+underscores.
diff --git a/doc/Tutorial.md b/doc/Tutorial.md
index 8d0864c5..cbce53bf 100644
--- a/doc/Tutorial.md
+++ b/doc/Tutorial.md
@@ -42,11 +42,17 @@ http {
# The backend returns a table of thumbnail profile pictures for every
# animal in the zoo.
proxy_pass http://backend;
+
+ # Propagate the context of the active span.
+ #
+ # See http://opentracing.io/documentation/pages/api/cross-process-tracing.html
+ opentracing_propagate_context;
}
# Display the profile for a specific animal in the zoo.
location = /animal {
proxy_pass http://backend;
+ opentracing_propagate_context;
}
# Admit a new animal.
@@ -57,6 +63,8 @@ http {
# thumbnail sized profile picture, and transform the full-sized profile
# picture, if necessary, to be in the jpeg format.
proxy_pass http://backend;
+
+ opentracing_propagate_context;
# Redirect to the spash page if the animal was successfully admitted.
proxy_intercept_errors on;
@@ -83,7 +91,7 @@ We can tell NGINX to trace every request by adding these two lines to
`nginx.conf`:
```
http {
- lightstep_access_token `your-access-token`;
+ opentracing_load_tracer /path/to/tracer/plugin /path/to/tracer/config;
opentracing on;
...
```
@@ -95,13 +103,10 @@ By default NGINX creates spans for both the request and the location blocks. It
uses the name of the first location as the name for the top-level span. We can
change this behavior by using the directives `opentracing_operation_name` and
`opentracing_location_operation_name` to set the names of the request and
-location block spans respectively. We can also use the directive
-`lightstep_component_name` to set a group name for related traces. For
+location block spans respectively. For
example, by adding
```
http {
-...
- lightstep_component_name zoo;
...
location = /upload/animal {
opentracing_location_operation_name upload;
diff --git a/example/browser/Dockerfile b/example/browser/Dockerfile
deleted file mode 100644
index 8e719236..00000000
--- a/example/browser/Dockerfile
+++ /dev/null
@@ -1,26 +0,0 @@
-FROM rnburn/nginx-opentracing
-
-WORKDIR /app
-ADD . /app
-RUN set -x \
-## install nodejs and node dependencies
- && apt-get update \
- && apt-get install --no-install-recommends --no-install-suggests -y \
- python \
- curl \
- gnupg2 \
- && mkdir /node-latest-install \
- && cd /node-latest-install \
- && curl -sL https://deb.nodesource.com/setup_7.x -o nodesource_setup.sh \
- && bash nodesource_setup.sh \
- && apt-get install --no-install-recommends --no-install-suggests -y \
- nodejs \
- && cd /app \
- && npm install . \
- && npm run browserify \
- && mv index.html /usr/share/nginx/html \
- && mv bundle.js /usr/share/nginx/html
-
-
-EXPOSE 80
-CMD ["/app/start.sh"]
diff --git a/example/browser/README.md b/example/browser/README.md
deleted file mode 100644
index 2c346ec3..00000000
--- a/example/browser/README.md
+++ /dev/null
@@ -1,9 +0,0 @@
-A port of the [zipkin-js-example/web example](https://github.com/openzipkin/zipkin-js-example/tree/master/web) to use nginx.
-It features Nginx as a reverse-proxy in front node services and client-side tracing in the browser.
-Use these commands to run:
-```bash
-docker build -t nginx-example-browser .
-docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin
-docker run -d -p 8080:80 --link zipkin:zipkin nginx-example-browser
-```
-Visit http://localhost:8080 in your browser and http://localhost:9411 to view the traces in Zipkin.
diff --git a/example/browser/index.html b/example/browser/index.html
deleted file mode 100644
index 928f7f7d..00000000
--- a/example/browser/index.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- Calling frontend service...
-
-
-
diff --git a/example/browser/nginx.conf b/example/browser/nginx.conf
deleted file mode 100644
index 9659bbfe..00000000
--- a/example/browser/nginx.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-load_module modules/ngx_http_opentracing_module.so;
-load_module modules/ngx_http_zipkin_module.so;
-
-events {}
-
-http {
- zipkin_collector_host $ZIPKIN_PORT_9411_TCP_ADDR;
- zipkin_collector_port $ZIPKIN_PORT_9411_TCP_PORT;
- zipkin_service_name nginx;
- opentracing on;
-
- upstream frontend {
- server localhost:8081;
- }
-
- upstream backend {
- server localhost:9000;
- }
-
- server {
- listen 80;
- server_name localhost;
-
- location / {
- root /usr/share/nginx/html;
- index index.html index.htm;
- }
-
- location /time {
- proxy_pass http://frontend;
- }
-
- location /api {
- proxy_pass http://backend;
- }
- }
-}
diff --git a/example/browser/node/backend.js b/example/browser/node/backend.js
deleted file mode 100644
index 15034656..00000000
--- a/example/browser/node/backend.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* eslint-disable import/newline-after-import */
-// initialize tracer
-const express = require('express');
-const CLSContext = require('zipkin-context-cls');
-const {Tracer} = require('zipkin');
-const {recorder} = require('./recorder');
-
-const ctxImpl = new CLSContext('zipkin');
-const localServiceName = 'backend';
-const tracer = new Tracer({ctxImpl, recorder, localServiceName});
-
-const app = express();
-
-// instrument the server
-const zipkinMiddleware = require('zipkin-instrumentation-express').expressMiddleware;
-app.use(zipkinMiddleware({tracer}));
-
-app.get('/api', (req, res) => res.send(new Date().toString()));
-
-app.listen(9000, () => {
- console.log('Backend listening on port 9000!');
-});
diff --git a/example/browser/node/browser.js b/example/browser/node/browser.js
deleted file mode 100644
index bd5763df..00000000
--- a/example/browser/node/browser.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/* eslint-env browser */
-/* eslint-disable import/newline-after-import */
-// use higher-precision time than milliseconds
-process.hrtime = require('browser-process-hrtime');
-
-// setup tracer
-const {
- BatchRecorder,
- jsonEncoder: {JSON_V2}
-} = require('zipkin');
-const {HttpLogger} = require('zipkin-transport-http');
-
-const recorder = new BatchRecorder({
- logger: new HttpLogger({
- endpoint: 'http://localhost:9411/api/v2/spans',
- jsonEncoder: JSON_V2
- })
-});
-
-const {Tracer, ExplicitContext} = require('zipkin');
-
-const ctxImpl = new ExplicitContext();
-const localServiceName = 'browser';
-const tracer = new Tracer({ctxImpl, recorder, localServiceName});
-
-// instrument fetch
-const wrapFetch = require('zipkin-instrumentation-fetch');
-const zipkinFetch = wrapFetch(fetch, {tracer});
-
-const logEl = document.getElementById('log');
-const log = text => logEl.innerHTML = `${logEl.innerHTML}\n${text}`;
-
-// wrap fetch call so that it is traced
-zipkinFetch('http://localhost:8080/time')
- .then(response => (response.text()))
- .then(text => log(text))
- .catch(err => log(`Failed:\n${err.stack}`));
diff --git a/example/browser/node/frontend.js b/example/browser/node/frontend.js
deleted file mode 100644
index 75a2a389..00000000
--- a/example/browser/node/frontend.js
+++ /dev/null
@@ -1,43 +0,0 @@
-/* eslint-disable import/newline-after-import */
-// initialize tracer
-const rest = require('rest');
-const express = require('express');
-const CLSContext = require('zipkin-context-cls');
-const {Tracer} = require('zipkin');
-const {recorder} = require('./recorder');
-
-const ctxImpl = new CLSContext('zipkin');
-const localServiceName = 'frontend';
-const tracer = new Tracer({ctxImpl, recorder, localServiceName});
-
-const app = express();
-
-// instrument the server
-const zipkinMiddleware = require('zipkin-instrumentation-express').expressMiddleware;
-app.use(zipkinMiddleware({tracer}));
-
-// instrument the client
-const {restInterceptor} = require('zipkin-instrumentation-cujojs-rest');
-const zipkinRest = rest.wrap(restInterceptor, {tracer});
-
-// Allow cross-origin, traced requests. See http://enable-cors.org/server_expressjs.html
-app.use((req, res, next) => {
- res.header('Access-Control-Allow-Origin', '*');
- res.header('Access-Control-Allow-Headers', [
- 'Origin', 'Accept', 'X-Requested-With', 'X-B3-TraceId',
- 'X-B3-ParentSpanId', 'X-B3-SpanId', 'X-B3-Sampled'
- ].join(', '));
- next();
-});
-
-app.get('/time', (req, res) => {
- tracer.local('pay-me', () =>
- zipkinRest('http://localhost/api')
- .then(response => res.send(response.entity))
- .catch(err => console.error('Error', err.stack))
- );
-});
-
-app.listen(8081, () => {
- console.log('Frontend listening on port 8081!');
-});
diff --git a/example/browser/node/recorder.js b/example/browser/node/recorder.js
deleted file mode 100644
index 5db304ed..00000000
--- a/example/browser/node/recorder.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/* eslint-env browser */
-const {
- BatchRecorder,
- jsonEncoder: {JSON_V2}
-} = require('zipkin');
-const {HttpLogger} = require('zipkin-transport-http');
-
-// Send spans to Zipkin asynchronously over HTTP
-if (!process.env.ZIPKIN_HOST || !process.env.ZIPKIN_PORT) {
- console.log("ZIPKIN_HOST and ZIPKIN_PORT must be set!");
- process.exit(1);
-}
-const zipkinBaseUrl = 'http://' + process.env.ZIPKIN_HOST + ':' +
- process.env.ZIPKIN_PORT
-const recorder = new BatchRecorder({
- logger: new HttpLogger({
- endpoint: `${zipkinBaseUrl}/api/v2/spans`,
- jsonEncoder: JSON_V2
- })
-});
-
-module.exports.recorder = recorder;
diff --git a/example/browser/node/servers.js b/example/browser/node/servers.js
deleted file mode 100644
index 9c1afe62..00000000
--- a/example/browser/node/servers.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const path = require('path');
-const childProc = require('child_process');
-
-childProc.fork(path.join(__dirname, 'frontend.js'));
-childProc.fork(path.join(__dirname, 'backend.js'));
diff --git a/example/browser/package.json b/example/browser/package.json
deleted file mode 100644
index b5d73811..00000000
--- a/example/browser/package.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "zipkin-nginx-js-example",
- "version": "0.0.1",
- "description": "Example project that shows how to use zipkin with javascript",
- "repository": "https://github.com/openzipkin/zipkin-js",
- "scripts": {
- "lint": "eslint .",
- "start": "node node/servers.js",
- "browserify": "browserify node/browser.js -o bundle.js"
- },
- "dependencies": {
- "browser-process-hrtime": "^0.1.2",
- "express": "^4.14.0",
- "rest": "^1.3.2",
- "zipkin": "^0.11.1",
- "zipkin-context-cls": "^0.11.0",
- "zipkin-instrumentation-cujojs-rest": "^0.11.1",
- "zipkin-instrumentation-express": "^0.11.1",
- "zipkin-instrumentation-fetch": "^0.11.1",
- "zipkin-transport-http": "^0.11.1"
- },
- "devDependencies": {
- "browserify": "^14.1.0",
- "eslint": "^3.4.0",
- "eslint-config-airbnb": "^14.1.0",
- "eslint-plugin-import": "^2.2.0",
- "eslint-plugin-jsx-a11y": "^4.0.0",
- "eslint-plugin-react": "^6.2.0"
- }
-}
diff --git a/example/browser/start.sh b/example/browser/start.sh
deleted file mode 100755
index a9eec50e..00000000
--- a/example/browser/start.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-
-export ZIPKIN_HOST=$ZIPKIN_PORT_9411_TCP_ADDR
-export ZIPKIN_PORT=$ZIPKIN_PORT_9411_TCP_PORT
-envsubst '\$ZIPKIN_PORT_9411_TCP_ADDR \$ZIPKIN_PORT_9411_TCP_PORT' < /app/nginx.conf > /etc/nginx/nginx.conf
-
-npm start &
-nginx
-while /bin/true; do
- sleep 50
-done
diff --git a/example/hotrod/Dockerfile b/example/hotrod/Dockerfile
deleted file mode 100644
index aa7ebe78..00000000
--- a/example/hotrod/Dockerfile
+++ /dev/null
@@ -1,52 +0,0 @@
-FROM rnburn/nginx-opentracing
-
-WORKDIR /app
-ADD . /app
-RUN set -x \
-# new directory for storing sources and .deb files
- && tempDir="$(mktemp -d)" \
- && chmod 777 "$tempDir" \
- \
-# save list of currently-installed packages so build dependencies can be cleanly removed later
- && savedAptMark="$(apt-mark showmanual)" \
- \
-# set up go
- && apt-get update \
- && apt-get install --no-install-recommends --no-install-suggests -y \
- git \
- ca-certificates \
- software-properties-common \
- wget \
- curl \
- && wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz \
- && tar -xvf go1.8.3.linux-amd64.tar.gz \
- && mv go $tempDir \
- && export GOROOT=$tempDir/go \
- && export GOPATH=$tempDir/gopath \
- && mkdir -p $GOPATH/bin \
- && export PATH=$GOPATH/bin:$GOROOT/bin:$PATH \
-# install glide
- && curl https://glide.sh/get | sh \
-# build the hotrod demo
- && mkdir -p $GOPATH/src/github.com/rnburn/ \
- && mv /app/hotrod $GOPATH/src/github.com/rnburn/hotrod-docker \
- && cd $GOPATH/src/github.com/rnburn/hotrod-docker \
- && glide install \
- && go build -o hotrod \
- && mv hotrod /app/hotrod \
- && mkdir -p /app/services/frontend/web_assets \
- && cp services/frontend/web_assets/index.html /app/services/frontend/web_assets/index.html \
-# reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies
-# (which is done after we install the built packages so we don't have to redownload any overlapping dependencies)
- && apt-mark showmanual | xargs apt-mark auto > /dev/null \
- && { [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; } \
- \
-# purge leftovers from building them (including extra, unnecessary build deps)
- && apt-get purge -y --auto-remove \
- && rm -rf "$tempDir"
-
-EXPOSE 8080
-
-STOPSIGNAL SIGTERM
-
-CMD ["/app/start.sh"]
diff --git a/example/hotrod/README.md b/example/hotrod/README.md
deleted file mode 100644
index 2e108f61..00000000
--- a/example/hotrod/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-An OpenTracing example demonstrating usage of the nginx-opentracing docker
-image with jaeger. It builds on Jaeger's HotROD example (see blog post
-[Take OpenTracing for a HotROD ride](https://medium.com/opentracing/take-opentracing-for-a-hotrod-ride-f6e3141f7941)),
-but inserts nginx as a load balancer for the HotROD services.
-
-Use these commands to run:
-```bash
-docker build -t nginx-example-hotrod .
-docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp \
- -p5778:5778 -p16686:16686 -p14268:14268 -p9411:9411 --name jaeger jaegertracing/all-in-one:latest
-docker run -d -p 8080:80 --link jaeger:jaeger nginx-example-hotrod
-```
-Visit http://localhost:8080 to interact with the demo and http://localhost:16686
-to view the traces in Jaeger.
diff --git a/example/hotrod/hotrod/cmd/all.go b/example/hotrod/hotrod/cmd/all.go
deleted file mode 100644
index 5016fd27..00000000
--- a/example/hotrod/hotrod/cmd/all.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package cmd
-
-import "github.com/spf13/cobra"
-
-// allCmd represents the all command
-var allCmd = &cobra.Command{
- Use: "all",
- Short: "Starts all services",
- Long: `Starts all services.`,
- Run: func(cmd *cobra.Command, args []string) {
- logger.Info("Starting all services")
- go customerCmd.RunE(customerCmd, args)
- go driverCmd.RunE(driverCmd, args)
- go routeCmd.RunE(routeCmd, args)
- frontendCmd.RunE(frontendCmd, args)
- },
-}
-
-func init() {
- RootCmd.AddCommand(allCmd)
-}
diff --git a/example/hotrod/hotrod/cmd/customer.go b/example/hotrod/hotrod/cmd/customer.go
deleted file mode 100644
index 7ddf6d4f..00000000
--- a/example/hotrod/hotrod/cmd/customer.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package cmd
-
-import (
- "net"
- "strconv"
-
- "github.com/spf13/cobra"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/customer"
-)
-
-// customerCmd represents the customer command
-var customerCmd = &cobra.Command{
- Use: "customer",
- Short: "Starts Customer service",
- Long: `Starts Customer service.`,
- RunE: func(cmd *cobra.Command, args []string) error {
- logger := log.NewFactory(logger.With(zap.String("service", "customer")))
- server := customer.NewServer(
- net.JoinHostPort(customerOptions.serverInterface, strconv.Itoa(customerOptions.serverPort)),
- tracing.Init("customer", metricsFactory.Namespace("customer", nil), logger),
- metricsFactory,
- logger,
- )
- return server.Run()
- },
-}
-
-var (
- customerOptions struct {
- serverInterface string
- serverPort int
- }
-)
-
-func init() {
- RootCmd.AddCommand(customerCmd)
-
- customerCmd.Flags().StringVarP(&customerOptions.serverInterface, "bind", "", "127.0.0.1", "interface to which the Customer server will bind")
- customerCmd.Flags().IntVarP(&customerOptions.serverPort, "port", "p", 8081, "port on which the Customer server will listen")
-}
diff --git a/example/hotrod/hotrod/cmd/driver.go b/example/hotrod/hotrod/cmd/driver.go
deleted file mode 100644
index 0c401095..00000000
--- a/example/hotrod/hotrod/cmd/driver.go
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package cmd
-
-import (
- "net"
- "strconv"
-
- "github.com/spf13/cobra"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/driver"
-)
-
-// driverCmd represents the driver command
-var driverCmd = &cobra.Command{
- Use: "driver",
- Short: "Starts Driver service",
- Long: `Starts Driver service.`,
- RunE: func(cmd *cobra.Command, args []string) error {
- logger := log.NewFactory(logger.With(zap.String("service", "driver")))
- server := driver.NewServer(
- net.JoinHostPort(driverOptions.serverInterface, strconv.Itoa(driverOptions.serverPort)),
- tracing.Init("driver", metricsFactory.Namespace("driver", nil), logger),
- metricsFactory,
- logger,
- )
- return server.Run()
- },
-}
-
-var (
- driverOptions struct {
- serverInterface string
- serverPort int
- }
-)
-
-func init() {
- RootCmd.AddCommand(driverCmd)
-
- driverCmd.Flags().StringVarP(&driverOptions.serverInterface, "bind", "", "127.0.0.1", "interface to which the driver server will bind")
- driverCmd.Flags().IntVarP(&driverOptions.serverPort, "port", "p", 8082, "port on which the driver server will listen")
-}
diff --git a/example/hotrod/hotrod/cmd/frontend.go b/example/hotrod/hotrod/cmd/frontend.go
deleted file mode 100644
index 6841edec..00000000
--- a/example/hotrod/hotrod/cmd/frontend.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package cmd
-
-import (
- "net"
- "strconv"
-
- "github.com/spf13/cobra"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/frontend"
-)
-
-// frontendCmd represents the frontend command
-var frontendCmd = &cobra.Command{
- Use: "frontend",
- Short: "Starts Frontend service",
- Long: `Starts Frontend service.`,
- RunE: func(cmd *cobra.Command, args []string) error {
- logger := log.NewFactory(logger.With(zap.String("service", "frontend")))
- server := frontend.NewServer(
- net.JoinHostPort(frontendOptions.serverInterface, strconv.Itoa(frontendOptions.serverPort)),
- tracing.Init("frontend", metricsFactory.Namespace("frontend", nil), logger),
- logger,
- )
- return server.Run()
- },
-}
-
-var (
- frontendOptions struct {
- serverInterface string
- serverPort int
- }
-)
-
-func init() {
- RootCmd.AddCommand(frontendCmd)
-
- frontendCmd.Flags().StringVarP(&frontendOptions.serverInterface, "bind", "", "", "interface to which the frontend server will bind")
- frontendCmd.Flags().IntVarP(&frontendOptions.serverPort, "port", "p", 8080, "port on which the frontend server will listen")
-}
diff --git a/example/hotrod/hotrod/cmd/root.go b/example/hotrod/hotrod/cmd/root.go
deleted file mode 100644
index 0b16e7c9..00000000
--- a/example/hotrod/hotrod/cmd/root.go
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package cmd
-
-import (
- "fmt"
- "math/rand"
- "os"
- "time"
-
- "github.com/spf13/cobra"
- "github.com/spf13/viper"
- "github.com/uber/jaeger-lib/metrics"
- "github.com/uber/jaeger-lib/metrics/go-kit"
- "github.com/uber/jaeger-lib/metrics/go-kit/expvar"
- "go.uber.org/zap"
-)
-
-var (
- cfgFile string
- logger *zap.Logger
- metricsFactory metrics.Factory
-)
-
-// RootCmd represents the base command when called without any subcommands
-var RootCmd = &cobra.Command{
- Use: "jaeger-demo",
- Short: "HotR.O.D. - A tracing demo application",
- Long: `HotR.O.D. - A tracing demo application.`,
-}
-
-// Execute adds all child commands to the root command sets flags appropriately.
-// This is called by main.main(). It only needs to happen once to the rootCmd.
-func Execute() {
- if err := RootCmd.Execute(); err != nil {
- logger.Fatal("We bowled a googly", zap.Error(err))
- os.Exit(-1)
- }
-}
-
-func init() {
- cobra.OnInitialize(initConfig)
- logger, _ = zap.NewDevelopment()
- metricsFactory = xkit.Wrap("", expvar.NewFactory(10)) // 10 buckets for histograms
-}
-
-// initConfig reads in config file and ENV variables if set.
-func initConfig() {
- if cfgFile != "" { // enable ability to specify config file via flag
- viper.SetConfigFile(cfgFile)
- }
-
- viper.SetConfigName(".jaeger-demo") // name of config file (without extension)
- viper.AddConfigPath("$HOME") // adding home directory as first search path
- viper.AutomaticEnv() // read in environment variables that match
-
- // If a config file is found, read it in.
- if err := viper.ReadInConfig(); err == nil {
- fmt.Println("Using config file:", viper.ConfigFileUsed())
- }
-
- rand.Seed(int64(time.Now().Nanosecond()))
-}
diff --git a/example/hotrod/hotrod/cmd/route.go b/example/hotrod/hotrod/cmd/route.go
deleted file mode 100644
index c4d5a51c..00000000
--- a/example/hotrod/hotrod/cmd/route.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package cmd
-
-import (
- "net"
- "strconv"
-
- "github.com/spf13/cobra"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/route"
-)
-
-// routeCmd represents the route command
-var routeCmd = &cobra.Command{
- Use: "route",
- Short: "Starts Route service",
- Long: `Starts Route service.`,
- RunE: func(cmd *cobra.Command, args []string) error {
- logger := log.NewFactory(logger.With(zap.String("service", "route")))
- server := route.NewServer(
- net.JoinHostPort(routeOptions.serverInterface, strconv.Itoa(routeOptions.serverPort)),
- tracing.Init("route", metricsFactory.Namespace("route", nil), logger),
- logger,
- )
- return server.Run()
- },
-}
-
-var (
- routeOptions struct {
- serverInterface string
- serverPort int
- }
-)
-
-func init() {
- RootCmd.AddCommand(routeCmd)
-
- routeCmd.Flags().StringVarP(&routeOptions.serverInterface, "bind", "", "127.0.0.1", "interface to which the Route server will bind")
- routeCmd.Flags().IntVarP(&routeOptions.serverPort, "port", "p", 8083, "port on which the Route server will listen")
-}
diff --git a/example/hotrod/hotrod/glide.lock b/example/hotrod/hotrod/glide.lock
deleted file mode 100644
index b829ce60..00000000
--- a/example/hotrod/hotrod/glide.lock
+++ /dev/null
@@ -1,126 +0,0 @@
-hash: 5afb055333607d4ef6fdd4023a87611599776f05195058dd4bf7a8381dad0bec
-updated: 2017-10-20T13:24:51.186338625-07:00
-imports:
-- name: github.com/apache/thrift
- version: b2a4d4ae21c789b689dd162deb819665567f481c
- subpackages:
- - lib/go/thrift
-- name: github.com/codahale/hdrhistogram
- version: 3a0bb77429bd3a61596f5e8a3172445844342120
-- name: github.com/fsnotify/fsnotify
- version: 4da3e2cfbabc9f751898f250b49f2439785783a1
-- name: github.com/go-kit/kit
- version: a9ca6725cbbea455e61c6bc8a1ed28e81eb3493b
- subpackages:
- - metrics
- - metrics/expvar
- - metrics/generic
- - metrics/internal/lv
-- name: github.com/hashicorp/hcl
- version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8
- subpackages:
- - hcl/ast
- - hcl/parser
- - hcl/scanner
- - hcl/strconv
- - hcl/token
- - json/parser
- - json/scanner
- - json/token
-- name: github.com/inconshreveable/mousetrap
- version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
-- name: github.com/magiconair/properties
- version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a
-- name: github.com/mitchellh/mapstructure
- version: 06020f85339e21b2478f756a78e295255ffa4d6a
-- name: github.com/opentracing-contrib/go-stdlib
- version: 48e4d763b2fbcd10e666e6a1742acdf8cc2286ef
- subpackages:
- - nethttp
-- name: github.com/opentracing/opentracing-go
- version: 1949ddbfd147afd4d964a9f00b24eb291e0e7c38
- subpackages:
- - ext
- - log
-- name: github.com/pelletier/go-toml
- version: 2009e44b6f182e34d8ce081ac2767622937ea3d4
-- name: github.com/spf13/afero
- version: e67d870304c4bca21331b02f414f970df13aa694
- subpackages:
- - mem
-- name: github.com/spf13/cast
- version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
-- name: github.com/spf13/cobra
- version: 7b2c5ac9fc04fc5efafb60700713d4fa609b777b
-- name: github.com/spf13/jwalterweatherman
- version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
-- name: github.com/spf13/pflag
- version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
-- name: github.com/spf13/viper
- version: 25b30aa063fc18e48662b86996252eabdcf2f0c7
-- name: github.com/uber-go/atomic
- version: 4e336646b2ef9fc6e47be8e21594178f98e5ebcf
-- name: github.com/uber/jaeger-client-go
- version: 3e3870040def0ebdaf65a003863fa64f5cb26139
- subpackages:
- - config
- - internal/spanlog
- - log
- - rpcmetrics
- - thrift-gen/agent
- - thrift-gen/jaeger
- - thrift-gen/sampling
- - thrift-gen/zipkincore
- - utils
-- name: github.com/uber/jaeger-lib
- version: 3b2a9ad2a045881ab7a0f81d465be54c8292ee4f
- subpackages:
- - metrics
- - metrics/go-kit
- - metrics/go-kit/expvar
-- name: github.com/uber/tchannel-go
- version: a7ad9ecb640b5f10a0395b38d6319175172b3ab2
- subpackages:
- - internal/argreader
- - relay
- - thrift
- - thrift/gen-go/meta
- - tnet
- - tos
- - trand
- - typed
-- name: github.com/VividCortex/gohistogram
- version: 51564d9861991fb0ad0f531c99ef602d0f9866e6
-- name: go.uber.org/atomic
- version: 4e336646b2ef9fc6e47be8e21594178f98e5ebcf
-- name: go.uber.org/multierr
- version: 3c4937480c32f4c13a875a1829af76c98ca3d40a
-- name: go.uber.org/zap
- version: 35aad584952c3e7020db7b839f6b102de6271f89
- subpackages:
- - buffer
- - internal/bufferpool
- - internal/color
- - internal/exit
- - zapcore
-- name: golang.org/x/net
- version: aabf50738bcdd9b207582cbe796b59ed65d56680
- subpackages:
- - bpf
- - context
- - internal/iana
- - internal/socket
- - ipv4
- - ipv6
-- name: golang.org/x/sys
- version: 8dbc5d05d6edcc104950cc299a1ce6641235bc86
- subpackages:
- - unix
-- name: golang.org/x/text
- version: c01e4764d870b77f8abe5096ee19ad20d80e8075
- subpackages:
- - transform
- - unicode/norm
-- name: gopkg.in/yaml.v2
- version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
-testImports: []
diff --git a/example/hotrod/hotrod/glide.yaml b/example/hotrod/hotrod/glide.yaml
deleted file mode 100644
index 519d0f67..00000000
--- a/example/hotrod/hotrod/glide.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-package: github.com/rnburn/hotrod-docker
-import:
-- package: github.com/apache/thrift
- version: ~0.10.0
- subpackages:
- - lib/go/thrift
-- package: github.com/opentracing-contrib/go-stdlib
- subpackages:
- - nethttp
-- package: github.com/opentracing/opentracing-go
- version: ~1.0.2
- subpackages:
- - ext
- - log
-- package: github.com/spf13/cobra
-- package: github.com/spf13/viper
- version: ~1.0.0
-- package: github.com/uber/jaeger-client-go
- version: ~2.9.0
- subpackages:
- - config
- - rpcmetrics
-- package: github.com/uber/jaeger-lib
- version: ~1.1.0
- subpackages:
- - metrics
- - metrics/go-kit
- - metrics/go-kit/expvar
-- package: github.com/uber/tchannel-go
- version: ~1.7.0
- subpackages:
- - thrift
-- package: go.uber.org/zap
- version: ~1.7.1
- subpackages:
- - zapcore
diff --git a/example/hotrod/hotrod/main.go b/example/hotrod/hotrod/main.go
deleted file mode 100644
index b352952c..00000000
--- a/example/hotrod/hotrod/main.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-
-package main
-
-import (
- "runtime"
-
- "github.com/rnburn/hotrod-docker/cmd"
-)
-
-func main() {
- runtime.GOMAXPROCS(runtime.NumCPU())
- cmd.Execute()
-}
diff --git a/example/hotrod/hotrod/pkg/delay/delay.go b/example/hotrod/hotrod/pkg/delay/delay.go
deleted file mode 100644
index d644eed5..00000000
--- a/example/hotrod/hotrod/pkg/delay/delay.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package delay
-
-import (
- "math"
- "math/rand"
- "time"
-)
-
-// Sleep generates a normally distributed random delay with given mean and stdDev
-// and blocks for that duration.
-func Sleep(mean time.Duration, stdDev time.Duration) {
- fMean := float64(mean)
- fStdDev := float64(stdDev)
- delay := time.Duration(math.Max(1, rand.NormFloat64()*fStdDev+fMean))
- time.Sleep(delay)
-}
diff --git a/example/hotrod/hotrod/pkg/httperr/httperr.go b/example/hotrod/hotrod/pkg/httperr/httperr.go
deleted file mode 100644
index 9351eea7..00000000
--- a/example/hotrod/hotrod/pkg/httperr/httperr.go
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package httperr
-
-import "net/http"
-
-// HandleError checks if the error is not nil, writes it to the output
-// with the specified status code, and returns true. If error is nil it returns false.
-func HandleError(w http.ResponseWriter, err error, statusCode int) bool {
- if err == nil {
- return false
- }
- http.Error(w, string(err.Error()), statusCode)
- return true
-}
diff --git a/example/hotrod/hotrod/pkg/httpexpvar/handler.go b/example/hotrod/hotrod/pkg/httpexpvar/handler.go
deleted file mode 100644
index 13046eeb..00000000
--- a/example/hotrod/hotrod/pkg/httpexpvar/handler.go
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package httpexpvar
-
-import (
- "expvar"
- "fmt"
- "net/http"
-)
-
-// Handler is a copy of expvar.expvarHandler private method.
-// TODO this won't be needed in Go 1.8
-func Handler(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json; charset=utf-8")
- fmt.Fprintf(w, "{\n")
- first := true
- expvar.Do(func(kv expvar.KeyValue) {
- if !first {
- fmt.Fprintf(w, ",\n")
- }
- first = false
- fmt.Fprintf(w, "%q: %s", kv.Key, kv.Value)
- })
- fmt.Fprintf(w, "\n}\n")
-}
diff --git a/example/hotrod/hotrod/pkg/log/factory.go b/example/hotrod/hotrod/pkg/log/factory.go
deleted file mode 100644
index 88cc4bb2..00000000
--- a/example/hotrod/hotrod/pkg/log/factory.go
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package log
-
-import (
- "context"
-
- "github.com/opentracing/opentracing-go"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-// Factory is the default logging wrapper that can create
-// logger instances either for a given Context or context-less.
-type Factory struct {
- logger *zap.Logger
-}
-
-// NewFactory creates a new Factory.
-func NewFactory(logger *zap.Logger) Factory {
- return Factory{logger: logger}
-}
-
-// Bg creates a context-unaware logger.
-func (b Factory) Bg() Logger {
- return logger{logger: b.logger}
-}
-
-// For returns a context-aware Logger. If the context
-// contains an OpenTracing span, all logging calls are also
-// echo-ed into the span.
-func (b Factory) For(ctx context.Context) Logger {
- if span := opentracing.SpanFromContext(ctx); span != nil {
- // TODO for Jaeger span extract trace/span IDs as fields
- return spanLogger{span: span, logger: b.logger}
- }
- return b.Bg()
-}
-
-// With creates a child logger, and optionally adds some context fields to that logger.
-func (b Factory) With(fields ...zapcore.Field) Factory {
- return Factory{logger: b.logger.With(fields...)}
-}
diff --git a/example/hotrod/hotrod/pkg/log/logger.go b/example/hotrod/hotrod/pkg/log/logger.go
deleted file mode 100644
index a2e1b594..00000000
--- a/example/hotrod/hotrod/pkg/log/logger.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package log
-
-import (
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-// Logger is a simplified abstraction of the zap.Logger
-type Logger interface {
- Info(msg string, fields ...zapcore.Field)
- Error(msg string, fields ...zapcore.Field)
- Fatal(msg string, fields ...zapcore.Field)
- With(fields ...zapcore.Field) Logger
-}
-
-// logger delegates all calls to the underlying zap.Logger
-type logger struct {
- logger *zap.Logger
-}
-
-// Info logs an info msg with fields
-func (l logger) Info(msg string, fields ...zapcore.Field) {
- l.logger.Info(msg, fields...)
-}
-
-// Error logs an error msg with fields
-func (l logger) Error(msg string, fields ...zapcore.Field) {
- l.logger.Error(msg, fields...)
-}
-
-// Fatal logs a fatal error msg with fields
-func (l logger) Fatal(msg string, fields ...zapcore.Field) {
- l.logger.Fatal(msg, fields...)
-}
-
-// With creates a child logger, and optionally adds some context fields to that logger.
-func (l logger) With(fields ...zapcore.Field) Logger {
- return logger{logger: l.logger.With(fields...)}
-}
diff --git a/example/hotrod/hotrod/pkg/log/spanlogger.go b/example/hotrod/hotrod/pkg/log/spanlogger.go
deleted file mode 100644
index 2d0580ac..00000000
--- a/example/hotrod/hotrod/pkg/log/spanlogger.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package log
-
-import (
- "time"
-
- "github.com/opentracing/opentracing-go"
- tag "github.com/opentracing/opentracing-go/ext"
- "github.com/opentracing/opentracing-go/log"
- "go.uber.org/zap"
- "go.uber.org/zap/zapcore"
-)
-
-type spanLogger struct {
- logger *zap.Logger
- span opentracing.Span
-}
-
-func (sl spanLogger) Info(msg string, fields ...zapcore.Field) {
- sl.logToSpan("info", msg, fields...)
- sl.logger.Info(msg, fields...)
-}
-
-func (sl spanLogger) Error(msg string, fields ...zapcore.Field) {
- sl.logToSpan("error", msg, fields...)
- sl.logger.Error(msg, fields...)
-}
-
-func (sl spanLogger) Fatal(msg string, fields ...zapcore.Field) {
- sl.logToSpan("fatal", msg, fields...)
- tag.Error.Set(sl.span, true)
- sl.logger.Fatal(msg, fields...)
-}
-
-// With creates a child logger, and optionally adds some context fields to that logger.
-func (sl spanLogger) With(fields ...zapcore.Field) Logger {
- return spanLogger{logger: sl.logger.With(fields...), span: sl.span}
-}
-
-func (sl spanLogger) logToSpan(level string, msg string, fields ...zapcore.Field) {
- // TODO rather than always converting the fields, we could wrap them into a lazy logger
- fa := fieldAdapter(make([]log.Field, 0, 2+len(fields)))
- fa = append(fa, log.String("event", msg))
- fa = append(fa, log.String("level", level))
- for _, field := range fields {
- field.AddTo(&fa)
- }
- sl.span.LogFields(fa...)
-}
-
-type fieldAdapter []log.Field
-
-func (fa *fieldAdapter) AddBool(key string, value bool) {
- *fa = append(*fa, log.Bool(key, value))
-}
-
-func (fa *fieldAdapter) AddFloat64(key string, value float64) {
- *fa = append(*fa, log.Float64(key, value))
-}
-
-func (fa *fieldAdapter) AddFloat32(key string, value float32) {
- *fa = append(*fa, log.Float64(key, float64(value)))
-}
-
-func (fa *fieldAdapter) AddInt(key string, value int) {
- *fa = append(*fa, log.Int(key, value))
-}
-
-func (fa *fieldAdapter) AddInt64(key string, value int64) {
- *fa = append(*fa, log.Int64(key, value))
-}
-
-func (fa *fieldAdapter) AddInt32(key string, value int32) {
- *fa = append(*fa, log.Int64(key, int64(value)))
-}
-
-func (fa *fieldAdapter) AddInt16(key string, value int16) {
- *fa = append(*fa, log.Int64(key, int64(value)))
-}
-
-func (fa *fieldAdapter) AddInt8(key string, value int8) {
- *fa = append(*fa, log.Int64(key, int64(value)))
-}
-
-func (fa *fieldAdapter) AddUint(key string, value uint) {
- *fa = append(*fa, log.Uint64(key, uint64(value)))
-}
-
-func (fa *fieldAdapter) AddUint64(key string, value uint64) {
- *fa = append(*fa, log.Uint64(key, value))
-}
-
-func (fa *fieldAdapter) AddUint32(key string, value uint32) {
- *fa = append(*fa, log.Uint64(key, uint64(value)))
-}
-
-func (fa *fieldAdapter) AddUint16(key string, value uint16) {
- *fa = append(*fa, log.Uint64(key, uint64(value)))
-}
-
-func (fa *fieldAdapter) AddUint8(key string, value uint8) {
- *fa = append(*fa, log.Uint64(key, uint64(value)))
-}
-
-func (fa *fieldAdapter) AddUintptr(key string, value uintptr) {}
-func (fa *fieldAdapter) AddArray(key string, marshaler zapcore.ArrayMarshaler) error { return nil }
-func (fa *fieldAdapter) AddComplex128(key string, value complex128) {}
-func (fa *fieldAdapter) AddComplex64(key string, value complex64) {}
-func (fa *fieldAdapter) AddObject(key string, value zapcore.ObjectMarshaler) error { return nil }
-func (fa *fieldAdapter) AddReflected(key string, value interface{}) error { return nil }
-func (fa *fieldAdapter) OpenNamespace(key string) {}
-
-func (fa *fieldAdapter) AddDuration(key string, value time.Duration) {
- // TODO inefficient
- *fa = append(*fa, log.String(key, value.String()))
-}
-
-func (fa *fieldAdapter) AddTime(key string, value time.Time) {
- // TODO inefficient
- *fa = append(*fa, log.String(key, value.String()))
-}
-
-func (fa *fieldAdapter) AddBinary(key string, value []byte) {
- *fa = append(*fa, log.Object(key, value))
-}
-
-func (fa *fieldAdapter) AddByteString(key string, value []byte) {
- *fa = append(*fa, log.Object(key, value))
-}
-
-func (fa *fieldAdapter) AddString(key, value string) {
- if key != "" && value != "" {
- *fa = append(*fa, log.String(key, value))
- }
-}
diff --git a/example/hotrod/hotrod/pkg/pool/pool.go b/example/hotrod/hotrod/pkg/pool/pool.go
deleted file mode 100644
index 172064e7..00000000
--- a/example/hotrod/hotrod/pkg/pool/pool.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package pool
-
-// Pool is a simple worker pool
-type Pool struct {
- jobs chan func()
- stop chan struct{}
-}
-
-// New creates a new pool with the given number of workers
-func New(workers int) *Pool {
- jobs := make(chan func())
- stop := make(chan struct{})
- for i := 0; i < workers; i++ {
- go func() {
- for {
- select {
- case job := <-jobs:
- job()
- case <-stop:
- return
- }
- }
- }()
- }
- return &Pool{
- jobs: jobs,
- stop: stop,
- }
-}
-
-// Execute enqueues the job to be executed by one of the workers in the pool
-func (p *Pool) Execute(job func()) {
- p.jobs <- job
-}
-
-// Stop halts all the workers
-func (p *Pool) Stop() {
- p.stop <- struct{}{}
-}
diff --git a/example/hotrod/hotrod/pkg/tracing/http.go b/example/hotrod/hotrod/pkg/tracing/http.go
deleted file mode 100644
index 6707602b..00000000
--- a/example/hotrod/hotrod/pkg/tracing/http.go
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package tracing
-
-import (
- "context"
- "encoding/json"
- "errors"
- "io/ioutil"
- "net/http"
-
- "github.com/opentracing-contrib/go-stdlib/nethttp"
- "github.com/opentracing/opentracing-go"
-)
-
-// HTTPClient wraps an http.Client with tracing instrumentation.
-type HTTPClient struct {
- Tracer opentracing.Tracer
- Client *http.Client
-}
-
-// GetJSON executes HTTP GET against specified url and tried to parse
-// the response into out object.
-func (c *HTTPClient) GetJSON(ctx context.Context, endpoint string, url string, out interface{}) error {
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- return err
- }
- req = req.WithContext(ctx)
- req, ht := nethttp.TraceRequest(c.Tracer, req, nethttp.OperationName("HTTP GET: "+endpoint))
- defer ht.Finish()
-
- res, err := c.Client.Do(req)
- if err != nil {
- return err
- }
-
- defer res.Body.Close()
-
- if res.StatusCode >= 400 {
- body, err := ioutil.ReadAll(res.Body)
- if err != nil {
- return err
- }
- return errors.New(string(body))
- }
- decoder := json.NewDecoder(res.Body)
- return decoder.Decode(out)
-}
diff --git a/example/hotrod/hotrod/pkg/tracing/init.go b/example/hotrod/hotrod/pkg/tracing/init.go
deleted file mode 100644
index 482b320e..00000000
--- a/example/hotrod/hotrod/pkg/tracing/init.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package tracing
-
-import (
- "fmt"
- "time"
- "os"
-
- "github.com/opentracing/opentracing-go"
- "github.com/uber/jaeger-client-go/config"
- "github.com/uber/jaeger-client-go/rpcmetrics"
- "github.com/uber/jaeger-lib/metrics"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
-)
-
-// Init creates a new instance of Jaeger tracer.
-func Init(serviceName string, metricsFactory metrics.Factory, logger log.Factory) opentracing.Tracer {
- localAgentHost := os.Getenv("JAEGER_AGENT_HOST")
- if localAgentHost == "" {
- localAgentHost = "localhost"
- }
- localAgentPort := os.Getenv("JAEGER_AGENT_PORT")
- if localAgentPort == "" {
- localAgentPort = "6831"
- }
- cfg := config.Configuration{
- Sampler: &config.SamplerConfig{
- Type: "const",
- Param: 1,
- },
- Reporter: &config.ReporterConfig{
- LogSpans: false,
- BufferFlushInterval: 1 * time.Second,
- LocalAgentHostPort: fmt.Sprintf("%s:%s", localAgentHost, localAgentPort),
- },
- }
- tracer, _, err := cfg.New(
- serviceName,
- config.Logger(jaegerLoggerAdapter{logger.Bg()}),
- config.Observer(rpcmetrics.NewObserver(metricsFactory, rpcmetrics.DefaultNameNormalizer)),
- )
- if err != nil {
- logger.Bg().Fatal("cannot initialize Jaeger Tracer", zap.Error(err))
- }
- return tracer
-}
-
-type jaegerLoggerAdapter struct {
- logger log.Logger
-}
-
-func (l jaegerLoggerAdapter) Error(msg string) {
- l.logger.Error(msg)
-}
-
-func (l jaegerLoggerAdapter) Infof(msg string, args ...interface{}) {
- l.logger.Info(fmt.Sprintf(msg, args...))
-}
diff --git a/example/hotrod/hotrod/pkg/tracing/mutex.go b/example/hotrod/hotrod/pkg/tracing/mutex.go
deleted file mode 100644
index b7da3fdc..00000000
--- a/example/hotrod/hotrod/pkg/tracing/mutex.go
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package tracing
-
-import (
- "context"
- "fmt"
- "sync"
-
- "github.com/opentracing/opentracing-go"
- "github.com/opentracing/opentracing-go/log"
-)
-
-// Mutex is just like the standard sync.Mutex, except that it is aware of the Context
-// and logs some diagnostic information into the current span.
-type Mutex struct {
- SessionBaggageKey string
-
- realLock sync.Mutex
- holder string
-
- waiters []string
- waitersLock sync.Mutex
-}
-
-// Lock acquires an exclusive lock.
-func (sm *Mutex) Lock(ctx context.Context) {
- var session string
- activeSpan := opentracing.SpanFromContext(ctx)
- if activeSpan != nil {
- session = activeSpan.BaggageItem(sm.SessionBaggageKey)
- activeSpan.SetTag(sm.SessionBaggageKey, session)
- }
-
- sm.waitersLock.Lock()
- if waiting := len(sm.waiters); waiting > 0 && activeSpan != nil {
- activeSpan.LogFields(
- log.String("event", fmt.Sprintf("Waiting for lock behind %d transactions", waiting)),
- log.String("blockers", fmt.Sprintf("%v", sm.waiters))) // avoid deferred slice.String()
- fmt.Printf("%s Waiting for lock behind %d transactions: %v\n", session, waiting, sm.waiters)
- }
- sm.waiters = append(sm.waiters, session)
- sm.waitersLock.Unlock()
-
- sm.realLock.Lock()
- sm.holder = session
-
- sm.waitersLock.Lock()
- behindLen := len(sm.waiters) - 1
- sm.waitersLock.Unlock()
-
- if activeSpan != nil {
- activeSpan.LogEvent(
- fmt.Sprintf("Acquired lock with %d transactions waiting behind", behindLen))
- }
-}
-
-// Unlock releases the lock.
-func (sm *Mutex) Unlock() {
- sm.waitersLock.Lock()
- for i, v := range sm.waiters {
- if v == sm.holder {
- sm.waiters = append(sm.waiters[0:i], sm.waiters[i+1:]...)
- break
- }
- }
- sm.waitersLock.Unlock()
-
- sm.realLock.Unlock()
-}
diff --git a/example/hotrod/hotrod/pkg/tracing/mux.go b/example/hotrod/hotrod/pkg/tracing/mux.go
deleted file mode 100644
index ac309f0d..00000000
--- a/example/hotrod/hotrod/pkg/tracing/mux.go
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package tracing
-
-import (
- "net/http"
-
- "github.com/opentracing-contrib/go-stdlib/nethttp"
- "github.com/opentracing/opentracing-go"
-)
-
-// NewServeMux creates a new TracedServeMux.
-func NewServeMux(tracer opentracing.Tracer) *TracedServeMux {
- return &TracedServeMux{
- mux: http.NewServeMux(),
- tracer: tracer,
- }
-}
-
-// TracedServeMux is a wrapper around http.ServeMux that instruments handlers for tracing.
-type TracedServeMux struct {
- mux *http.ServeMux
- tracer opentracing.Tracer
-}
-
-// Handle implements http.ServeMux#Handle
-func (tm *TracedServeMux) Handle(pattern string, handler http.Handler) {
- middleware := nethttp.Middleware(
- tm.tracer,
- handler,
- nethttp.OperationNameFunc(func(r *http.Request) string {
- return "HTTP " + r.Method + " " + pattern
- }))
- tm.mux.Handle(pattern, middleware)
-}
-
-// ServeHTTP implements http.ServeMux#ServeHTTP
-func (tm *TracedServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- tm.mux.ServeHTTP(w, r)
-}
diff --git a/example/hotrod/hotrod/services/config/config.go b/example/hotrod/hotrod/services/config/config.go
deleted file mode 100644
index 28cccd74..00000000
--- a/example/hotrod/hotrod/services/config/config.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package config
-
-import (
- "time"
-)
-
-var (
- // 'frontend' service
-
- // WorkerPoolSize is the size of goroutine pool used to query for routes
- WorkerPoolSize = 3
-
- // 'customer' service
-
- // MySQLGetDelay is how long retrieving a customer record takes.
- // Using large value mostly because I cannot click the button fast enough to cause a queue.
- MySQLGetDelay = 300 * time.Millisecond
-
- // MySQLGetDelayStdDev is standard deviation
- MySQLGetDelayStdDev = MySQLGetDelay / 10
-
- // RouteWorkerPoolSize is the size of the worker pool used to query `route` service
- RouteWorkerPoolSize = 3
-
- // 'driver' service
-
- // RedisFindDelay is how long finding closest drivers takes
- RedisFindDelay = 20 * time.Millisecond
-
- // RedisFindDelayStdDev is standard deviation
- RedisFindDelayStdDev = RedisFindDelay / 4
-
- // RedisGetDelay is how long retrieving a driver record takes
- RedisGetDelay = 10 * time.Millisecond
-
- // RedisGetDelayStdDev is standard deviation
- RedisGetDelayStdDev = RedisGetDelay / 4
-
- // 'route' service
-
- // RouteCalcDelay is how long a route calculation takes
- RouteCalcDelay = 50 * time.Millisecond
-
- // RouteCalcDelayStdDev is standard deviation
- RouteCalcDelayStdDev = RouteCalcDelay / 4
-)
diff --git a/example/hotrod/hotrod/services/customer/client.go b/example/hotrod/hotrod/services/customer/client.go
deleted file mode 100644
index 95316f33..00000000
--- a/example/hotrod/hotrod/services/customer/client.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package customer
-
-import (
- "context"
- "fmt"
- "net/http"
-
- "github.com/opentracing-contrib/go-stdlib/nethttp"
- "github.com/opentracing/opentracing-go"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
-)
-
-// Client is a remote client that implements customer.Interface
-type Client struct {
- tracer opentracing.Tracer
- logger log.Factory
- client *tracing.HTTPClient
-}
-
-// NewClient creates a new customer.Client
-func NewClient(tracer opentracing.Tracer, logger log.Factory) *Client {
- return &Client{
- tracer: tracer,
- logger: logger,
- client: &tracing.HTTPClient{
- Client: &http.Client{Transport: &nethttp.Transport{}},
- Tracer: tracer,
- },
- }
-}
-
-// Get implements customer.Interface#Get as an RPC
-func (c *Client) Get(ctx context.Context, customerID string) (*Customer, error) {
- c.logger.For(ctx).Info("Getting customer", zap.String("customer_id", customerID))
-
- url := fmt.Sprintf("http://127.0.0.1/customer?customer=%s", customerID)
- var customer Customer
- if err := c.client.GetJSON(ctx, "/customer", url, &customer); err != nil {
- return nil, err
- }
- return &customer, nil
-}
diff --git a/example/hotrod/hotrod/services/customer/database.go b/example/hotrod/hotrod/services/customer/database.go
deleted file mode 100644
index 41078bbf..00000000
--- a/example/hotrod/hotrod/services/customer/database.go
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package customer
-
-import (
- "context"
- "errors"
-
- "go.uber.org/zap"
-
- "github.com/opentracing/opentracing-go"
- tags "github.com/opentracing/opentracing-go/ext"
-
- "github.com/rnburn/hotrod-docker/pkg/delay"
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/config"
-)
-
-// database simulates Customer repository implemented on top of an SQL database
-type database struct {
- tracer opentracing.Tracer
- logger log.Factory
- customers map[string]*Customer
- lock *tracing.Mutex
-}
-
-func newDatabase(tracer opentracing.Tracer, logger log.Factory) *database {
- return &database{
- tracer: tracer,
- logger: logger,
- lock: &tracing.Mutex{
- SessionBaggageKey: "request",
- },
- customers: map[string]*Customer{
- "123": {
- ID: "123",
- Name: "Rachel's Floral Designs",
- Location: "115,277",
- },
- "567": {
- ID: "567",
- Name: "Amazing Coffee Roasters",
- Location: "211,653",
- },
- "392": {
- ID: "392",
- Name: "Trom Chocolatier",
- Location: "577,322",
- },
- "731": {
- ID: "731",
- Name: "Japanese Deserts",
- Location: "728,326",
- },
- },
- }
-}
-
-func (d *database) Get(ctx context.Context, customerID string) (*Customer, error) {
- d.logger.For(ctx).Info("Loading customer", zap.String("customer_id", customerID))
-
- // simulate opentracing instrumentation of an SQL query
- if span := opentracing.SpanFromContext(ctx); span != nil {
- span := d.tracer.StartSpan("SQL SELECT", opentracing.ChildOf(span.Context()))
- tags.SpanKindRPCClient.Set(span)
- tags.PeerService.Set(span, "mysql")
- span.SetTag("sql.query", "SELECT * FROM customer WHERE customer_id="+customerID)
- defer span.Finish()
- ctx = opentracing.ContextWithSpan(ctx, span)
- }
-
- // simulate misconfigured connection pool that only gives one connection at a time
- d.lock.Lock(ctx)
- defer d.lock.Unlock()
-
- // simulate RPC delay
- delay.Sleep(config.MySQLGetDelay, config.MySQLGetDelayStdDev)
-
- if customer, ok := d.customers[customerID]; ok {
- return customer, nil
- }
- return nil, errors.New("invalid customer ID")
-}
diff --git a/example/hotrod/hotrod/services/customer/interface.go b/example/hotrod/hotrod/services/customer/interface.go
deleted file mode 100644
index 976adc9a..00000000
--- a/example/hotrod/hotrod/services/customer/interface.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package customer
-
-import "context"
-
-// Customer contains data about a customer.
-type Customer struct {
- ID string
- Name string
- Location string
-}
-
-// Interface exposed by the Customer service.
-type Interface interface {
- Get(ctx context.Context, customerID string) (*Customer, error)
-}
diff --git a/example/hotrod/hotrod/services/customer/server.go b/example/hotrod/hotrod/services/customer/server.go
deleted file mode 100644
index c3f44a2a..00000000
--- a/example/hotrod/hotrod/services/customer/server.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package customer
-
-import (
- "encoding/json"
- "net/http"
-
- "github.com/opentracing/opentracing-go"
- "github.com/uber/jaeger-lib/metrics"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/httperr"
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
-)
-
-// Server implements Customer service
-type Server struct {
- hostPort string
- tracer opentracing.Tracer
- logger log.Factory
- database *database
-}
-
-// NewServer creates a new customer.Server
-func NewServer(hostPort string, tracer opentracing.Tracer, metricsFactory metrics.Factory, logger log.Factory) *Server {
- return &Server{
- hostPort: hostPort,
- tracer: tracer,
- logger: logger,
- database: newDatabase(
- tracing.Init("mysql", metricsFactory.Namespace("mysql", nil), logger),
- logger.With(zap.String("component", "mysql")),
- ),
- }
-}
-
-// Run starts the Customer server
-func (s *Server) Run() error {
- mux := s.createServeMux()
- s.logger.Bg().Info("Starting", zap.String("address", "http://"+s.hostPort))
- return http.ListenAndServe(s.hostPort, mux)
-}
-
-func (s *Server) createServeMux() http.Handler {
- mux := tracing.NewServeMux(s.tracer)
- mux.Handle("/customer", http.HandlerFunc(s.customer))
- return mux
-}
-
-func (s *Server) customer(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- s.logger.For(ctx).Info("HTTP request received", zap.String("method", r.Method), zap.Stringer("url", r.URL))
- if err := r.ParseForm(); httperr.HandleError(w, err, http.StatusBadRequest) {
- s.logger.For(ctx).Error("bad request", zap.Error(err))
- return
- }
-
- customerID := r.Form.Get("customer")
- if customerID == "" {
- http.Error(w, "Missing required 'customer' parameter", http.StatusBadRequest)
- return
- }
-
- response, err := s.database.Get(ctx, customerID)
- if httperr.HandleError(w, err, http.StatusInternalServerError) {
- s.logger.For(ctx).Error("request failed", zap.Error(err))
- return
- }
-
- data, err := json.Marshal(response)
- if httperr.HandleError(w, err, http.StatusInternalServerError) {
- s.logger.For(ctx).Error("cannot marshal response", zap.Error(err))
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- w.Write(data)
-}
diff --git a/example/hotrod/hotrod/services/driver/client.go b/example/hotrod/hotrod/services/driver/client.go
deleted file mode 100644
index 9a8d3f75..00000000
--- a/example/hotrod/hotrod/services/driver/client.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package driver
-
-import (
- "context"
- "time"
-
- "github.com/opentracing/opentracing-go"
- "github.com/uber/tchannel-go"
- "github.com/uber/tchannel-go/thrift"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/services/driver/thrift-gen/driver"
-)
-
-// Client is a remote client that implements driver.Interface
-type Client struct {
- tracer opentracing.Tracer
- logger log.Factory
- ch *tchannel.Channel
- client driver.TChanDriver
-}
-
-// NewClient creates a new driver.Client
-func NewClient(tracer opentracing.Tracer, logger log.Factory) *Client {
- channelOpts := &tchannel.ChannelOptions{
- //Logger: logger,
- //StatsReporter: statsReporter,
- Tracer: tracer,
- }
- ch, err := tchannel.NewChannel("driver-client", channelOpts)
- if err != nil {
- logger.Bg().Fatal("Cannot create TChannel", zap.Error(err))
- }
- clientOpts := &thrift.ClientOptions{
- HostPort: "127.0.0.1:8082",
- }
- thriftClient := thrift.NewClient(ch, "driver", clientOpts)
- client := driver.NewTChanDriverClient(thriftClient)
-
- return &Client{
- tracer: tracer,
- logger: logger,
- ch: ch,
- client: client,
- }
-}
-
-// FindNearest implements driver.Interface#FindNearest as an RPC
-func (c *Client) FindNearest(ctx context.Context, location string) ([]Driver, error) {
- c.logger.For(ctx).Info("Finding nearest drivers", zap.String("location", location))
- ctx, cancel := context.WithTimeout(ctx, 1*time.Second)
- defer cancel()
- results, err := c.client.FindNearest(thrift.Wrap(ctx), location)
- if err != nil {
- return nil, err
- }
- return fromThrift(results), nil
-}
-
-func fromThrift(results []*driver.DriverLocation) []Driver {
- retMe := make([]Driver, len(results))
- for i, result := range results {
- retMe[i] = Driver{
- DriverID: result.DriverID,
- Location: result.Location,
- }
- }
- return retMe
-}
diff --git a/example/hotrod/hotrod/services/driver/driver.thrift b/example/hotrod/hotrod/services/driver/driver.thrift
deleted file mode 100644
index 0b6778f3..00000000
--- a/example/hotrod/hotrod/services/driver/driver.thrift
+++ /dev/null
@@ -1,9 +0,0 @@
-
-struct DriverLocation {
- 1: required string driver_id
- 2: required string location
-}
-
-service Driver {
- list findNearest(1: string location)
-}
\ No newline at end of file
diff --git a/example/hotrod/hotrod/services/driver/interface.go b/example/hotrod/hotrod/services/driver/interface.go
deleted file mode 100644
index d20941f4..00000000
--- a/example/hotrod/hotrod/services/driver/interface.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package driver
-
-import "context"
-
-// Driver describes a driver and the currentl car location.
-type Driver struct {
- DriverID string
- Location string
-}
-
-// Interface exposed by the Driver service.
-type Interface interface {
- FindNearest(ctx context.Context, location string) ([]Driver, error)
-}
diff --git a/example/hotrod/hotrod/services/driver/redis.go b/example/hotrod/hotrod/services/driver/redis.go
deleted file mode 100644
index 3e1edf6f..00000000
--- a/example/hotrod/hotrod/services/driver/redis.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package driver
-
-import (
- "context"
- "errors"
- "fmt"
- "math/rand"
- "sync"
-
- "github.com/opentracing/opentracing-go"
- "github.com/opentracing/opentracing-go/ext"
- "github.com/uber/jaeger-lib/metrics"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/delay"
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/config"
-)
-
-// Redis is a simulator of remote Redis cache
-type Redis struct {
- tracer opentracing.Tracer // simulate redis as a separate process
- logger log.Factory
- errorSimulator
-}
-
-func newRedis(metricsFactory metrics.Factory, logger log.Factory) *Redis {
- return &Redis{
- tracer: tracing.Init("redis", metricsFactory.Namespace("redis", nil), logger),
- logger: logger,
- }
-}
-
-// FindDriverIDs finds IDs of drivers who are near the location.
-func (r *Redis) FindDriverIDs(ctx context.Context, location string) []string {
- if span := opentracing.SpanFromContext(ctx); span != nil {
- span := r.tracer.StartSpan("FindDriverIDs", opentracing.ChildOf(span.Context()))
- span.SetTag("param.location", location)
- ext.SpanKindRPCClient.Set(span)
- defer span.Finish()
- ctx = opentracing.ContextWithSpan(ctx, span)
- }
- // simulate RPC delay
- delay.Sleep(config.RedisFindDelay, config.RedisFindDelayStdDev)
-
- drivers := make([]string, 10)
- for i := range drivers {
- drivers[i] = fmt.Sprintf("T7%05dC", rand.Int()%100000)
- }
- return drivers
-}
-
-// GetDriver returns driver and the current car location
-func (r *Redis) GetDriver(ctx context.Context, driverID string) (Driver, error) {
- if span := opentracing.SpanFromContext(ctx); span != nil {
- span := r.tracer.StartSpan("GetDriver", opentracing.ChildOf(span.Context()))
- span.SetTag("param.driverID", driverID)
- ext.SpanKindRPCClient.Set(span)
- defer span.Finish()
- ctx = opentracing.ContextWithSpan(ctx, span)
- }
- // simulate RPC delay
- delay.Sleep(config.RedisGetDelay, config.RedisGetDelayStdDev)
- if err := r.checkError(); err != nil {
- if span := opentracing.SpanFromContext(ctx); span != nil {
- ext.Error.Set(span, true)
- }
- r.logger.For(ctx).Error("redis timeout", zap.String("driver_id", driverID), zap.Error(err))
- return Driver{}, err
- }
-
- return Driver{
- DriverID: driverID,
- Location: fmt.Sprintf("%d,%d", rand.Int()%1000, rand.Int()%1000),
- }, nil
-}
-
-var errTimeout = errors.New("redis timeout")
-
-type errorSimulator struct {
- sync.Mutex
- countTillError int
-}
-
-func (es *errorSimulator) checkError() error {
- es.Lock()
- es.countTillError--
- if es.countTillError > 0 {
- es.Unlock()
- return nil
- }
- es.countTillError = 5
- es.Unlock()
- delay.Sleep(2*config.RedisGetDelay, 0) // add more delay for "timeout"
- return errTimeout
-}
diff --git a/example/hotrod/hotrod/services/driver/server.go b/example/hotrod/hotrod/services/driver/server.go
deleted file mode 100644
index a514cac2..00000000
--- a/example/hotrod/hotrod/services/driver/server.go
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package driver
-
-import (
- "github.com/opentracing/opentracing-go"
- "github.com/uber/jaeger-lib/metrics"
- "github.com/uber/tchannel-go"
- "github.com/uber/tchannel-go/thrift"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/services/driver/thrift-gen/driver"
-)
-
-// Server implements jaeger-demo-frontend service
-type Server struct {
- hostPort string
- tracer opentracing.Tracer
- logger log.Factory
- ch *tchannel.Channel
- server *thrift.Server
- redis *Redis
-}
-
-// NewServer creates a new driver.Server
-func NewServer(hostPort string, tracer opentracing.Tracer, metricsFactory metrics.Factory, logger log.Factory) *Server {
- channelOpts := &tchannel.ChannelOptions{
- Tracer: tracer,
- }
- ch, err := tchannel.NewChannel("driver", channelOpts)
- if err != nil {
- logger.Bg().Fatal("Cannot create TChannel", zap.Error(err))
- }
- server := thrift.NewServer(ch)
-
- return &Server{
- hostPort: hostPort,
- tracer: tracer,
- logger: logger,
- ch: ch,
- server: server,
- redis: newRedis(metricsFactory, logger),
- }
-}
-
-// Run starts the Driver server
-func (s *Server) Run() error {
-
- s.server.Register(driver.NewTChanDriverServer(s))
-
- if err := s.ch.ListenAndServe(s.hostPort); err != nil {
- s.logger.Bg().Fatal("Unable to start tchannel server", zap.Error(err))
- }
-
- peerInfo := s.ch.PeerInfo()
- s.logger.Bg().Info("TChannel listening", zap.String("hostPort", peerInfo.HostPort))
-
- // Run must block, but TChannel's ListenAndServe runs in the background, so block indefinitely
- select {}
-}
-
-// FindNearest implements Thrift interface TChanDriver
-func (s *Server) FindNearest(ctx thrift.Context, location string) ([]*driver.DriverLocation, error) {
- s.logger.For(ctx).Info("Searching for nearby drivers", zap.String("location", location))
- driverIDs := s.redis.FindDriverIDs(ctx, location)
-
- retMe := make([]*driver.DriverLocation, len(driverIDs))
- for i, driverID := range driverIDs {
- var drv Driver
- var err error
- for i := 0; i < 3; i++ {
- drv, err = s.redis.GetDriver(ctx, driverID)
- if err == nil {
- break
- }
- s.logger.For(ctx).Error("Retrying GetDriver after error", zap.Int("retry_no", i+1), zap.Error(err))
- }
- if err != nil {
- s.logger.For(ctx).Error("Failed to get driver after 3 attempts", zap.Error(err))
- return nil, err
- }
- retMe[i] = &driver.DriverLocation{
- DriverID: drv.DriverID,
- Location: drv.Location,
- }
- }
- s.logger.For(ctx).Info("Search successful", zap.Int("num_drivers", len(retMe)))
- return retMe, nil
-}
diff --git a/example/hotrod/hotrod/services/driver/thrift-gen/driver/constants.go b/example/hotrod/hotrod/services/driver/thrift-gen/driver/constants.go
deleted file mode 100644
index 09d65670..00000000
--- a/example/hotrod/hotrod/services/driver/thrift-gen/driver/constants.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Autogenerated by Thrift Compiler (0.9.3)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package driver
-
-import (
- "bytes"
- "fmt"
- "github.com/apache/thrift/lib/go/thrift"
-)
-
-// (needed to ensure safety because of naive import list construction.)
-var _ = thrift.ZERO
-var _ = fmt.Printf
-var _ = bytes.Equal
-
-func init() {
-}
diff --git a/example/hotrod/hotrod/services/driver/thrift-gen/driver/driver.go b/example/hotrod/hotrod/services/driver/thrift-gen/driver/driver.go
deleted file mode 100644
index c8b20275..00000000
--- a/example/hotrod/hotrod/services/driver/thrift-gen/driver/driver.go
+++ /dev/null
@@ -1,427 +0,0 @@
-// Autogenerated by Thrift Compiler (0.9.3)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package driver
-
-import (
- "bytes"
- "fmt"
- "github.com/apache/thrift/lib/go/thrift"
-)
-
-// (needed to ensure safety because of naive import list construction.)
-var _ = thrift.ZERO
-var _ = fmt.Printf
-var _ = bytes.Equal
-
-type Driver interface {
- // Parameters:
- // - Location
- FindNearest(location string) (r []*DriverLocation, err error)
-}
-
-type DriverClient struct {
- Transport thrift.TTransport
- ProtocolFactory thrift.TProtocolFactory
- InputProtocol thrift.TProtocol
- OutputProtocol thrift.TProtocol
- SeqId int32
-}
-
-func NewDriverClientFactory(t thrift.TTransport, f thrift.TProtocolFactory) *DriverClient {
- return &DriverClient{Transport: t,
- ProtocolFactory: f,
- InputProtocol: f.GetProtocol(t),
- OutputProtocol: f.GetProtocol(t),
- SeqId: 0,
- }
-}
-
-func NewDriverClientProtocol(t thrift.TTransport, iprot thrift.TProtocol, oprot thrift.TProtocol) *DriverClient {
- return &DriverClient{Transport: t,
- ProtocolFactory: nil,
- InputProtocol: iprot,
- OutputProtocol: oprot,
- SeqId: 0,
- }
-}
-
-// Parameters:
-// - Location
-func (p *DriverClient) FindNearest(location string) (r []*DriverLocation, err error) {
- if err = p.sendFindNearest(location); err != nil {
- return
- }
- return p.recvFindNearest()
-}
-
-func (p *DriverClient) sendFindNearest(location string) (err error) {
- oprot := p.OutputProtocol
- if oprot == nil {
- oprot = p.ProtocolFactory.GetProtocol(p.Transport)
- p.OutputProtocol = oprot
- }
- p.SeqId++
- if err = oprot.WriteMessageBegin("findNearest", thrift.CALL, p.SeqId); err != nil {
- return
- }
- args := DriverFindNearestArgs{
- Location: location,
- }
- if err = args.Write(oprot); err != nil {
- return
- }
- if err = oprot.WriteMessageEnd(); err != nil {
- return
- }
- return oprot.Flush()
-}
-
-func (p *DriverClient) recvFindNearest() (value []*DriverLocation, err error) {
- iprot := p.InputProtocol
- if iprot == nil {
- iprot = p.ProtocolFactory.GetProtocol(p.Transport)
- p.InputProtocol = iprot
- }
- method, mTypeId, seqId, err := iprot.ReadMessageBegin()
- if err != nil {
- return
- }
- if method != "findNearest" {
- err = thrift.NewTApplicationException(thrift.WRONG_METHOD_NAME, "findNearest failed: wrong method name")
- return
- }
- if p.SeqId != seqId {
- err = thrift.NewTApplicationException(thrift.BAD_SEQUENCE_ID, "findNearest failed: out of sequence response")
- return
- }
- if mTypeId == thrift.EXCEPTION {
- error0 := thrift.NewTApplicationException(thrift.UNKNOWN_APPLICATION_EXCEPTION, "Unknown Exception")
- var error1 error
- error1, err = error0.Read(iprot)
- if err != nil {
- return
- }
- if err = iprot.ReadMessageEnd(); err != nil {
- return
- }
- err = error1
- return
- }
- if mTypeId != thrift.REPLY {
- err = thrift.NewTApplicationException(thrift.INVALID_MESSAGE_TYPE_EXCEPTION, "findNearest failed: invalid message type")
- return
- }
- result := DriverFindNearestResult{}
- if err = result.Read(iprot); err != nil {
- return
- }
- if err = iprot.ReadMessageEnd(); err != nil {
- return
- }
- value = result.GetSuccess()
- return
-}
-
-type DriverProcessor struct {
- processorMap map[string]thrift.TProcessorFunction
- handler Driver
-}
-
-func (p *DriverProcessor) AddToProcessorMap(key string, processor thrift.TProcessorFunction) {
- p.processorMap[key] = processor
-}
-
-func (p *DriverProcessor) GetProcessorFunction(key string) (processor thrift.TProcessorFunction, ok bool) {
- processor, ok = p.processorMap[key]
- return processor, ok
-}
-
-func (p *DriverProcessor) ProcessorMap() map[string]thrift.TProcessorFunction {
- return p.processorMap
-}
-
-func NewDriverProcessor(handler Driver) *DriverProcessor {
-
- self2 := &DriverProcessor{handler: handler, processorMap: make(map[string]thrift.TProcessorFunction)}
- self2.processorMap["findNearest"] = &driverProcessorFindNearest{handler: handler}
- return self2
-}
-
-func (p *DriverProcessor) Process(iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
- name, _, seqId, err := iprot.ReadMessageBegin()
- if err != nil {
- return false, err
- }
- if processor, ok := p.GetProcessorFunction(name); ok {
- return processor.Process(seqId, iprot, oprot)
- }
- iprot.Skip(thrift.STRUCT)
- iprot.ReadMessageEnd()
- x3 := thrift.NewTApplicationException(thrift.UNKNOWN_METHOD, "Unknown function "+name)
- oprot.WriteMessageBegin(name, thrift.EXCEPTION, seqId)
- x3.Write(oprot)
- oprot.WriteMessageEnd()
- oprot.Flush()
- return false, x3
-
-}
-
-type driverProcessorFindNearest struct {
- handler Driver
-}
-
-func (p *driverProcessorFindNearest) Process(seqId int32, iprot, oprot thrift.TProtocol) (success bool, err thrift.TException) {
- args := DriverFindNearestArgs{}
- if err = args.Read(iprot); err != nil {
- iprot.ReadMessageEnd()
- x := thrift.NewTApplicationException(thrift.PROTOCOL_ERROR, err.Error())
- oprot.WriteMessageBegin("findNearest", thrift.EXCEPTION, seqId)
- x.Write(oprot)
- oprot.WriteMessageEnd()
- oprot.Flush()
- return false, err
- }
-
- iprot.ReadMessageEnd()
- result := DriverFindNearestResult{}
- var retval []*DriverLocation
- var err2 error
- if retval, err2 = p.handler.FindNearest(args.Location); err2 != nil {
- x := thrift.NewTApplicationException(thrift.INTERNAL_ERROR, "Internal error processing findNearest: "+err2.Error())
- oprot.WriteMessageBegin("findNearest", thrift.EXCEPTION, seqId)
- x.Write(oprot)
- oprot.WriteMessageEnd()
- oprot.Flush()
- return true, err2
- } else {
- result.Success = retval
- }
- if err2 = oprot.WriteMessageBegin("findNearest", thrift.REPLY, seqId); err2 != nil {
- err = err2
- }
- if err2 = result.Write(oprot); err == nil && err2 != nil {
- err = err2
- }
- if err2 = oprot.WriteMessageEnd(); err == nil && err2 != nil {
- err = err2
- }
- if err2 = oprot.Flush(); err == nil && err2 != nil {
- err = err2
- }
- if err != nil {
- return
- }
- return true, err
-}
-
-// HELPER FUNCTIONS AND STRUCTURES
-
-// Attributes:
-// - Location
-type DriverFindNearestArgs struct {
- Location string `thrift:"location,1" json:"location"`
-}
-
-func NewDriverFindNearestArgs() *DriverFindNearestArgs {
- return &DriverFindNearestArgs{}
-}
-
-func (p *DriverFindNearestArgs) GetLocation() string {
- return p.Location
-}
-func (p *DriverFindNearestArgs) Read(iprot thrift.TProtocol) error {
- if _, err := iprot.ReadStructBegin(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
- }
-
- for {
- _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
- if err != nil {
- return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
- }
- if fieldTypeId == thrift.STOP {
- break
- }
- switch fieldId {
- case 1:
- if err := p.readField1(iprot); err != nil {
- return err
- }
- default:
- if err := iprot.Skip(fieldTypeId); err != nil {
- return err
- }
- }
- if err := iprot.ReadFieldEnd(); err != nil {
- return err
- }
- }
- if err := iprot.ReadStructEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
- }
- return nil
-}
-
-func (p *DriverFindNearestArgs) readField1(iprot thrift.TProtocol) error {
- if v, err := iprot.ReadString(); err != nil {
- return thrift.PrependError("error reading field 1: ", err)
- } else {
- p.Location = v
- }
- return nil
-}
-
-func (p *DriverFindNearestArgs) Write(oprot thrift.TProtocol) error {
- if err := oprot.WriteStructBegin("findNearest_args"); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
- }
- if err := p.writeField1(oprot); err != nil {
- return err
- }
- if err := oprot.WriteFieldStop(); err != nil {
- return thrift.PrependError("write field stop error: ", err)
- }
- if err := oprot.WriteStructEnd(); err != nil {
- return thrift.PrependError("write struct stop error: ", err)
- }
- return nil
-}
-
-func (p *DriverFindNearestArgs) writeField1(oprot thrift.TProtocol) (err error) {
- if err := oprot.WriteFieldBegin("location", thrift.STRING, 1); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:location: ", p), err)
- }
- if err := oprot.WriteString(string(p.Location)); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T.location (1) field write error: ", p), err)
- }
- if err := oprot.WriteFieldEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field end error 1:location: ", p), err)
- }
- return err
-}
-
-func (p *DriverFindNearestArgs) String() string {
- if p == nil {
- return ""
- }
- return fmt.Sprintf("DriverFindNearestArgs(%+v)", *p)
-}
-
-// Attributes:
-// - Success
-type DriverFindNearestResult struct {
- Success []*DriverLocation `thrift:"success,0" json:"success,omitempty"`
-}
-
-func NewDriverFindNearestResult() *DriverFindNearestResult {
- return &DriverFindNearestResult{}
-}
-
-var DriverFindNearestResult_Success_DEFAULT []*DriverLocation
-
-func (p *DriverFindNearestResult) GetSuccess() []*DriverLocation {
- return p.Success
-}
-func (p *DriverFindNearestResult) IsSetSuccess() bool {
- return p.Success != nil
-}
-
-func (p *DriverFindNearestResult) Read(iprot thrift.TProtocol) error {
- if _, err := iprot.ReadStructBegin(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
- }
-
- for {
- _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
- if err != nil {
- return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
- }
- if fieldTypeId == thrift.STOP {
- break
- }
- switch fieldId {
- case 0:
- if err := p.readField0(iprot); err != nil {
- return err
- }
- default:
- if err := iprot.Skip(fieldTypeId); err != nil {
- return err
- }
- }
- if err := iprot.ReadFieldEnd(); err != nil {
- return err
- }
- }
- if err := iprot.ReadStructEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
- }
- return nil
-}
-
-func (p *DriverFindNearestResult) readField0(iprot thrift.TProtocol) error {
- _, size, err := iprot.ReadListBegin()
- if err != nil {
- return thrift.PrependError("error reading list begin: ", err)
- }
- tSlice := make([]*DriverLocation, 0, size)
- p.Success = tSlice
- for i := 0; i < size; i++ {
- _elem4 := &DriverLocation{}
- if err := _elem4.Read(iprot); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T error reading struct: ", _elem4), err)
- }
- p.Success = append(p.Success, _elem4)
- }
- if err := iprot.ReadListEnd(); err != nil {
- return thrift.PrependError("error reading list end: ", err)
- }
- return nil
-}
-
-func (p *DriverFindNearestResult) Write(oprot thrift.TProtocol) error {
- if err := oprot.WriteStructBegin("findNearest_result"); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
- }
- if err := p.writeField0(oprot); err != nil {
- return err
- }
- if err := oprot.WriteFieldStop(); err != nil {
- return thrift.PrependError("write field stop error: ", err)
- }
- if err := oprot.WriteStructEnd(); err != nil {
- return thrift.PrependError("write struct stop error: ", err)
- }
- return nil
-}
-
-func (p *DriverFindNearestResult) writeField0(oprot thrift.TProtocol) (err error) {
- if p.IsSetSuccess() {
- if err := oprot.WriteFieldBegin("success", thrift.LIST, 0); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field begin error 0:success: ", p), err)
- }
- if err := oprot.WriteListBegin(thrift.STRUCT, len(p.Success)); err != nil {
- return thrift.PrependError("error writing list begin: ", err)
- }
- for _, v := range p.Success {
- if err := v.Write(oprot); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T error writing struct: ", v), err)
- }
- }
- if err := oprot.WriteListEnd(); err != nil {
- return thrift.PrependError("error writing list end: ", err)
- }
- if err := oprot.WriteFieldEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field end error 0:success: ", p), err)
- }
- }
- return err
-}
-
-func (p *DriverFindNearestResult) String() string {
- if p == nil {
- return ""
- }
- return fmt.Sprintf("DriverFindNearestResult(%+v)", *p)
-}
diff --git a/example/hotrod/hotrod/services/driver/thrift-gen/driver/tchan-driver.go b/example/hotrod/hotrod/services/driver/thrift-gen/driver/tchan-driver.go
deleted file mode 100644
index d69dfd23..00000000
--- a/example/hotrod/hotrod/services/driver/thrift-gen/driver/tchan-driver.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// @generated Code generated by thrift-gen. Do not modify.
-
-// Package driver is generated code used to make or handle TChannel calls using Thrift.
-package driver
-
-import (
- "fmt"
-
- athrift "github.com/apache/thrift/lib/go/thrift"
- "github.com/uber/tchannel-go/thrift"
-)
-
-// Interfaces for the service and client for the services defined in the IDL.
-
-// TChanDriver is the interface that defines the server handler and client interface.
-type TChanDriver interface {
- FindNearest(ctx thrift.Context, location string) ([]*DriverLocation, error)
-}
-
-// Implementation of a client and service handler.
-
-type tchanDriverClient struct {
- thriftService string
- client thrift.TChanClient
-}
-
-func NewTChanDriverInheritedClient(thriftService string, client thrift.TChanClient) *tchanDriverClient {
- return &tchanDriverClient{
- thriftService,
- client,
- }
-}
-
-// NewTChanDriverClient creates a client that can be used to make remote calls.
-func NewTChanDriverClient(client thrift.TChanClient) TChanDriver {
- return NewTChanDriverInheritedClient("Driver", client)
-}
-
-func (c *tchanDriverClient) FindNearest(ctx thrift.Context, location string) ([]*DriverLocation, error) {
- var resp DriverFindNearestResult
- args := DriverFindNearestArgs{
- Location: location,
- }
- success, err := c.client.Call(ctx, c.thriftService, "findNearest", &args, &resp)
- if err == nil && !success {
- }
-
- return resp.GetSuccess(), err
-}
-
-type tchanDriverServer struct {
- handler TChanDriver
-}
-
-// NewTChanDriverServer wraps a handler for TChanDriver so it can be
-// registered with a thrift.Server.
-func NewTChanDriverServer(handler TChanDriver) thrift.TChanServer {
- return &tchanDriverServer{
- handler,
- }
-}
-
-func (s *tchanDriverServer) Service() string {
- return "Driver"
-}
-
-func (s *tchanDriverServer) Methods() []string {
- return []string{
- "findNearest",
- }
-}
-
-func (s *tchanDriverServer) Handle(ctx thrift.Context, methodName string, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
- switch methodName {
- case "findNearest":
- return s.handleFindNearest(ctx, protocol)
-
- default:
- return false, nil, fmt.Errorf("method %v not found in service %v", methodName, s.Service())
- }
-}
-
-func (s *tchanDriverServer) handleFindNearest(ctx thrift.Context, protocol athrift.TProtocol) (bool, athrift.TStruct, error) {
- var req DriverFindNearestArgs
- var res DriverFindNearestResult
-
- if err := req.Read(protocol); err != nil {
- return false, nil, err
- }
-
- r, err :=
- s.handler.FindNearest(ctx, req.Location)
-
- if err != nil {
- return false, nil, err
- } else {
- res.Success = r
- }
-
- return err == nil, &res, nil
-}
diff --git a/example/hotrod/hotrod/services/driver/thrift-gen/driver/ttypes.go b/example/hotrod/hotrod/services/driver/thrift-gen/driver/ttypes.go
deleted file mode 100644
index 2f5093b1..00000000
--- a/example/hotrod/hotrod/services/driver/thrift-gen/driver/ttypes.go
+++ /dev/null
@@ -1,154 +0,0 @@
-// Autogenerated by Thrift Compiler (0.9.3)
-// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
-
-package driver
-
-import (
- "bytes"
- "fmt"
- "github.com/apache/thrift/lib/go/thrift"
-)
-
-// (needed to ensure safety because of naive import list construction.)
-var _ = thrift.ZERO
-var _ = fmt.Printf
-var _ = bytes.Equal
-
-var GoUnusedProtection__ int
-
-// Attributes:
-// - DriverID
-// - Location
-type DriverLocation struct {
- DriverID string `thrift:"driver_id,1,required" json:"driver_id"`
- Location string `thrift:"location,2,required" json:"location"`
-}
-
-func NewDriverLocation() *DriverLocation {
- return &DriverLocation{}
-}
-
-func (p *DriverLocation) GetDriverID() string {
- return p.DriverID
-}
-
-func (p *DriverLocation) GetLocation() string {
- return p.Location
-}
-func (p *DriverLocation) Read(iprot thrift.TProtocol) error {
- if _, err := iprot.ReadStructBegin(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T read error: ", p), err)
- }
-
- var issetDriverID bool = false
- var issetLocation bool = false
-
- for {
- _, fieldTypeId, fieldId, err := iprot.ReadFieldBegin()
- if err != nil {
- return thrift.PrependError(fmt.Sprintf("%T field %d read error: ", p, fieldId), err)
- }
- if fieldTypeId == thrift.STOP {
- break
- }
- switch fieldId {
- case 1:
- if err := p.readField1(iprot); err != nil {
- return err
- }
- issetDriverID = true
- case 2:
- if err := p.readField2(iprot); err != nil {
- return err
- }
- issetLocation = true
- default:
- if err := iprot.Skip(fieldTypeId); err != nil {
- return err
- }
- }
- if err := iprot.ReadFieldEnd(); err != nil {
- return err
- }
- }
- if err := iprot.ReadStructEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T read struct end error: ", p), err)
- }
- if !issetDriverID {
- return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field DriverID is not set"))
- }
- if !issetLocation {
- return thrift.NewTProtocolExceptionWithType(thrift.INVALID_DATA, fmt.Errorf("Required field Location is not set"))
- }
- return nil
-}
-
-func (p *DriverLocation) readField1(iprot thrift.TProtocol) error {
- if v, err := iprot.ReadString(); err != nil {
- return thrift.PrependError("error reading field 1: ", err)
- } else {
- p.DriverID = v
- }
- return nil
-}
-
-func (p *DriverLocation) readField2(iprot thrift.TProtocol) error {
- if v, err := iprot.ReadString(); err != nil {
- return thrift.PrependError("error reading field 2: ", err)
- } else {
- p.Location = v
- }
- return nil
-}
-
-func (p *DriverLocation) Write(oprot thrift.TProtocol) error {
- if err := oprot.WriteStructBegin("DriverLocation"); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write struct begin error: ", p), err)
- }
- if err := p.writeField1(oprot); err != nil {
- return err
- }
- if err := p.writeField2(oprot); err != nil {
- return err
- }
- if err := oprot.WriteFieldStop(); err != nil {
- return thrift.PrependError("write field stop error: ", err)
- }
- if err := oprot.WriteStructEnd(); err != nil {
- return thrift.PrependError("write struct stop error: ", err)
- }
- return nil
-}
-
-func (p *DriverLocation) writeField1(oprot thrift.TProtocol) (err error) {
- if err := oprot.WriteFieldBegin("driver_id", thrift.STRING, 1); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field begin error 1:driver_id: ", p), err)
- }
- if err := oprot.WriteString(string(p.DriverID)); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T.driver_id (1) field write error: ", p), err)
- }
- if err := oprot.WriteFieldEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field end error 1:driver_id: ", p), err)
- }
- return err
-}
-
-func (p *DriverLocation) writeField2(oprot thrift.TProtocol) (err error) {
- if err := oprot.WriteFieldBegin("location", thrift.STRING, 2); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field begin error 2:location: ", p), err)
- }
- if err := oprot.WriteString(string(p.Location)); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T.location (2) field write error: ", p), err)
- }
- if err := oprot.WriteFieldEnd(); err != nil {
- return thrift.PrependError(fmt.Sprintf("%T write field end error 2:location: ", p), err)
- }
- return err
-}
-
-func (p *DriverLocation) String() string {
- if p == nil {
- return ""
- }
- return fmt.Sprintf("DriverLocation(%+v)", *p)
-}
diff --git a/example/hotrod/hotrod/services/frontend/best_eta.go b/example/hotrod/hotrod/services/frontend/best_eta.go
deleted file mode 100644
index a1094fc7..00000000
--- a/example/hotrod/hotrod/services/frontend/best_eta.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package frontend
-
-import (
- "context"
- "errors"
- "math"
- "sync"
- "time"
-
- "github.com/opentracing/opentracing-go"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/pool"
- "github.com/rnburn/hotrod-docker/services/config"
- "github.com/rnburn/hotrod-docker/services/customer"
- "github.com/rnburn/hotrod-docker/services/driver"
- "github.com/rnburn/hotrod-docker/services/route"
-)
-
-type bestETA struct {
- customer customer.Interface
- driver driver.Interface
- route route.Interface
- pool *pool.Pool
- logger log.Factory
-}
-
-// Response contains ETA for a trip.
-type Response struct {
- Driver string
- ETA time.Duration
-}
-
-func newBestETA(tracer opentracing.Tracer, logger log.Factory) *bestETA {
- return &bestETA{
- customer: customer.NewClient(
- tracer,
- logger.With(zap.String("component", "customer_client")),
- ),
- driver: driver.NewClient(
- tracer,
- logger.With(zap.String("component", "driver_client")),
- ),
- route: route.NewClient(
- tracer,
- logger.With(zap.String("component", "route_client")),
- ),
- pool: pool.New(config.RouteWorkerPoolSize),
- logger: logger,
- }
-}
-
-func (eta *bestETA) Get(ctx context.Context, customerID string) (*Response, error) {
- customer, err := eta.customer.Get(ctx, customerID)
- if err != nil {
- return nil, err
- }
- eta.logger.For(ctx).Info("Found customer", zap.Any("customer", customer))
-
- if span := opentracing.SpanFromContext(ctx); span != nil {
- span.SetBaggageItem("customer", customer.Name)
- }
-
- drivers, err := eta.driver.FindNearest(ctx, customer.Location)
- if err != nil {
- return nil, err
- }
- eta.logger.For(ctx).Info("Found drivers", zap.Any("drivers", drivers))
-
- results := eta.getRoutes(ctx, customer, drivers)
- eta.logger.For(ctx).Info("Found routes", zap.Any("routes", results))
-
- resp := &Response{ETA: math.MaxInt64}
- for _, result := range results {
- if result.err != nil {
- return nil, err
- }
- if result.route.ETA < resp.ETA {
- resp.ETA = result.route.ETA
- resp.Driver = result.driver
- }
- }
- if resp.Driver == "" {
- return nil, errors.New("No routes found")
- }
-
- eta.logger.For(ctx).Info("Dispatch successful", zap.String("driver", resp.Driver), zap.String("eta", resp.ETA.String()))
- return resp, nil
-}
-
-type routeResult struct {
- driver string
- route *route.Route
- err error
-}
-
-// getRoutes calls Route service for each (customer, driver) pair
-func (eta *bestETA) getRoutes(ctx context.Context, customer *customer.Customer, drivers []driver.Driver) []routeResult {
- results := make([]routeResult, 0, len(drivers))
- wg := sync.WaitGroup{}
- routesLock := sync.Mutex{}
- for _, dd := range drivers {
- wg.Add(1)
- driver := dd // capture loop var
- // Use worker pool to (potentially) execute requests in parallel
- eta.pool.Execute(func() {
- route, err := eta.route.FindRoute(ctx, driver.Location, customer.Location)
- routesLock.Lock()
- results = append(results, routeResult{
- driver: driver.DriverID,
- route: route,
- err: err,
- })
- routesLock.Unlock()
- wg.Done()
- })
- }
- wg.Wait()
- return results
-}
diff --git a/example/hotrod/hotrod/services/frontend/server.go b/example/hotrod/hotrod/services/frontend/server.go
deleted file mode 100644
index 2a338e23..00000000
--- a/example/hotrod/hotrod/services/frontend/server.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package frontend
-
-import (
- "encoding/json"
- "net/http"
-
- "github.com/opentracing/opentracing-go"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/httperr"
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
-)
-
-// Server implements jaeger-demo-frontend service
-type Server struct {
- hostPort string
- tracer opentracing.Tracer
- logger log.Factory
- bestETA *bestETA
-}
-
-// NewServer creates a new frontend.Server
-func NewServer(hostPort string, tracer opentracing.Tracer, logger log.Factory) *Server {
- return &Server{
- hostPort: hostPort,
- tracer: tracer,
- logger: logger,
- bestETA: newBestETA(tracer, logger),
- }
-}
-
-// Run starts the frontend server
-func (s *Server) Run() error {
- mux := s.createServeMux()
- s.logger.Bg().Info("Starting", zap.String("address", "http://"+s.hostPort))
- return http.ListenAndServe(s.hostPort, mux)
-}
-
-func (s *Server) createServeMux() http.Handler {
- mux := tracing.NewServeMux(s.tracer)
- mux.Handle("/", http.HandlerFunc(s.home))
- mux.Handle("/dispatch", http.HandlerFunc(s.dispatch))
- return mux
-}
-
-func (s *Server) home(w http.ResponseWriter, r *http.Request) {
- s.logger.For(r.Context()).Info("HTTP", zap.String("method", r.Method), zap.Stringer("url", r.URL))
- http.ServeFile(w, r, "services/frontend/web_assets/index.html")
-}
-
-func (s *Server) dispatch(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- s.logger.For(ctx).Info("HTTP request received", zap.String("method", r.Method), zap.Stringer("url", r.URL))
- if err := r.ParseForm(); httperr.HandleError(w, err, http.StatusBadRequest) {
- s.logger.For(ctx).Error("bad request", zap.Error(err))
- return
- }
-
- customerID := r.Form.Get("customer")
- if customerID == "" {
- http.Error(w, "Missing required 'customer' parameter", http.StatusBadRequest)
- return
- }
-
- // TODO distinguish between user errors (such as invalid customer ID) and server failures
- response, err := s.bestETA.Get(ctx, customerID)
- if httperr.HandleError(w, err, http.StatusInternalServerError) {
- s.logger.For(ctx).Error("request failed", zap.Error(err))
- return
- }
-
- data, err := json.Marshal(response)
- if httperr.HandleError(w, err, http.StatusInternalServerError) {
- s.logger.For(ctx).Error("cannot marshal response", zap.Error(err))
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- w.Write(data)
-}
diff --git a/example/hotrod/hotrod/services/frontend/web_assets/index.html b/example/hotrod/hotrod/services/frontend/web_assets/index.html
deleted file mode 100644
index 5db64bad..00000000
--- a/example/hotrod/hotrod/services/frontend/web_assets/index.html
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-
-
- HotROD - Rides On Demand
-
-
-
-
-
-
-
-
-
-
-
- Hot R.O.D.
- Rides On Demand
-
-
- Rachel's Floral Designs
-
-
- Trom Chocolatier
-
-
- Japanese Deserts
-
-
- Amazing Coffee Roasters
-
-
- Click on customer name above to order a car.
-
-
-
-
-
-
-
-
diff --git a/example/hotrod/hotrod/services/route/client.go b/example/hotrod/hotrod/services/route/client.go
deleted file mode 100644
index 3de40a47..00000000
--- a/example/hotrod/hotrod/services/route/client.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package route
-
-import (
- "context"
- "net/http"
- "net/url"
-
- "github.com/opentracing-contrib/go-stdlib/nethttp"
- "github.com/opentracing/opentracing-go"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
-)
-
-// Client is a remote client that implements route.Interface
-type Client struct {
- tracer opentracing.Tracer
- logger log.Factory
- client *tracing.HTTPClient
-}
-
-// NewClient creates a new route.Client
-func NewClient(tracer opentracing.Tracer, logger log.Factory) *Client {
- return &Client{
- tracer: tracer,
- logger: logger,
- client: &tracing.HTTPClient{
- Client: &http.Client{Transport: &nethttp.Transport{}},
- Tracer: tracer,
- },
- }
-}
-
-// FindRoute implements route.Interface#FindRoute as an RPC
-func (c *Client) FindRoute(ctx context.Context, pickup, dropoff string) (*Route, error) {
- c.logger.For(ctx).Info("Finding route", zap.String("pickup", pickup), zap.String("dropoff", dropoff))
-
- v := url.Values{}
- v.Set("pickup", pickup)
- v.Set("dropoff", dropoff)
- url := "http://127.0.0.1/route?" + v.Encode()
-
- var route Route
- if err := c.client.GetJSON(ctx, "/route", url, &route); err != nil {
- c.logger.For(ctx).Error("Error getting route", zap.Error(err))
- return nil, err
- }
- return &route, nil
-}
diff --git a/example/hotrod/hotrod/services/route/interface.go b/example/hotrod/hotrod/services/route/interface.go
deleted file mode 100644
index f65addce..00000000
--- a/example/hotrod/hotrod/services/route/interface.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package route
-
-import "context"
-import "time"
-
-// Route describes a route between Pickup and Dropoff locations and expected time to arrival.
-type Route struct {
- Pickup string
- Dropoff string
- ETA time.Duration
-}
-
-// Interface exposed by the Driver service.
-type Interface interface {
- FindRoute(ctx context.Context, pickup, dropoff string) (*Route, error)
-}
diff --git a/example/hotrod/hotrod/services/route/server.go b/example/hotrod/hotrod/services/route/server.go
deleted file mode 100644
index e4be024a..00000000
--- a/example/hotrod/hotrod/services/route/server.go
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package route
-
-import (
- "context"
- "encoding/json"
- "math"
- "math/rand"
- "net/http"
- "time"
-
- "github.com/opentracing/opentracing-go"
- "go.uber.org/zap"
-
- "github.com/rnburn/hotrod-docker/pkg/delay"
- "github.com/rnburn/hotrod-docker/pkg/httperr"
- "github.com/rnburn/hotrod-docker/pkg/httpexpvar"
- "github.com/rnburn/hotrod-docker/pkg/log"
- "github.com/rnburn/hotrod-docker/pkg/tracing"
- "github.com/rnburn/hotrod-docker/services/config"
-)
-
-// Server implements Route service
-type Server struct {
- hostPort string
- tracer opentracing.Tracer
- logger log.Factory
-}
-
-// NewServer creates a new route.Server
-func NewServer(hostPort string, tracer opentracing.Tracer, logger log.Factory) *Server {
- return &Server{
- hostPort: hostPort,
- tracer: tracer,
- logger: logger,
- }
-}
-
-// Run starts the Route server
-func (s *Server) Run() error {
- mux := s.createServeMux()
- s.logger.Bg().Info("Starting", zap.String("address", "http://"+s.hostPort))
- return http.ListenAndServe(s.hostPort, mux)
-}
-
-func (s *Server) createServeMux() http.Handler {
- mux := tracing.NewServeMux(s.tracer)
- mux.Handle("/route", http.HandlerFunc(s.route))
- mux.Handle("/debug/vars", http.HandlerFunc(httpexpvar.Handler))
- return mux
-}
-
-func (s *Server) route(w http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- s.logger.For(ctx).Info("HTTP request received", zap.String("method", r.Method), zap.Stringer("url", r.URL))
- if err := r.ParseForm(); httperr.HandleError(w, err, http.StatusBadRequest) {
- s.logger.For(ctx).Error("bad request", zap.Error(err))
- return
- }
-
- pickup := r.Form.Get("pickup")
- if pickup == "" {
- http.Error(w, "Missing required 'pickup' parameter", http.StatusBadRequest)
- return
- }
-
- dropoff := r.Form.Get("dropoff")
- if dropoff == "" {
- http.Error(w, "Missing required 'dropoff' parameter", http.StatusBadRequest)
- return
- }
-
- response := computeRoute(ctx, pickup, dropoff)
-
- data, err := json.Marshal(response)
- if httperr.HandleError(w, err, http.StatusInternalServerError) {
- s.logger.For(ctx).Error("cannot marshal response", zap.Error(err))
- return
- }
-
- w.Header().Set("Content-Type", "application/json")
- w.Write(data)
-}
-
-func computeRoute(ctx context.Context, pickup, dropoff string) *Route {
- start := time.Now()
- defer func() {
- updateCalcStats(ctx, time.Since(start))
- }()
-
- // Simulate expensive calculation
- delay.Sleep(config.RouteCalcDelay, config.RouteCalcDelayStdDev)
-
- eta := math.Max(2, rand.NormFloat64()*3+5)
- return &Route{
- Pickup: pickup,
- Dropoff: dropoff,
- ETA: time.Duration(eta) * time.Minute,
- }
-}
diff --git a/example/hotrod/hotrod/services/route/stats.go b/example/hotrod/hotrod/services/route/stats.go
deleted file mode 100644
index 22a2037d..00000000
--- a/example/hotrod/hotrod/services/route/stats.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// 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.
-
-package route
-
-import (
- "context"
- "expvar"
- "time"
-
- "github.com/opentracing/opentracing-go"
-)
-
-var routeCalcByCustomer = expvar.NewMap("route.calc.by.customer.sec")
-var routeCalcBySession = expvar.NewMap("route.calc.by.session.sec")
-
-var stats = []struct {
- expvar *expvar.Map
- baggage string
-}{
- {routeCalcByCustomer, "customer"},
- {routeCalcBySession, "session"},
-}
-
-func updateCalcStats(ctx context.Context, delay time.Duration) {
- span := opentracing.SpanFromContext(ctx)
- if span == nil {
- return
- }
- delaySec := float64(delay/time.Millisecond) / 1000.0
- for _, s := range stats {
- key := span.BaggageItem(s.baggage)
- if key != "" {
- s.expvar.AddFloat(key, delaySec)
- }
- }
-}
diff --git a/example/hotrod/nginx.conf b/example/hotrod/nginx.conf
deleted file mode 100644
index 1554687c..00000000
--- a/example/hotrod/nginx.conf
+++ /dev/null
@@ -1,41 +0,0 @@
-load_module modules/ngx_http_opentracing_module.so;
-load_module modules/ngx_http_jaeger_module.so;
-
-events {}
-
-http {
- jaeger_reporter_local_agent_host_port $JAEGER_AGENT_HOST:$JAEGER_AGENT_PORT;
- jaeger_service_name nginx;
- jaeger_sampler_type const;
- jaeger_sampler_param 1;
- opentracing on;
-
- upstream frontend {
- server localhost:8080;
- }
-
- upstream customer {
- server localhost:8081;
- }
-
- upstream route {
- server localhost:8083;
- }
-
- server {
- listen 80;
- server_name localhost;
-
- location / {
- proxy_pass http://frontend;
- }
-
- location /customer {
- proxy_pass http://customer;
- }
-
- location /route {
- proxy_pass http://route;
- }
- }
-}
diff --git a/example/hotrod/start.sh b/example/hotrod/start.sh
deleted file mode 100755
index 301516a1..00000000
--- a/example/hotrod/start.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-export JAEGER_AGENT_HOST=$JAEGER_PORT_6831_UDP_ADDR
-export JAEGER_AGENT_PORT=$JAEGER_PORT_6831_UDP_PORT
-/app/hotrod all &
-envsubst '\$JAEGER_AGENT_HOST \$JAEGER_AGENT_PORT' < /app/nginx.conf > /etc/nginx/nginx.conf
-nginx
-while /bin/true; do
- sleep 50
-done
diff --git a/example/trivial/README.md b/example/trivial/README.md
deleted file mode 100644
index 13e4fd27..00000000
--- a/example/trivial/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-A minimal OpenTracing example demonstrating usage of the nginx-opentracing
-docker image with zipkin. It features Nginx as a reverse-proxy in front a Go
-server. Use these commands to run:
-```bash
-docker build -t nginx-example-trivial .
-docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin
-docker run -d -p 8080:80 --link zipkin:zipkin nginx-example-trivial
-curl localhost:8080
-```
-Visit http://localhost:9411 to view the traces in Zipkin.
-
-Additionaly, the example can be made to work with Jaeger. Run:
-```bash
-docker build -t nginx-example-trivial .
-docker run -d -e COLLECTOR_ZIPKIN_HTTP_PORT=9411 -p5775:5775/udp -p6831:6831/udp -p6832:6832/udp -p5778:5778 -p16686:16686 -p14268:14268 -p9411:9411 --name jaeger jaegertracing/all-in-one:latest
-docker run -d -p 8080:80 --link jaeger:zipkin nginx-example-trivial
-curl localhost:8080
-```
-And you can view the traces at http://localhost:16686.
diff --git a/example/trivial/jaeger/Dockerfile b/example/trivial/jaeger/Dockerfile
new file mode 100644
index 00000000..8d7ef8b9
--- /dev/null
+++ b/example/trivial/jaeger/Dockerfile
@@ -0,0 +1,21 @@
+FROM ubuntu:18.04
+
+WORKDIR /app
+ADD . /app
+ENV GOPATH="/app/go"
+RUN set -x \
+ && apt-get update \
+ && apt-get install --no-install-recommends --no-install-suggests -y \
+ golang \
+ ca-certificates \
+ git \
+ curl \
+ && export PATH=$PATH:$GOPATH/bin \
+ && curl https://glide.sh/get | sh \
+ && cd go/src/hello-backend \
+ && glide up \
+ && glide install \
+ && go build -o /app/server server.go
+
+EXPOSE 9001
+CMD ["/app/server", "-collector_host", "jaeger", "-collector_port", "6831"]
diff --git a/example/trivial/jaeger/README.md b/example/trivial/jaeger/README.md
new file mode 100644
index 00000000..c8029c38
--- /dev/null
+++ b/example/trivial/jaeger/README.md
@@ -0,0 +1,8 @@
+A minimal OpenTracing example demonstrating usage of the nginx-opentracing
+docker image with Jaeger. It features Nginx as a reverse-proxy in front a Go
+server. Use these commands to run:
+```bash
+docker-compose up
+curl localhost:8080
+```
+Visit http://localhost:16686 to view the traces in Jaeger.
diff --git a/example/trivial/jaeger/docker-compose.yaml b/example/trivial/jaeger/docker-compose.yaml
new file mode 100644
index 00000000..7840c54c
--- /dev/null
+++ b/example/trivial/jaeger/docker-compose.yaml
@@ -0,0 +1,51 @@
+version: '2'
+services:
+
+ nginx:
+ image: opentracing/nginx-opentracing
+ networks:
+ trivial_example:
+ aliases:
+ - nginx
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf
+ - ./jaeger-config.json:/etc/jaeger-config.json
+ expose:
+ - "8080"
+ ports:
+ - "8080:8080"
+
+ app-service:
+ build:
+ context: .
+ dockerfile: ./Dockerfile
+ networks:
+ trivial_example:
+ aliases:
+ - app-service
+ expose:
+ - "9001"
+ ports:
+ - "9001:9001"
+ command:
+ - /app/server
+ - -collector_host
+ - jaeger
+
+ jaeger:
+ image: jaegertracing/all-in-one
+ environment:
+ - COLLECTOR_ZIPKIN_HTTP_PORT=9411
+ networks:
+ trivial_example:
+ aliases:
+ - jaeger
+ expose:
+ - "9411"
+ - "16686"
+ ports:
+ - "9411:9411"
+ - "16686:16686"
+
+networks:
+ trivial_example: {}
diff --git a/example/trivial/jaeger/go/src/hello-backend/glide.yaml b/example/trivial/jaeger/go/src/hello-backend/glide.yaml
new file mode 100644
index 00000000..df73e09b
--- /dev/null
+++ b/example/trivial/jaeger/go/src/hello-backend/glide.yaml
@@ -0,0 +1,8 @@
+package: .
+import:
+- package: github.com/opentracing/opentracing-go
+ version: ~1.0.2
+- package: github.com/uber/jaeger-client-go
+ version: ~2.14.0
+ subpackages:
+ - config
diff --git a/example/trivial/jaeger/go/src/hello-backend/server.go b/example/trivial/jaeger/go/src/hello-backend/server.go
new file mode 100644
index 00000000..f5b3c6c5
--- /dev/null
+++ b/example/trivial/jaeger/go/src/hello-backend/server.go
@@ -0,0 +1,66 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "time"
+ "log"
+ opentracing "github.com/opentracing/opentracing-go"
+ "github.com/uber/jaeger-client-go"
+ "github.com/uber/jaeger-client-go/config"
+ "net/http"
+)
+
+const (
+ serviceName = "hello-server"
+ hostPort = "0.0.0.0:0"
+ debug = false
+ sameSpan = false
+ traceID128Bit = true
+)
+
+var collectorHost = flag.String("collector_host", "localhost", "Host for Zipkin Collector")
+var collectorPort = flag.String("collector_port", "6831", "Port for Zipkin Collector")
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ for k, v := range r.Header {
+ fmt.Fprintf(w, "Header field %q, Value %q\n", k, v)
+ }
+ wireContext, _ := opentracing.GlobalTracer().Extract(
+ opentracing.HTTPHeaders,
+ opentracing.HTTPHeadersCarrier(r.Header))
+ span := opentracing.StartSpan(
+ "/",
+ opentracing.ChildOf(wireContext))
+ defer span.Finish()
+ fmt.Fprintf(w, "Hello, World!")
+}
+
+func main() {
+ flag.Parse()
+ cfg := config.Configuration{
+ Sampler: &config.SamplerConfig{
+ Type: "const",
+ Param: 1,
+ },
+ Reporter: &config.ReporterConfig{
+ LocalAgentHostPort: *collectorHost + ":" + *collectorPort,
+ LogSpans: true,
+ BufferFlushInterval: 1 * time.Second,
+ },
+ }
+ closer, err := cfg.InitGlobalTracer(
+ "backend",
+ config.Logger(jaeger.StdLogger),
+ )
+
+ if err != nil {
+ log.Printf("Could not initialize jaeger tracer: %s", err.Error())
+ return
+ }
+
+ defer closer.Close()
+
+ http.HandleFunc("/", handler)
+ http.ListenAndServe(":9001", nil)
+}
diff --git a/example/trivial/jaeger/jaeger-config.json b/example/trivial/jaeger/jaeger-config.json
new file mode 100644
index 00000000..f4ec56fa
--- /dev/null
+++ b/example/trivial/jaeger/jaeger-config.json
@@ -0,0 +1,12 @@
+{
+ "service_name": "nginx",
+ "diabled": false,
+ "reporter": {
+ "logSpans": true,
+ "localAgentHostPort": "jaeger:6831"
+ },
+ "sampler": {
+ "type": "const",
+ "param": "1"
+ }
+}
diff --git a/example/trivial/nginx.conf b/example/trivial/jaeger/nginx.conf
similarity index 53%
rename from example/trivial/nginx.conf
rename to example/trivial/jaeger/nginx.conf
index d7133a54..059e8eeb 100644
--- a/example/trivial/nginx.conf
+++ b/example/trivial/jaeger/nginx.conf
@@ -1,25 +1,24 @@
load_module modules/ngx_http_opentracing_module.so;
-load_module modules/ngx_http_zipkin_module.so;
events {}
http {
- zipkin_collector_host $ZIPKIN_PORT_9411_TCP_ADDR;
- zipkin_collector_port $ZIPKIN_PORT_9411_TCP_PORT;
- zipkin_service_name nginx;
opentracing on;
+ opentracing_load_tracer /usr/local/lib/libjaegertracing_plugin.so /etc/jaeger-config.json;
upstream backend {
- server localhost:9001;
+ server app-service:9001;
}
server {
- listen 80;
+ error_log /var/log/nginx/debug.log debug;
+ listen 8080;
server_name localhost;
location = / {
- proxy_pass http://backend;
opentracing_trace_locations off;
+ proxy_pass http://backend;
+ opentracing_propagate_context;
}
}
}
diff --git a/example/trivial/start.sh b/example/trivial/start.sh
deleted file mode 100755
index 5ec715ef..00000000
--- a/example/trivial/start.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-./server -collector_host $ZIPKIN_PORT_9411_TCP_ADDR -collector_port $ZIPKIN_PORT_9411_TCP_PORT &
-envsubst '\$ZIPKIN_PORT_9411_TCP_ADDR \$ZIPKIN_PORT_9411_TCP_PORT' < /app/nginx.conf > /etc/nginx/nginx.conf
-nginx
-while /bin/true; do
- sleep 50
-done
diff --git a/example/trivial/Dockerfile b/example/trivial/zipkin/Dockerfile
similarity index 72%
rename from example/trivial/Dockerfile
rename to example/trivial/zipkin/Dockerfile
index 4fa71c86..0aa55322 100644
--- a/example/trivial/Dockerfile
+++ b/example/trivial/zipkin/Dockerfile
@@ -1,4 +1,4 @@
-FROM rnburn/nginx-opentracing
+FROM ubuntu:17.10
WORKDIR /app
ADD . /app
@@ -7,11 +7,12 @@ RUN set -x \
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y \
golang \
+ ca-certificates \
git \
&& mkdir /go \
&& go get github.com/opentracing/opentracing-go \
&& go get github.com/openzipkin/zipkin-go-opentracing \
&& go build -o /app/server go/server.go
-EXPOSE 80
-CMD ["/app/start.sh"]
+EXPOSE 9001
+CMD ["/app/server", "-collector_host", "zipkin", "-collector_port", "9411"]
diff --git a/example/trivial/zipkin/README.md b/example/trivial/zipkin/README.md
new file mode 100644
index 00000000..f1da1ac4
--- /dev/null
+++ b/example/trivial/zipkin/README.md
@@ -0,0 +1,8 @@
+A minimal OpenTracing example demonstrating usage of the nginx-opentracing
+docker image with Zipkin. It features Nginx as a reverse-proxy in front a Go
+server. Use these commands to run:
+```bash
+docker-compose up
+curl localhost:8080
+```
+Visit http://localhost:9411 to view the traces in Zipkin.
diff --git a/example/trivial/zipkin/docker-compose.yaml b/example/trivial/zipkin/docker-compose.yaml
new file mode 100644
index 00000000..11590a4d
--- /dev/null
+++ b/example/trivial/zipkin/docker-compose.yaml
@@ -0,0 +1,47 @@
+version: '2'
+services:
+
+ nginx:
+ image: opentracing/nginx-opentracing
+ networks:
+ trivial_example:
+ aliases:
+ - nginx
+ volumes:
+ - ./nginx.conf:/etc/nginx/nginx.conf
+ - ./zipkin-config.json:/etc/zipkin-config.json
+ expose:
+ - "8080"
+ ports:
+ - "8080:8080"
+
+ app-service:
+ build:
+ context: .
+ dockerfile: ./Dockerfile
+ networks:
+ trivial_example:
+ aliases:
+ - app-service
+ expose:
+ - "9001"
+ ports:
+ - "9001:9001"
+ command:
+ - /app/server
+ - -collector_host
+ - zipkin
+
+ zipkin:
+ image: openzipkin/zipkin
+ networks:
+ trivial_example:
+ aliases:
+ - zipkin
+ expose:
+ - "9411"
+ ports:
+ - "9411:9411"
+
+networks:
+ trivial_example: {}
diff --git a/example/trivial/go/server.go b/example/trivial/zipkin/go/server.go
similarity index 94%
rename from example/trivial/go/server.go
rename to example/trivial/zipkin/go/server.go
index 26c8ca63..7bdef0d7 100644
--- a/example/trivial/go/server.go
+++ b/example/trivial/zipkin/go/server.go
@@ -21,6 +21,9 @@ var collectorHost = flag.String("collector_host", "localhost", "Host for Zipkin
var collectorPort = flag.String("collector_port", "9411", "Port for Zipkin Collector")
func handler(w http.ResponseWriter, r *http.Request) {
+ for k, v := range r.Header {
+ fmt.Fprintf(w, "Header field %q, Value %q\n", k, v)
+ }
wireContext, _ := opentracing.GlobalTracer().Extract(
opentracing.HTTPHeaders,
opentracing.HTTPHeadersCarrier(r.Header))
diff --git a/example/trivial/zipkin/nginx.conf b/example/trivial/zipkin/nginx.conf
new file mode 100644
index 00000000..11e377d2
--- /dev/null
+++ b/example/trivial/zipkin/nginx.conf
@@ -0,0 +1,24 @@
+load_module modules/ngx_http_opentracing_module.so;
+
+events {}
+
+http {
+ opentracing on;
+
+ opentracing_load_tracer /usr/local/lib/libzipkin_opentracing_plugin.so /etc/zipkin-config.json;
+ upstream backend {
+ server app-service:9001;
+ }
+
+ server {
+ error_log /var/log/nginx/debug.log debug;
+ listen 8080;
+ server_name localhost;
+
+ location = / {
+ opentracing_trace_locations off;
+ proxy_pass http://backend;
+ opentracing_propagate_context;
+ }
+ }
+}
diff --git a/example/trivial/zipkin/zipkin-config.json b/example/trivial/zipkin/zipkin-config.json
new file mode 100644
index 00000000..ffe14cc4
--- /dev/null
+++ b/example/trivial/zipkin/zipkin-config.json
@@ -0,0 +1,4 @@
+{
+ "service_name": "nginx",
+ "collector_host": "zipkin"
+}
diff --git a/example/zoo/Dockerfile b/example/zoo/Dockerfile
index 0eae320b..4508bf11 100644
--- a/example/zoo/Dockerfile
+++ b/example/zoo/Dockerfile
@@ -1,4 +1,4 @@
-FROM rnburn/nginx-opentracing
+FROM ubuntu:17.10
WORKDIR /app
ADD . /app
@@ -8,10 +8,12 @@ RUN set -x \
&& apt-get install --no-install-recommends --no-install-suggests -y \
python \
curl \
+ ca-certificates \
gnupg2 \
+ build-essential \
&& mkdir /node-latest-install \
&& cd /node-latest-install \
- && curl -sL https://deb.nodesource.com/setup_7.x -o nodesource_setup.sh \
+ && curl -sL https://deb.nodesource.com/setup_8.x -o nodesource_setup.sh \
&& bash nodesource_setup.sh \
&& apt-get install --no-install-recommends --no-install-suggests -y \
nodejs \
@@ -25,4 +27,4 @@ RUN set -x \
EXPOSE 80
-CMD ["/app/start.sh"]
+CMD ["/app/start-backend.sh"]
diff --git a/example/zoo/docker-compose.yaml b/example/zoo/docker-compose.yaml
new file mode 100644
index 00000000..7914b10f
--- /dev/null
+++ b/example/zoo/docker-compose.yaml
@@ -0,0 +1,53 @@
+version: '2'
+services:
+
+ nginx:
+ image: opentracing/nginx-opentracing
+ networks:
+ zoonet:
+ aliases:
+ - nginx
+ volumes:
+ - ./start-nginx.sh:/start-nginx.sh
+ - ./nginx.conf:/etc/nginx/nginx.conf
+ - ./lightstep-config.json.in:/tmp/lightstep-config.json.in
+ - ./www:/app/www
+ - image-volume:/app/data/images
+ - tmp-volume:/tmp
+ environment:
+ - LIGHTSTEP_ACCESS_TOKEN=${LIGHTSTEP_ACCESS_TOKEN}
+ expose:
+ - "8080"
+ ports:
+ - "8080:8080"
+ entrypoint: ./start-nginx.sh
+
+ backend:
+ build:
+ context: .
+ dockerfile: ./Dockerfile
+ environment:
+ - LIGHTSTEP_ACCESS_TOKEN=${LIGHTSTEP_ACCESS_TOKEN}
+ networks:
+ zoonet:
+ aliases:
+ - backend
+ volumes:
+ - image-volume:/app/data/images
+ - tmp-volume:/tmp
+ expose:
+ - "3001"
+ - "3002"
+ - "3003"
+ ports:
+ - "3001:3001"
+ - "3002:3002"
+ - "3003:3003"
+ entrypoint: ./start-backend.sh
+
+volumes:
+ image-volume:
+ tmp-volume:
+
+networks:
+ zoonet: {}
diff --git a/example/zoo/lightstep-config.json.in b/example/zoo/lightstep-config.json.in
new file mode 100644
index 00000000..e2af759e
--- /dev/null
+++ b/example/zoo/lightstep-config.json.in
@@ -0,0 +1,4 @@
+{
+ "access_token": "$LIGHTSTEP_ACCESS_TOKEN",
+ "component_name": "nginx"
+}
diff --git a/example/zoo/nginx.conf b/example/zoo/nginx.conf
index 4e347afd..d3acd95b 100644
--- a/example/zoo/nginx.conf
+++ b/example/zoo/nginx.conf
@@ -1,27 +1,27 @@
load_module modules/ngx_http_opentracing_module.so;
-load_module modules/ngx_http_lightstep_module.so;
events {}
http {
- lightstep_access_token $LIGHTSTEP_ACCESS_TOKEN;
- lightstep_component_name zoo;
- proxy_pass_request_headers on;
opentracing on;
+ opentracing_load_tracer /usr/local/lib/liblightstep_tracer_plugin.so /etc/lightstep-config.json;
+
upstream backend {
- server localhost:3001;
- server localhost:3002;
- server localhost:3003;
+ server backend:3001;
+ server backend:3002;
+ server backend:3003;
}
server {
- listen 80;
+ error_log /var/log/nginx/debug.log debug;
+ listen 8080;
server_name localhost;
location = / {
proxy_pass http://backend;
opentracing_tag nginx.upstream_addr $upstream_addr;
+ opentracing_propagate_context;
}
location = /animal {
@@ -29,6 +29,7 @@ http {
proxy_pass http://backend;
opentracing_tag nginx.upstream_addr $upstream_addr;
+ opentracing_propagate_context;
}
location = /upload/animal {
@@ -47,13 +48,13 @@ http {
client_body_buffer_size 128K;
client_max_body_size 1000M;
- proxy_pass_request_headers on;
proxy_set_header admit-profile-pic $request_body_file;
proxy_set_body off;
proxy_redirect off;
proxy_pass http://backend;
proxy_intercept_errors on;
+ opentracing_propagate_context;
error_page 301 302 303 =200 /;
}
diff --git a/example/zoo/start.sh b/example/zoo/start-backend.sh
similarity index 73%
rename from example/zoo/start.sh
rename to example/zoo/start-backend.sh
index 8a986752..a3c1c4d8 100755
--- a/example/zoo/start.sh
+++ b/example/zoo/start-backend.sh
@@ -2,8 +2,6 @@
DATA_ROOT=/app/data
IMG_ROOT=$DATA_ROOT/images
-mkdir -p $IMG_ROOT
-
node node/setup.js --data_root $DATA_ROOT
for i in {1..3}; do
@@ -11,8 +9,6 @@ for i in {1..3}; do
node node/server.js --port $port --data_root $DATA_ROOT --access_token $LIGHTSTEP_ACCESS_TOKEN&
done
-envsubst '\$LIGHTSTEP_ACCESS_TOKEN' < /app/nginx.conf > /etc/nginx/nginx.conf
-nginx
while /bin/true; do
sleep 50
done
diff --git a/example/zoo/start-nginx.sh b/example/zoo/start-nginx.sh
new file mode 100755
index 00000000..ccb97ced
--- /dev/null
+++ b/example/zoo/start-nginx.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+envsubst '\$LIGHTSTEP_ACCESS_TOKEN' < /tmp/lightstep-config.json.in > /etc/lightstep-config.json
+nginx-debug -g "daemon off;"
diff --git a/jaeger/config b/jaeger/config
deleted file mode 100644
index f447698e..00000000
--- a/jaeger/config
+++ /dev/null
@@ -1,17 +0,0 @@
-ngx_addon_name=ngx_http_jaeger_module
-ngx_module_type=HTTP
-ngx_module_name=$ngx_addon_name
-ngx_module_incs=
-ngx_module_deps=
-ngx_module_srcs=" \
- $ngx_addon_dir/src/ngx_http_jaeger_module.cpp \
-"
-ngx_module_libs=" \
- -lthrift \
- -lopentracing \
- -ljaegertracing \
-"
-
-. auto/module
-
-JAEGER_NGX_SRCS="$ngx_module_srcs"
diff --git a/jaeger/config.make b/jaeger/config.make
deleted file mode 100644
index 38909ab1..00000000
--- a/jaeger/config.make
+++ /dev/null
@@ -1,7 +0,0 @@
-# Since nginx build system doesn't normally do C++, there is no CXXFLAGS for us
-# to touch, and compilers are understandably unhappy with --std=c++11 on C
-# files. Hence, we hack the makefile to add it for just our sources.
-for src_file in $JAEGER_NGX_SRCS; do
- obj_file="$NGX_OBJS/addon/src/`basename $src_file .cpp`.o"
- echo "$obj_file : CFLAGS += --std=c++11" >> $NGX_MAKEFILE
-done
diff --git a/jaeger/doc/Directives.md b/jaeger/doc/Directives.md
deleted file mode 100644
index 4ec97a88..00000000
--- a/jaeger/doc/Directives.md
+++ /dev/null
@@ -1,139 +0,0 @@
-### `jaeger_service_name`
-
-- **syntax** `jaeger_service_name `
-- **context**: `http`
-
-Specifies the service name to use for traces.
-
-### `jaeger_disabled`
-
-- **syntax** `jaeger_disabled on|off`
-- **default**: `off`
-- **context**: `http`
-
-Specifies whether or not to disable tracing.
-
-### `jaeger_sampler_type`
-
-- **syntax** `jaeger_sampler_type `
-- **default**: `remote`
-- **context**: `http`
-
-Specifies the sampler to be used when sampling traces. The available samplers
-are: `const`, `probabilistic`, `ratelimiting`, `remote`. `const` sampling always
-sample or always ignore. `probabilistic` sampling will use a random number to
-check whether or not to sample the trace. `ratelimiting` sampling caps the
-number of traces at a given number per second. `remote` sampling allows the
-Jaeger backend to customize the sampling strategy based on throughput. The
-recommended default is `remote`.
-
-### `jaeger_sampler_param`
-
-- **syntax** `jaeger_sampler_param `
-- **default**: `0.001`
-- **context**: `http`
-
-Specifies the argument to be passed to the sampler constructor. Must be a
-number. For `const` this should be `0` to never sample and `1` to always sample.
-For `probabilistic`, this should be a number representing the percent to sample
-(i.e. 0.001 = 0.1%). For `ratelimiting` this should be the maximum number of
-traces to sample per second. For `remote` this represents the upfront
-probabilistic sampling rate to use for traces before determining throughput on
-the backend (i.e. 0.001 = 0.1%, as above).
-
-### `jaeger_sampling_server_url`
-
-- **syntax** `jaeger_sampling_server_url `
-- **default**: `http://127.0.0.1:5778`
-- **context**: `http`
-
-Specifies the URL to use to request sampling strategy from Jaeger agent.
-
-### `jaeger_sampler_max_operations`
-
-- **syntax** `jaeger_sampler_max_operations `
-- **default**: `2000`
-- **context**: `http`
-
-Specifies the maximum number of operations that the sampler will keep track of.
-
-### `jaeger_sampling_refresh_interval_seconds`
-
-- **syntax** `jaeger_sampling_refresh_interval_seconds `
-- **default**: `60`
-- **context**: `http`
-
-Specifies the interval the remote sampler should wait before polling the Jaeger
-agent again for sampling strategy information.
-
-### `jaeger_reporter_queue_size`
-
-- **syntax** `jaeger_reporter_queue_size `
-- **default**: `100`
-- **context**: `http`
-
-Specifies the maximum number of spans to maintain in memory awaiting submission
-to Jaeger agent before dropping new spans.
-
-### `jaeger_reporter_buffer_flush_interval_seconds`
-
-- **syntax** `jaeger_reporter_buffer_flush_interval_seconds `
-- **default**: `10`
-- **context**: `http`
-
-Specifies the maximum number of seconds to wait before forcing a flush of spans
-to Jaeger agent, even if size does not warrant flush.
-
-### `jaeger_reporter_log_spans`
-
-- **syntax** `jaeger_reporter_log_spans `
-- **default**: `false`
-- **context**: `http`
-
-Specifies whether or not the reporter should log the spans it reports.
-
-### `jaeger_reporter_local_agent_host_port`
-
-- **syntax** `jaeger_reporter_local_agent_host_port `
-- **default**: `127.0.0.1:6831`
-- **context**: `http`
-
-Specifies the host and port of Jaeger agent where reporter should submit span
-data.
-
-### `jaeger_debug_header`
-
-- **syntax** `jaeger_debug_header `
-- **default**: `jaeger-debug-id`
-- **context**: `http`
-
-Specifies the name of HTTP header or a TextMap carrier key which, if found in
-the carrier, forces the trace to be sampled as "debug" trace.
-
-### `jaeger_baggage_header`
-
-- **syntax** `jaeger_baggage_header `
-- **default**: `jaeger-baggage`
-- **context**: `http`
-
-Specifies the name of the HTTP header that is used to submit baggage.
-It differs from `jaeger_trace_baggage_header_prefix` in that it can be used only
-in cases where a root span does not exist.
-
-### `jaeger_trace_context_header_name`
-
-- **syntax** `jaeger_trace_context_header_name `
-- **default**: `uber-trace-id`
-- **context**: `http`
-
-Specifies the HTTP header name used to propagate tracing context. This must be
-lowercase to avoid mismatches when decoding incoming headers.
-
-### `jaeger_trace_baggage_header_prefix`
-
-- **syntax** `jaeger_trace_baggage_header_prefix `
-- **default**: `uberctx-`
-- **context**: `http`
-
-Specifies the prefix for HTTP headers used to propagate baggage. This must be
-lowercase to avoid mismatches when decoding incoming headers.
diff --git a/jaeger/src/ngx_http_jaeger_module.cpp b/jaeger/src/ngx_http_jaeger_module.cpp
deleted file mode 100644
index 1bc885c6..00000000
--- a/jaeger/src/ngx_http_jaeger_module.cpp
+++ /dev/null
@@ -1,208 +0,0 @@
-extern "C" {
-
-#include
-#include
-#include
-#include
-
-} // extern "C"
-
-#include
-
-extern ngx_module_t ngx_http_jaeger_module;
-
-namespace {
-
-struct Config {
- ngx_str_t serviceName;
- ngx_flag_t disabled = NGX_CONF_UNSET;
- // samplers::Config
- ngx_str_t samplerType;
- ngx_str_t samplerParam;
- ngx_str_t samplingServerURL;
- ngx_uint_t samplerMaxOperations = NGX_CONF_UNSET_UINT;
- ngx_uint_t samplingRefreshIntervalSeconds = NGX_CONF_UNSET_UINT;
- // reporters::Config
- ngx_uint_t reporterQueueSize = NGX_CONF_UNSET_UINT;
- ngx_uint_t reporterBufferFlushIntervalSeconds = NGX_CONF_UNSET_UINT;
- ngx_flag_t reporterLogSpans = NGX_CONF_UNSET;
- ngx_str_t reporterLocalAgentHostPort;
- // propagation::HeadersConfig
- ngx_str_t jaegerDebugHeader;
- ngx_str_t jaegerBaggageHeader;
- ngx_str_t traceContextHeaderName;
- ngx_str_t traceBaggageHeaderPrefix;
-};
-
-inline std::string makeStr(const ngx_str_t& str) {
- return std::string(str.data, str.data + str.len);
-}
-
-inline double makeDouble(const ngx_str_t& str) {
- std::istringstream iss(makeStr(str));
- double result = 0;
- if (iss >> result) {
- return result;
- }
- return 0;
-}
-
-ngx_int_t moduleInit(ngx_conf_t* cf) {
- auto* rawConfig = static_cast(
- ngx_http_conf_get_module_main_conf(cf, ngx_http_jaeger_module));
- if (rawConfig->serviceName.len <= 0) {
- ngx_log_error(NGX_LOG_ERR, cf->log, 0,
- "`jaeger_service_name` must be specified");
- return NGX_ERROR;
- }
- return NGX_OK;
-}
-
-ngx_int_t initWorker(ngx_cycle_t* cycle) {
- auto rawConfig = static_cast(
- ngx_http_cycle_get_module_main_conf(cycle, ngx_http_jaeger_module));
- try {
- // Apply defaults.
- if (rawConfig->disabled == NGX_CONF_UNSET) rawConfig->disabled = false;
- // samplers::Config
- if (!rawConfig->samplerType.data)
- rawConfig->samplerType = ngx_string("remote");
- if (!rawConfig->samplerParam.data)
- rawConfig->samplerParam = ngx_string("0.001");
- if (!rawConfig->samplingServerURL.data)
- rawConfig->samplingServerURL = ngx_string("http://127.0.0.1:5778");
- if (rawConfig->samplerMaxOperations == NGX_CONF_UNSET_UINT)
- rawConfig->samplerMaxOperations = 2000;
- if (rawConfig->samplingRefreshIntervalSeconds == NGX_CONF_UNSET_UINT)
- rawConfig->samplingRefreshIntervalSeconds = 60;
- // reporters::Config
- if (rawConfig->reporterQueueSize == NGX_CONF_UNSET_UINT)
- rawConfig->reporterQueueSize = 100;
- if (rawConfig->reporterBufferFlushIntervalSeconds == NGX_CONF_UNSET_UINT)
- rawConfig->reporterBufferFlushIntervalSeconds = 10;
- if (rawConfig->reporterLogSpans == NGX_CONF_UNSET)
- rawConfig->reporterLogSpans = false;
- if (!rawConfig->reporterLocalAgentHostPort.data)
- rawConfig->reporterLocalAgentHostPort = ngx_string("127.0.0.1:6831");
- // propagation::HeadersConfig
- if (!rawConfig->jaegerDebugHeader.data)
- rawConfig->jaegerDebugHeader = ngx_string("jaeger-debug-id");
- if (!rawConfig->jaegerBaggageHeader.data)
- rawConfig->jaegerBaggageHeader = ngx_string("jaeger-baggage");
- if (!rawConfig->traceContextHeaderName.data)
- rawConfig->traceContextHeaderName = ngx_string("uber-trace-id");
- if (!rawConfig->traceBaggageHeaderPrefix.data)
- rawConfig->traceBaggageHeaderPrefix = ngx_string("uberctx-");
-
- const jaegertracing::Config config(
- rawConfig->disabled,
- jaegertracing::samplers::Config(
- makeStr(rawConfig->samplerType),
- makeDouble(rawConfig->samplerParam),
- makeStr(rawConfig->samplingServerURL),
- rawConfig->samplerMaxOperations,
- std::chrono::seconds(rawConfig->samplingRefreshIntervalSeconds)),
- jaegertracing::reporters::Config(
- rawConfig->reporterQueueSize,
- std::chrono::seconds(rawConfig->reporterBufferFlushIntervalSeconds),
- rawConfig->reporterLogSpans,
- makeStr(rawConfig->reporterLocalAgentHostPort)),
- jaegertracing::propagation::HeadersConfig(
- makeStr(rawConfig->jaegerDebugHeader),
- makeStr(rawConfig->jaegerBaggageHeader),
- makeStr(rawConfig->traceContextHeaderName),
- makeStr(rawConfig->traceBaggageHeaderPrefix)),
- jaegertracing::baggage::RestrictionsConfig());
- auto tracer =
- jaegertracing::Tracer::make(makeStr(rawConfig->serviceName), config);
- opentracing::Tracer::InitGlobal(tracer);
- } catch (const std::exception& e) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "Failed to create Jaeger tracer: %s", e.what());
- }
- return NGX_OK;
-}
-
-void* createJaegerMainConfig(ngx_conf_t* conf) {
- auto* mainConfig =
- static_cast(ngx_pcalloc(conf->pool, sizeof(Config)));
- if (!mainConfig) {
- return nullptr;
- }
- // Default initialize members.
- *mainConfig = Config();
- return mainConfig;
-}
-
-ngx_http_module_t moduleCtx = {
- nullptr, // preconfiguration
- &moduleInit, // postconfiguration
- &createJaegerMainConfig, // create main configuration
- nullptr, // init main configuration
- nullptr, // create server configuration
- nullptr, // merge server configuration
- nullptr, // create location configuration
- nullptr // merge location configuration
-};
-
-struct JaegerCommands {
- JaegerCommands() {
-#define DEFINE_COMMAND(commandName, memberName, ngxType) \
- { \
- ngx_command_t command( \
- {ngx_string(#commandName), NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1, \
- ngx_conf_set_##ngxType##_slot, NGX_HTTP_MAIN_CONF_OFFSET, \
- offsetof(Config, memberName), nullptr}); \
- _commands.emplace_back(std::move(command)); \
- }
-
- DEFINE_COMMAND(jaeger_service_name, serviceName, str);
- DEFINE_COMMAND(jaeger_disabled, disabled, flag);
- // samplers::Config
- DEFINE_COMMAND(jaeger_sampler_type, samplerType, str);
- DEFINE_COMMAND(jaeger_sampler_param, samplerParam, str);
- DEFINE_COMMAND(jaeger_sampling_server_url, samplingServerURL, str);
- DEFINE_COMMAND(jaeger_sampler_max_operations, samplerMaxOperations, num);
- DEFINE_COMMAND(jaeger_sampling_refresh_interval_seconds,
- samplingRefreshIntervalSeconds, num);
- // reporters::Config
- DEFINE_COMMAND(jaeger_reporter_queue_size, reporterQueueSize, num);
- DEFINE_COMMAND(jaeger_reporter_buffer_flush_interval_seconds,
- reporterBufferFlushIntervalSeconds, num)
- DEFINE_COMMAND(jaeger_reporter_log_spans, reporterLogSpans, flag);
- DEFINE_COMMAND(jaeger_reporter_local_agent_host_port,
- reporterLocalAgentHostPort, str);
- // propagation::HeadersConfig
- DEFINE_COMMAND(jaeger_debug_header, jaegerDebugHeader, str);
- DEFINE_COMMAND(jaeger_baggage_header, jaegerBaggageHeader, str);
- DEFINE_COMMAND(jaeger_trace_context_header_name, traceContextHeaderName,
- str);
- DEFINE_COMMAND(jaeger_trace_baggage_header_prefix, traceBaggageHeaderPrefix,
- str);
- _commands.push_back(ngx_null_command);
-
-#undef DEFINE_COMMAND
- }
-
- std::vector _commands;
-};
-
-ngx_command_t* jaegerCommands() {
- static JaegerCommands commands;
- return &commands._commands[0];
-}
-
-} // anonymous namespace
-
-ngx_module_t ngx_http_jaeger_module = {NGX_MODULE_V1,
- &moduleCtx, // module context
- jaegerCommands(), // module directives
- NGX_HTTP_MODULE, // module type
- nullptr, // init master
- nullptr, // init module
- &initWorker, // init process
- nullptr, // init thread
- nullptr, // exit thread
- nullptr, // exit process
- nullptr, // exit master
- NGX_MODULE_V1_PADDING};
diff --git a/lightstep/config b/lightstep/config
deleted file mode 100644
index 4774a6b7..00000000
--- a/lightstep/config
+++ /dev/null
@@ -1,19 +0,0 @@
-ngx_addon_name=ngx_http_lightstep_module
-ngx_module_type=HTTP
-ngx_module_name=$ngx_addon_name
-ngx_module_incs=
-ngx_module_deps=
-ngx_module_srcs=" \
- $ngx_addon_dir/src/ngx_http_lightstep_module.cpp \
-"
-ngx_module_libs=" \
- -lgrpc++ \
- -lgrpc \
- -lprotobuf \
- -lopentracing \
- -llightstep_tracer \
-"
-
-. auto/module
-
-LIGHTSTEP_NGX_SRCS="$ngx_module_srcs"
diff --git a/lightstep/config.make b/lightstep/config.make
deleted file mode 100644
index 625fe712..00000000
--- a/lightstep/config.make
+++ /dev/null
@@ -1,7 +0,0 @@
-# Since nginx build system doesn't normally do C++, there is no CXXFLAGS for us
-# to touch, and compilers are understandably unhappy with --std=c++11 on C
-# files. Hence, we hack the makefile to add it for just our sources.
-for src_file in $LIGHTSTEP_NGX_SRCS; do
- obj_file="$NGX_OBJS/addon/src/`basename $src_file .cpp`.o"
- echo "$obj_file : CFLAGS += --std=c++11" >> $NGX_MAKEFILE
-done
diff --git a/lightstep/doc/Directives.md b/lightstep/doc/Directives.md
deleted file mode 100644
index 9393b601..00000000
--- a/lightstep/doc/Directives.md
+++ /dev/null
@@ -1,38 +0,0 @@
-### `lightstep_access_token`
-
-- **syntax** `lightstep_access_token `
-- **context**: `http`
-
-Specifies the access token to use when uploading traces.
-
-### `lightstep_component_name`
-
-- **syntax** `lightstep_component_name `
-- **default**: `nginx`
-- **context**: `http`
-
-Specifies the component name to use for any traces created.
-
-### `lightstep_collector_host`
-
-- **syntax** `lightstep_collector_host `
-- **default**: `collector-grpc.lightstep.com`
-- **context**: `http`
-
-Specifies the host to use when uploading traces.
-
-### `lightstep_collector_plaintext`
-
-- **syntax** `lightstep_collector_plaintext on|off`
-- **default**: `off`
-- **context**: `http`
-
-Specifies whether to encrypt when uploading traces.
-
-### `lightstep_collector_port`
-
-- **syntax** `lightstep_collector_port `
-- **default**: `443`
-- **context**: `http`
-
-Specifies the port to use when uploading traces.
diff --git a/lightstep/src/ngx_http_lightstep_module.cpp b/lightstep/src/ngx_http_lightstep_module.cpp
deleted file mode 100644
index 2d26b1a9..00000000
--- a/lightstep/src/ngx_http_lightstep_module.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-#include
-#include
-#include
-
-extern "C" {
-#include
-#include
-#include
-#include
-
-extern ngx_module_t ngx_http_lightstep_module;
-}
-
-//------------------------------------------------------------------------------
-// to_string
-//------------------------------------------------------------------------------
-static inline std::string to_string(const ngx_str_t &ngx_str) {
- return {reinterpret_cast(ngx_str.data), ngx_str.len};
-}
-
-//------------------------------------------------------------------------------
-// lightstep_main_conf_t
-//------------------------------------------------------------------------------
-struct lightstep_main_conf_t {
- ngx_str_t access_token;
- ngx_str_t component_name;
- ngx_str_t collector_host;
- ngx_flag_t collector_plaintext = NGX_CONF_UNSET;
- ngx_str_t collector_port;
-};
-
-//------------------------------------------------------------------------------
-// lightstep_module_init
-//------------------------------------------------------------------------------
-static ngx_int_t lightstep_module_init(ngx_conf_t *cf) {
- auto main_conf = static_cast(
- ngx_http_conf_get_module_main_conf(cf, ngx_http_lightstep_module));
- // Validate the configuration
- if (!main_conf->access_token.data) {
- ngx_log_error(NGX_LOG_ERR, cf->log, 0,
- "`lighstep_access_token` must be specified");
- return NGX_ERROR;
- }
- return NGX_OK;
-}
-
-//------------------------------------------------------------------------------
-// lightstep_init_worker
-//------------------------------------------------------------------------------
-static ngx_int_t lightstep_init_worker(ngx_cycle_t *cycle) {
- auto main_conf = static_cast(
- ngx_http_cycle_get_module_main_conf(cycle, ngx_http_lightstep_module));
- lightstep::LightStepTracerOptions tracer_options;
- if (!main_conf->access_token.data) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "`lighstep_access_token` must be specified");
- return NGX_ERROR;
- }
- tracer_options.access_token = to_string(main_conf->access_token);
- if (main_conf->collector_host.data)
- tracer_options.collector_host = to_string(main_conf->collector_host);
- if (main_conf->collector_port.data)
- // TODO: Check for errors here?
- tracer_options.collector_port =
- std::stoi(to_string(main_conf->collector_port));
- if (main_conf->collector_plaintext != NGX_CONF_UNSET)
- tracer_options.collector_plaintext = main_conf->collector_plaintext;
- if (main_conf->component_name.data)
- tracer_options.component_name = to_string(main_conf->component_name);
- else
- tracer_options.component_name = "nginx";
- auto tracer = lightstep::MakeLightStepTracer(std::move(tracer_options));
- if (!tracer) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "Failed to create LightStep tracer");
- return NGX_OK;
- }
- opentracing::Tracer::InitGlobal(std::move(tracer));
- return NGX_OK;
-}
-
-//------------------------------------------------------------------------------
-// create_lightstep_main_conf
-//------------------------------------------------------------------------------
-static void *create_lightstep_main_conf(ngx_conf_t *conf) {
- auto main_conf = static_cast(
- ngx_pcalloc(conf->pool, sizeof(lightstep_main_conf_t)));
- // Default initialize members.
- *main_conf = lightstep_main_conf_t();
- if (!main_conf) return nullptr;
- return main_conf;
-}
-
-//------------------------------------------------------------------------------
-// lightstep_module_ctx
-//------------------------------------------------------------------------------
-static ngx_http_module_t lightstep_module_ctx = {
- nullptr, /* preconfiguration */
- lightstep_module_init, /* postconfiguration */
- create_lightstep_main_conf, /* create main configuration */
- nullptr, /* init main configuration */
- nullptr, /* create server configuration */
- nullptr, /* merge server configuration */
- nullptr, /* create location configuration */
- nullptr /* merge location configuration */
-};
-
-//------------------------------------------------------------------------------
-// lightstep_commands
-//------------------------------------------------------------------------------
-static ngx_command_t lightstep_commands[] = {
- {ngx_string("lightstep_access_token"), NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1,
- ngx_conf_set_str_slot, NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(lightstep_main_conf_t, access_token), nullptr},
- {ngx_string("lightstep_component_name"),
- NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1, ngx_conf_set_str_slot,
- NGX_HTTP_MAIN_CONF_OFFSET, offsetof(lightstep_main_conf_t, component_name),
- nullptr},
- {ngx_string("lightstep_collector_host"),
- NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1, ngx_conf_set_str_slot,
- NGX_HTTP_MAIN_CONF_OFFSET, offsetof(lightstep_main_conf_t, collector_host),
- nullptr},
- {ngx_string("lightstep_collector_plaintext"),
- NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1, ngx_conf_set_flag_slot,
- NGX_HTTP_MAIN_CONF_OFFSET,
- offsetof(lightstep_main_conf_t, collector_plaintext), nullptr},
- {ngx_string("lightstep_collector_port"),
- NGX_HTTP_MAIN_CONF | NGX_CONF_TAKE1, ngx_conf_set_str_slot,
- NGX_HTTP_MAIN_CONF_OFFSET, offsetof(lightstep_main_conf_t, collector_port),
- nullptr}};
-
-//------------------------------------------------------------------------------
-// ngx_http_lightstep_module
-//------------------------------------------------------------------------------
-ngx_module_t ngx_http_lightstep_module = {
- NGX_MODULE_V1,
- &lightstep_module_ctx, /* module context */
- lightstep_commands, /* module directives */
- NGX_HTTP_MODULE, /* module type */
- nullptr, /* init master */
- nullptr, /* init module */
- lightstep_init_worker, /* init process */
- nullptr, /* init thread */
- nullptr, /* exit thread */
- nullptr, /* exit process */
- nullptr, /* exit master */
- NGX_MODULE_V1_PADDING};
diff --git a/opentracing/config b/opentracing/config
index cebd9b99..d161bcd1 100644
--- a/opentracing/config
+++ b/opentracing/config
@@ -4,18 +4,28 @@ ngx_module_name=$ngx_addon_name
ngx_module_incs=
ngx_module_deps=" \
$ngx_addon_dir/src/opentracing_conf.h \
+ $ngx_addon_dir/src/opentracing_directive.h \
+ $ngx_addon_dir/src/opentracing_variable.h \
$ngx_addon_dir/src/opentracing_handler.h \
- $ngx_addon_dir/src/opentracing_request_instrumentor.h \
+ $ngx_addon_dir/src/load_tracer.h \
+ $ngx_addon_dir/src/opentracing_context.h \
+ $ngx_addon_dir/src/opentracing_conf_handler.h \
$ngx_addon_dir/src/ngx_script.h \
+ $ngx_addon_dir/src/span_context_querier.h \
$ngx_addon_dir/src/utility.h \
"
ngx_module_srcs=" \
$ngx_addon_dir/src/ngx_http_opentracing_module.cpp \
$ngx_addon_dir/src/ngx_script.cpp \
$ngx_addon_dir/src/extract_span_context.cpp \
- $ngx_addon_dir/src/inject_span_context.cpp \
+ $ngx_addon_dir/src/discover_span_context_keys.cpp \
+ $ngx_addon_dir/src/load_tracer.cpp \
+ $ngx_addon_dir/src/opentracing_directive.cpp \
+ $ngx_addon_dir/src/opentracing_variable.cpp \
$ngx_addon_dir/src/opentracing_handler.cpp \
- $ngx_addon_dir/src/opentracing_request_instrumentor.cpp \
+ $ngx_addon_dir/src/opentracing_conf_handler.cpp \
+ $ngx_addon_dir/src/opentracing_context.cpp \
+ $ngx_addon_dir/src/span_context_querier.cpp \
$ngx_addon_dir/src/utility.cpp \
"
ngx_module_libs="-lstdc++ -lopentracing"
diff --git a/opentracing/src/discover_span_context_keys.cpp b/opentracing/src/discover_span_context_keys.cpp
new file mode 100644
index 00000000..f207c721
--- /dev/null
+++ b/opentracing/src/discover_span_context_keys.cpp
@@ -0,0 +1,85 @@
+#include "discover_span_context_keys.h"
+#include "load_tracer.h"
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// HeaderKeyWriter
+//------------------------------------------------------------------------------
+namespace {
+class HeaderKeyWriter : public opentracing::HTTPHeadersWriter {
+ public:
+ HeaderKeyWriter(ngx_pool_t* pool, std::vector& keys)
+ : pool_{pool}, keys_{keys} {}
+
+ opentracing::expected Set(
+ opentracing::string_view key,
+ opentracing::string_view value) const override {
+ auto data = static_cast(ngx_palloc(pool_, key.size()));
+ if (data == nullptr) {
+ throw std::bad_alloc{};
+ }
+ std::copy_n(key.data(), key.size(), data);
+
+ keys_.emplace_back(data, key.size());
+
+ return {};
+ }
+
+ private:
+ ngx_pool_t* pool_;
+ std::vector& keys_;
+};
+} // namespace
+
+//------------------------------------------------------------------------------
+// discover_span_context_keys
+//------------------------------------------------------------------------------
+// Loads the vendor tracing library and creates a dummy span so as to obtain
+// a list of the keys used for span context propagation. This is necessary to
+// make context propagation work for requests proxied upstream.
+//
+// See propagate_opentracing_context, set_tracer.
+//
+// Note: Any keys that a tracer might use for propagation that aren't discovered
+// discovered here will get dropped during propagation.
+ngx_array_t* discover_span_context_keys(ngx_pool_t* pool, ngx_log_t* log,
+ const char* tracing_library,
+ const char* tracer_config_file) {
+ opentracing::DynamicTracingLibraryHandle handle;
+ std::shared_ptr tracer;
+ auto rcode =
+ load_tracer(log, tracing_library, tracer_config_file, handle, tracer);
+ if (rcode != NGX_OK) {
+ return nullptr;
+ }
+ auto span = tracer->StartSpan("dummySpan");
+ std::vector keys;
+ HeaderKeyWriter carrier_writer{pool, keys};
+ auto was_successful = tracer->Inject(span->context(), carrier_writer);
+ span->SetTag(opentracing::ext::sampling_priority, 0);
+ if (!was_successful) {
+ ngx_log_error(NGX_LOG_ERR, log, 0,
+ "failed to discover span context tags: %s",
+ was_successful.error().message().c_str());
+ return nullptr;
+ }
+ ngx_array_t* result =
+ ngx_array_create(pool, keys.size(), sizeof(opentracing::string_view));
+ if (result == nullptr) {
+ throw std::bad_alloc{};
+ }
+
+ for (auto key : keys) {
+ auto element =
+ static_cast(ngx_array_push(result));
+ *element = key;
+ }
+ return result;
+}
+} // namespace ngx_opentracing
diff --git a/opentracing/src/discover_span_context_keys.h b/opentracing/src/discover_span_context_keys.h
new file mode 100644
index 00000000..35bb8c15
--- /dev/null
+++ b/opentracing/src/discover_span_context_keys.h
@@ -0,0 +1,17 @@
+#pragma once
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// discover_span_context_keys
+//------------------------------------------------------------------------------
+ngx_array_t* discover_span_context_keys(ngx_pool_t* pool, ngx_log_t* log,
+ const char* tracing_library,
+ const char* tracer_config_file);
+} // namespace ngx_opentracing
diff --git a/opentracing/src/inject_span_context.cpp b/opentracing/src/inject_span_context.cpp
deleted file mode 100644
index 8c6136ca..00000000
--- a/opentracing/src/inject_span_context.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-#include
-#include
-#include
-#include "utility.h"
-using opentracing::expected;
-using opentracing::make_unexpected;
-using opentracing::string_view;
-
-extern "C" {
-#include
-#include
-#include
-#include
-}
-
-namespace ngx_opentracing {
-//------------------------------------------------------------------------------
-// insert_header
-//------------------------------------------------------------------------------
-static expected insert_header(ngx_http_request_t *request, ngx_str_t key,
- ngx_str_t value) {
- auto header = static_cast(
- ngx_list_push(&request->headers_in.headers));
- if (!header)
- return make_unexpected(std::make_error_code(std::errc::not_enough_memory));
- header->hash = 1;
- header->key = key;
- header->lowcase_key = key.data;
- header->value = value;
- return {};
-}
-
-//------------------------------------------------------------------------------
-// set_headers
-//------------------------------------------------------------------------------
-static expected set_headers(
- ngx_http_request_t *request,
- std::vector> &headers) {
- if (headers.empty()) return {};
-
- // If header keys are already in the request, overwrite the values instead of
- // inserting a new header.
- //
- // It may be possible in some cases to use nginx's hashes to look up the
- // entries faster, but then we'd have to handle the special case of when a
- // header element isn't hashed yet. Iterating over the header entries all the
- // time keeps things simple.
- for_each(
- request->headers_in.headers, [&](ngx_table_elt_t &header) {
- auto i = std::find_if(
- headers.begin(), headers.end(),
- [&](const std::pair &key_value) {
- const auto &key = key_value.first;
- return header.key.len == key.len &&
- ngx_strncmp(reinterpret_cast(header.lowcase_key),
- reinterpret_cast(key.data),
- key.len) == 0;
-
- });
- if (i == headers.end()) return;
- ngx_log_debug4(
- NGX_LOG_DEBUG_HTTP, request->connection->log, 0,
- "replacing opentracing header \"%V:%V\" with value \"%V\""
- " in request %p",
- &header.key, &header.value, &i->second, request);
- header.value = i->second;
- headers.erase(i);
- });
-
- // Any header left in `headers` doesn't already have a key in the request, so
- // create a new entry for it.
- for (const auto &key_value : headers) {
- ngx_log_debug3(NGX_LOG_DEBUG_HTTP, request->connection->log, 0,
- "adding opentracing header \"%V:%V\" in request %p",
- &key_value.first, &key_value.second, request);
- auto was_successful =
- insert_header(request, key_value.first, key_value.second);
- if (!was_successful) {
- ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
- "failed to insert header");
- return was_successful;
- }
- }
- return {};
-}
-
-//------------------------------------------------------------------------------
-// NgxHeaderCarrierWriter
-//------------------------------------------------------------------------------
-namespace {
-class NgxHeaderCarrierWriter : public opentracing::HTTPHeadersWriter {
- public:
- NgxHeaderCarrierWriter(ngx_http_request_t *request,
- std::vector> &headers)
- : request_{request}, headers_(headers) {}
-
- expected Set(string_view key, string_view value) const override {
- auto ngx_key = to_lower_ngx_str(request_->pool, key);
- if (!ngx_key.data) {
- ngx_log_error(NGX_LOG_ERR, request_->connection->log, 0,
- "failed to allocate header key");
- return make_unexpected(
- std::make_error_code(std::errc::not_enough_memory));
- }
- auto ngx_value = to_ngx_str(request_->pool, value);
- if (!ngx_value.data) {
- ngx_log_error(NGX_LOG_ERR, request_->connection->log, 0,
- "failed to allocate header value");
- return make_unexpected(
- std::make_error_code(std::errc::not_enough_memory));
- }
- headers_.emplace_back(ngx_key, ngx_value);
- return {};
- }
-
- private:
- ngx_http_request_t *request_;
- std::vector> &headers_;
-};
-} // namespace
-
-//------------------------------------------------------------------------------
-// inject_span_context
-//------------------------------------------------------------------------------
-void inject_span_context(const opentracing::Tracer &tracer,
- ngx_http_request_t *request,
- const opentracing::SpanContext &span_context) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, request->connection->log, 0,
- "injecting opentracing span context from request %p", request);
- std::vector> headers;
- auto carrier_writer = NgxHeaderCarrierWriter{request, headers};
- auto was_successful = tracer.Inject(span_context, carrier_writer);
- if (was_successful) was_successful = set_headers(request, headers);
- if (!was_successful)
- ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
- "Tracer.inject() failed for request %p: %s", request,
- was_successful.error().message().c_str());
-}
-} // namespace ngx_opentracing
diff --git a/opentracing/src/load_tracer.cpp b/opentracing/src/load_tracer.cpp
new file mode 100644
index 00000000..e872e1d6
--- /dev/null
+++ b/opentracing/src/load_tracer.cpp
@@ -0,0 +1,65 @@
+#include "load_tracer.h"
+
+#include
+#include
+#include
+
+namespace ngx_opentracing {
+ngx_int_t load_tracer(ngx_log_t* log, const char* tracer_library,
+ const char* config_file,
+ opentracing::DynamicTracingLibraryHandle& handle,
+ std::shared_ptr& tracer) {
+ std::string error_message;
+
+ // Open the library handle
+ auto handle_maybe =
+ opentracing::DynamicallyLoadTracingLibrary(tracer_library, error_message);
+ if (!handle_maybe) {
+ if (!error_message.empty()) {
+ ngx_log_error(NGX_LOG_ERR, log, 0,
+ "Failed to load tracing library %s: %s", tracer_library,
+ error_message.c_str());
+ } else {
+ ngx_log_error(NGX_LOG_ERR, log, 0,
+ "Failed to load tracing library %s: %s", tracer_library,
+ handle_maybe.error().message().c_str());
+ }
+ return NGX_ERROR;
+ }
+ auto& tracer_factory = handle_maybe->tracer_factory();
+
+ // Construct a tracer
+ errno = 0;
+ std::ifstream in{config_file};
+ if (!in.good()) {
+ ngx_log_error(NGX_LOG_ERR, log, errno,
+ "Failed to open tracer configuration file %s", config_file);
+ return NGX_ERROR;
+ }
+ std::string tracer_config{std::istreambuf_iterator{in},
+ std::istreambuf_iterator{}};
+ if (!in.good()) {
+ ngx_log_error(NGX_LOG_ERR, log, errno,
+ "Failed to read tracer configuration file %s", &config_file);
+ return NGX_ERROR;
+ }
+
+ auto tracer_maybe =
+ tracer_factory.MakeTracer(tracer_config.c_str(), error_message);
+ if (!tracer_maybe) {
+ if (!error_message.empty()) {
+ ngx_log_error(NGX_LOG_ERR, log, 0, "Failed to construct tracer: %s",
+ error_message.c_str());
+ } else {
+ ngx_log_error(NGX_LOG_ERR, log, 0, "Failed to construct tracer: %s",
+ tracer_maybe.error().message().c_str());
+ }
+ return NGX_ERROR;
+ }
+
+ handle = std::move(*handle_maybe);
+ tracer = std::move(*tracer_maybe);
+
+ return NGX_OK;
+}
+} // namespace ngx_opentracing
diff --git a/opentracing/src/load_tracer.h b/opentracing/src/load_tracer.h
new file mode 100644
index 00000000..72767d7c
--- /dev/null
+++ b/opentracing/src/load_tracer.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+namespace ngx_opentracing {
+ngx_int_t load_tracer(ngx_log_t* log, const char* tracer_library,
+ const char* config_file,
+ opentracing::DynamicTracingLibraryHandle& handle,
+ std::shared_ptr& tracer);
+} // namespace ngx_opentracing
diff --git a/opentracing/src/ngx_http_opentracing_module.cpp b/opentracing/src/ngx_http_opentracing_module.cpp
index a79a9938..a5f8f3f0 100644
--- a/opentracing/src/ngx_http_opentracing_module.cpp
+++ b/opentracing/src/ngx_http_opentracing_module.cpp
@@ -1,14 +1,16 @@
+#include "load_tracer.h"
+#include "opentracing_conf.h"
+#include "opentracing_directive.h"
+#include "opentracing_handler.h"
+#include "opentracing_variable.h"
+#include "utility.h"
+
#include
-#include
+
#include
#include
-#include
#include
-#include
#include
-#include "opentracing_conf.h"
-#include "opentracing_handler.h"
-#include "utility.h"
extern "C" {
#include
@@ -19,13 +21,7 @@ extern "C" {
extern ngx_module_t ngx_http_opentracing_module;
}
-using ngx_opentracing::opentracing_main_conf_t;
-using ngx_opentracing::opentracing_loc_conf_t;
-using ngx_opentracing::opentracing_tag_t;
-using ngx_opentracing::on_enter_block;
-using ngx_opentracing::on_log_request;
-using ngx_opentracing::NgxScript;
-using ngx_opentracing::to_string;
+using namespace ngx_opentracing;
static std::unique_ptr
opentracing_library_handle;
@@ -33,7 +29,7 @@ static std::unique_ptr
//------------------------------------------------------------------------------
// kDefaultOpentracingTags
//------------------------------------------------------------------------------
-const std::pair kDefaultOpenTracingTags[] = {
+const std::pair default_opentracing_tags[] = {
{ngx_string("component"), ngx_string("nginx")},
{ngx_string("nginx.worker_pid"), ngx_string("$pid")},
{ngx_string("peer.address"), ngx_string("$remote_addr:$remote_port")},
@@ -41,53 +37,10 @@ const std::pair kDefaultOpenTracingTags[] = {
{ngx_string("http.url"), ngx_string("$scheme://$http_host$request_uri")},
{ngx_string("http.host"), ngx_string("$http_host")}};
-//------------------------------------------------------------------------------
-// add_opentracing_tag
-//------------------------------------------------------------------------------
-static char *add_opentracing_tag(ngx_conf_t *cf, ngx_array_t *tags,
- ngx_str_t key, ngx_str_t value) {
- if (!tags) return static_cast(NGX_CONF_ERROR);
-
- auto tag = static_cast(ngx_array_push(tags));
- if (!tag) return static_cast(NGX_CONF_ERROR);
-
- ngx_memzero(tag, sizeof(opentracing_tag_t));
- if (tag->key_script.compile(cf, key) != NGX_OK)
- return static_cast(NGX_CONF_ERROR);
- if (tag->value_script.compile(cf, value) != NGX_OK)
- return static_cast(NGX_CONF_ERROR);
-
- return static_cast(NGX_CONF_OK);
-}
-
-//------------------------------------------------------------------------------
-// set_opentracing_tag
-//------------------------------------------------------------------------------
-static char *set_opentracing_tag(ngx_conf_t *cf, ngx_command_t *command,
- void *conf) {
- auto loc_conf = static_cast(conf);
- if (!loc_conf->tags)
- loc_conf->tags = ngx_array_create(cf->pool, 1, sizeof(opentracing_tag_t));
- auto values = static_cast(cf->args->elts);
- return add_opentracing_tag(cf, loc_conf->tags, values[1], values[2]);
-}
-
-//------------------------------------------------------------------------------
-// set_tracer
-//------------------------------------------------------------------------------
-static char *set_tracer(ngx_conf_t *cf, ngx_command_t *command, void *conf) {
- auto main_conf = static_cast(
- ngx_http_conf_get_module_main_conf(cf, ngx_http_opentracing_module));
- auto values = static_cast(cf->args->elts);
- main_conf->tracer_library = values[1];
- main_conf->tracer_conf_file = values[2];
- return static_cast(NGX_CONF_OK);
-}
-
//------------------------------------------------------------------------------
// opentracing_module_init
//------------------------------------------------------------------------------
-static ngx_int_t opentracing_module_init(ngx_conf_t *cf) {
+static ngx_int_t opentracing_module_init(ngx_conf_t *cf) noexcept {
auto core_main_config = static_cast(
ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module));
auto main_conf = static_cast(
@@ -106,12 +59,12 @@ static ngx_int_t opentracing_module_init(ngx_conf_t *cf) {
// Add default span tags.
const auto num_default_tags =
- sizeof(kDefaultOpenTracingTags) / sizeof(kDefaultOpenTracingTags[0]);
+ sizeof(default_opentracing_tags) / sizeof(default_opentracing_tags[0]);
if (num_default_tags == 0) return NGX_OK;
main_conf->tags =
ngx_array_create(cf->pool, num_default_tags, sizeof(opentracing_tag_t));
if (!main_conf->tags) return NGX_ERROR;
- for (const auto &tag : kDefaultOpenTracingTags)
+ for (const auto &tag : default_opentracing_tags)
if (add_opentracing_tag(cf, main_conf->tags, tag.first, tag.second) !=
NGX_CONF_OK)
return NGX_ERROR;
@@ -121,79 +74,43 @@ static ngx_int_t opentracing_module_init(ngx_conf_t *cf) {
//------------------------------------------------------------------------------
// opentracing_init_worker
//------------------------------------------------------------------------------
-static ngx_int_t opentracing_init_worker(ngx_cycle_t *cycle) {
+static ngx_int_t opentracing_init_worker(ngx_cycle_t *cycle) noexcept try {
auto main_conf = static_cast(
ngx_http_cycle_get_module_main_conf(cycle, ngx_http_opentracing_module));
if (!main_conf->tracer_library.data) {
return NGX_OK;
}
- // Load a tracer factory from the provided library.
- std::string error_message;
- auto library_handle_maybe = opentracing::DynamicallyLoadTracingLibrary(
- to_string(main_conf->tracer_library).data(), error_message);
- if (!library_handle_maybe) {
- if (!error_message.empty()) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "Failed to load tracing library %V: %s",
- &main_conf->tracer_library, error_message.c_str());
- } else {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "Failed to load tracing library %V: %s",
- &main_conf->tracer_library,
- library_handle_maybe.error().message().c_str());
- }
- return NGX_ERROR;
- }
- opentracing_library_handle.reset(new opentracing::DynamicTracingLibraryHandle{
- std::move(*library_handle_maybe)});
- auto &tracer_factory = opentracing_library_handle->tracer_factory();
-
- // Construct a tracer and initiqlize the global tracer.
- std::ifstream in{to_string(main_conf->tracer_conf_file)};
- if (!in.good()) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, errno,
- "Failed to open tracer configuration file %V",
- &main_conf->tracer_conf_file);
- return NGX_ERROR;
- }
- std::string tracer_configuration{std::istreambuf_iterator{in},
- std::istreambuf_iterator{}};
- if (!in.good()) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, errno,
- "Failed to read tracer configuration file %V",
- &main_conf->tracer_conf_file);
- return NGX_ERROR;
- }
-
- error_message.clear();
- auto tracer_maybe =
- tracer_factory.MakeTracer(tracer_configuration.c_str(), error_message);
- if (!tracer_maybe) {
- if (!error_message.empty()) {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "Failed to construct tracer: %s", error_message.c_str());
- } else {
- ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
- "Failed to construct tracer: %s",
- tracer_maybe.error().message().c_str());
- }
- return NGX_ERROR;
+ std::unique_ptr handle{
+ new opentracing::DynamicTracingLibraryHandle{}};
+ std::shared_ptr tracer;
+ auto result = ngx_opentracing::load_tracer(
+ cycle->log, to_string(main_conf->tracer_library).data(),
+ to_string(main_conf->tracer_conf_file).data(), *handle, tracer);
+ if (result != NGX_OK) {
+ return result;
}
- opentracing::Tracer::InitGlobal(std::move(*tracer_maybe));
+ opentracing_library_handle = std::move(handle);
+ opentracing::Tracer::InitGlobal(std::move(tracer));
return NGX_OK;
+} catch (const std::exception &e) {
+ ngx_log_error(NGX_LOG_ERR, cycle->log, 0, "failed to initialize tracer: %s",
+ e.what());
+ return NGX_ERROR;
}
//------------------------------------------------------------------------------
// opentracing_exit_worker
//------------------------------------------------------------------------------
-static void opentracing_exit_worker(ngx_cycle_t *cycle) {
+static void opentracing_exit_worker(ngx_cycle_t *cycle) noexcept {
// Close the global tracer if it's set and release the reference so as to
// ensure that any dynamically loaded tracer is destructed before the library
// handle is closed.
auto tracer = opentracing::Tracer::InitGlobal(nullptr);
if (tracer != nullptr) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cycle->log, 0,
+ "closing opentracing tracer");
tracer->Close();
tracer.reset();
}
@@ -205,7 +122,7 @@ static void opentracing_exit_worker(ngx_cycle_t *cycle) {
//------------------------------------------------------------------------------
// create_opentracing_main_conf
//------------------------------------------------------------------------------
-static void *create_opentracing_main_conf(ngx_conf_t *conf) {
+static void *create_opentracing_main_conf(ngx_conf_t *conf) noexcept {
auto main_conf = static_cast(
ngx_pcalloc(conf->pool, sizeof(opentracing_main_conf_t)));
// Default initialize members.
@@ -214,46 +131,10 @@ static void *create_opentracing_main_conf(ngx_conf_t *conf) {
return main_conf;
}
-//------------------------------------------------------------------------------
-// set_script
-//------------------------------------------------------------------------------
-static char *set_script(ngx_conf_t *cf, ngx_command_t *command,
- NgxScript &script) {
- if (script.is_valid()) return const_cast("is duplicate");
-
- auto value = static_cast(cf->args->elts);
- auto pattern = &value[1];
-
- if (script.compile(cf, *pattern) != NGX_OK)
- return static_cast(NGX_CONF_ERROR);
-
- return static_cast(NGX_CONF_OK);
-}
-
-//------------------------------------------------------------------------------
-// set_opentracing_operation_name
-//------------------------------------------------------------------------------
-static char *set_opentracing_operation_name(ngx_conf_t *cf,
- ngx_command_t *command,
- void *conf) {
- auto loc_conf = static_cast(conf);
- return set_script(cf, command, loc_conf->operation_name_script);
-}
-
-//------------------------------------------------------------------------------
-// set_opentracing_location_operation_name
-//------------------------------------------------------------------------------
-static char *set_opentracing_location_operation_name(ngx_conf_t *cf,
- ngx_command_t *command,
- void *conf) {
- auto loc_conf = static_cast(conf);
- return set_script(cf, command, loc_conf->loc_operation_name_script);
-}
-
//------------------------------------------------------------------------------
// create_opentracing_loc_conf
//------------------------------------------------------------------------------
-static void *create_opentracing_loc_conf(ngx_conf_t *conf) {
+static void *create_opentracing_loc_conf(ngx_conf_t *conf) noexcept {
auto loc_conf = static_cast(
ngx_pcalloc(conf->pool, sizeof(opentracing_loc_conf_t)));
if (!loc_conf) return nullptr;
@@ -269,7 +150,7 @@ static void *create_opentracing_loc_conf(ngx_conf_t *conf) {
// merge_opentracing_loc_conf
//------------------------------------------------------------------------------
static char *merge_opentracing_loc_conf(ngx_conf_t *, void *parent,
- void *child) {
+ void *child) noexcept {
auto prev = static_cast(parent);
auto conf = static_cast(child);
@@ -309,7 +190,7 @@ static char *merge_opentracing_loc_conf(ngx_conf_t *, void *parent,
// opentracing_module_ctx
//------------------------------------------------------------------------------
static ngx_http_module_t opentracing_module_ctx = {
- nullptr, /* preconfiguration */
+ add_variables, /* preconfiguration */
opentracing_module_init, /* postconfiguration */
create_opentracing_main_conf, /* create main configuration */
nullptr, /* init main configuration */
@@ -333,6 +214,9 @@ static ngx_command_t opentracing_commands[] = {
NGX_CONF_TAKE1,
ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET,
offsetof(opentracing_loc_conf_t, enable_locations), nullptr},
+ {ngx_string("opentracing_propagate_context"),
+ NGX_HTTP_LOC_CONF | NGX_CONF_NOARGS, propagate_opentracing_context,
+ NGX_HTTP_LOC_CONF_OFFSET, 0, nullptr},
{ngx_string("opentracing_operation_name"),
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF |
NGX_CONF_TAKE1,
diff --git a/opentracing/src/ngx_script.cpp b/opentracing/src/ngx_script.cpp
index 6335c2a0..0d13b353 100644
--- a/opentracing/src/ngx_script.cpp
+++ b/opentracing/src/ngx_script.cpp
@@ -5,13 +5,14 @@ namespace ngx_opentracing {
//------------------------------------------------------------------------------
// NgxScript
//------------------------------------------------------------------------------
-NgxScript::NgxScript()
+NgxScript::NgxScript() noexcept
: pattern_{0, nullptr}, lengths_{nullptr}, values_{nullptr} {}
//------------------------------------------------------------------------------
// compile
//------------------------------------------------------------------------------
-ngx_int_t NgxScript::compile(ngx_conf_t *cf, const ngx_str_t &pattern) {
+ngx_int_t NgxScript::compile(ngx_conf_t *cf,
+ const ngx_str_t &pattern) noexcept {
pattern_ = pattern;
lengths_ = nullptr;
values_ = nullptr;
@@ -36,7 +37,7 @@ ngx_int_t NgxScript::compile(ngx_conf_t *cf, const ngx_str_t &pattern) {
//------------------------------------------------------------------------------
// run
//------------------------------------------------------------------------------
-ngx_str_t NgxScript::run(ngx_http_request_t *request) const {
+ngx_str_t NgxScript::run(ngx_http_request_t *request) const noexcept {
if (!is_valid()) {
ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
"Executing invalid opentracing script");
diff --git a/opentracing/src/ngx_script.h b/opentracing/src/ngx_script.h
index 0108e3f0..2285de6b 100644
--- a/opentracing/src/ngx_script.h
+++ b/opentracing/src/ngx_script.h
@@ -11,12 +11,12 @@ namespace ngx_opentracing {
class NgxScript {
public:
// Note: Constructor is compatible with begin zero initialized.
- NgxScript();
+ NgxScript() noexcept;
- bool is_valid() const { return pattern_.data; }
+ bool is_valid() const noexcept { return pattern_.data; }
- ngx_int_t compile(ngx_conf_t *cf, const ngx_str_t &pattern);
- ngx_str_t run(ngx_http_request_t *request) const;
+ ngx_int_t compile(ngx_conf_t *cf, const ngx_str_t &pattern) noexcept;
+ ngx_str_t run(ngx_http_request_t *request) const noexcept;
private:
ngx_str_t pattern_;
diff --git a/opentracing/src/opentracing_conf.h b/opentracing/src/opentracing_conf.h
index a20990ad..78e64cdc 100644
--- a/opentracing/src/opentracing_conf.h
+++ b/opentracing/src/opentracing_conf.h
@@ -19,6 +19,7 @@ struct opentracing_main_conf_t {
ngx_array_t *tags;
ngx_str_t tracer_library;
ngx_str_t tracer_conf_file;
+ ngx_array_t *span_context_keys;
};
struct opentracing_loc_conf_t {
diff --git a/opentracing/src/opentracing_conf_handler.cpp b/opentracing/src/opentracing_conf_handler.cpp
new file mode 100644
index 00000000..c33344b2
--- /dev/null
+++ b/opentracing/src/opentracing_conf_handler.cpp
@@ -0,0 +1,146 @@
+#include "opentracing_conf_handler.h"
+
+namespace ngx_opentracing {
+/* The eight fixed arguments */
+
+static ngx_uint_t argument_number[] = {
+ NGX_CONF_NOARGS, NGX_CONF_TAKE1, NGX_CONF_TAKE2, NGX_CONF_TAKE3,
+ NGX_CONF_TAKE4, NGX_CONF_TAKE5, NGX_CONF_TAKE6, NGX_CONF_TAKE7};
+
+//------------------------------------------------------------------------------
+// opentracing_conf_handler
+//------------------------------------------------------------------------------
+ngx_int_t opentracing_conf_handler(ngx_conf_t *cf, ngx_int_t last) noexcept {
+ char *rv;
+ void *conf, **confp;
+ ngx_uint_t i, found;
+ ngx_str_t *name;
+ ngx_command_t *cmd;
+
+ name = static_cast(cf->args->elts);
+
+ found = 0;
+
+ for (i = 0; cf->cycle->modules[i]; i++) {
+ cmd = cf->cycle->modules[i]->commands;
+ if (cmd == NULL) {
+ continue;
+ }
+
+ for (/* void */; cmd->name.len; cmd++) {
+ if (name->len != cmd->name.len) {
+ continue;
+ }
+
+ if (ngx_strcmp(name->data, cmd->name.data) != 0) {
+ continue;
+ }
+
+ found = 1;
+
+ if (cf->cycle->modules[i]->type != NGX_CONF_MODULE &&
+ cf->cycle->modules[i]->type != cf->module_type) {
+ continue;
+ }
+
+ /* is the directive's location right ? */
+
+ if (!(cmd->type & cf->cmd_type)) {
+ continue;
+ }
+
+ if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "directive \"%s\" is not terminated by \";\"",
+ name->data);
+ return NGX_ERROR;
+ }
+
+ if ((cmd->type & NGX_CONF_BLOCK) && last != NGX_CONF_BLOCK_START) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "directive \"%s\" has no opening \"{\"", name->data);
+ return NGX_ERROR;
+ }
+
+ /* is the directive's argument count right ? */
+
+ if (!(cmd->type & NGX_CONF_ANY)) {
+ if (cmd->type & NGX_CONF_FLAG) {
+ if (cf->args->nelts != 2) {
+ goto invalid;
+ }
+
+ } else if (cmd->type & NGX_CONF_1MORE) {
+ if (cf->args->nelts < 2) {
+ goto invalid;
+ }
+
+ } else if (cmd->type & NGX_CONF_2MORE) {
+ if (cf->args->nelts < 3) {
+ goto invalid;
+ }
+
+ } else if (cf->args->nelts > NGX_CONF_MAX_ARGS) {
+ goto invalid;
+
+ } else if (!(cmd->type & argument_number[cf->args->nelts - 1])) {
+ goto invalid;
+ }
+ }
+
+ /* set up the directive's configuration context */
+
+ conf = NULL;
+
+ if (cmd->type & NGX_DIRECT_CONF) {
+ conf = ((void **)cf->ctx)[cf->cycle->modules[i]->index];
+
+ } else if (cmd->type & NGX_MAIN_CONF) {
+ conf = &(((void **)cf->ctx)[cf->cycle->modules[i]->index]);
+
+ } else if (cf->ctx) {
+ confp = static_cast(*(void **)((char *)cf->ctx + cmd->conf));
+
+ if (confp) {
+ conf = confp[cf->cycle->modules[i]->ctx_index];
+ }
+ }
+
+ rv = cmd->set(cf, cmd, conf);
+
+ if (rv == NGX_CONF_OK) {
+ return NGX_OK;
+ }
+
+ if (rv == NGX_CONF_ERROR) {
+ return NGX_ERROR;
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"%s\" directive %s",
+ name->data, rv);
+
+ return NGX_ERROR;
+ }
+ }
+
+ if (found) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "\"%s\" directive is not allowed here", name->data);
+
+ return NGX_ERROR;
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "unknown directive \"%s\"",
+ name->data);
+
+ return NGX_ERROR;
+
+invalid:
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid number of arguments in \"%s\" directive",
+ name->data);
+
+ return NGX_ERROR;
+}
+} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_conf_handler.h b/opentracing/src/opentracing_conf_handler.h
new file mode 100644
index 00000000..62a5bda6
--- /dev/null
+++ b/opentracing/src/opentracing_conf_handler.h
@@ -0,0 +1,17 @@
+#pragma once
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+namespace ngx_opentracing {
+// opentracing_conf_handler is copied from
+// https://github.com/nginx/nginx/blob/0ad556fe59ad132dc4d34dea9e80f2ff2c3c1314/src/core/ngx_conf_file.c
+// this is necessary for OpenTracing's implementation of context propagation.
+//
+// See http://mailman.nginx.org/pipermail/nginx-devel/2018-March/011008.html
+ngx_int_t opentracing_conf_handler(ngx_conf_t *cf, ngx_int_t last) noexcept;
+} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_request_instrumentor.cpp b/opentracing/src/opentracing_context.cpp
similarity index 55%
rename from opentracing/src/opentracing_request_instrumentor.cpp
rename to opentracing/src/opentracing_context.cpp
index a2d3fac2..a6c69cb1 100644
--- a/opentracing/src/opentracing_request_instrumentor.cpp
+++ b/opentracing/src/opentracing_context.cpp
@@ -1,6 +1,8 @@
-#include "opentracing_request_instrumentor.h"
+#include "opentracing_context.h"
#include "utility.h"
+#include
+
extern "C" {
extern ngx_module_t ngx_http_opentracing_module;
}
@@ -9,10 +11,6 @@ namespace ngx_opentracing {
std::unique_ptr extract_span_context(
const opentracing::Tracer &tracer, const ngx_http_request_t *request);
-void inject_span_context(const opentracing::Tracer &tracer,
- ngx_http_request_t *request,
- const opentracing::SpanContext &span_context);
-
//------------------------------------------------------------------------------
// get_loc_operation_name
//------------------------------------------------------------------------------
@@ -70,16 +68,18 @@ static void add_status_tags(const ngx_http_request_t *request,
}
//------------------------------------------------------------------------------
-// OpenTracingRequestInstrumentor
+// OpenTracingContext
//------------------------------------------------------------------------------
-OpenTracingRequestInstrumentor::OpenTracingRequestInstrumentor(
- ngx_http_request_t *request, ngx_http_core_loc_conf_t *core_loc_conf,
- opentracing_loc_conf_t *loc_conf)
- : request_{request}, loc_conf_{loc_conf} {
- main_conf_ = static_cast(
- ngx_http_get_module_main_conf(request_, ngx_http_opentracing_module));
+OpenTracingContext::OpenTracingContext(ngx_http_request_t *request,
+ ngx_http_core_loc_conf_t *core_loc_conf,
+ opentracing_loc_conf_t *loc_conf)
+ : request_{request},
+ main_conf_{
+ static_cast(ngx_http_get_module_main_conf(
+ request_, ngx_http_opentracing_module))},
+ loc_conf_{loc_conf} {
auto tracer = opentracing::Tracer::Global();
- if (!tracer) throw InstrumentationFailure{};
+ if (!tracer) throw std::runtime_error{"no global tracer set"};
std::unique_ptr parent_span_context = nullptr;
if (loc_conf_->trust_incoming_span) {
@@ -93,7 +93,7 @@ OpenTracingRequestInstrumentor::OpenTracingRequestInstrumentor(
{opentracing::ChildOf(parent_span_context.get()),
opentracing::StartTimestamp{
to_system_timestamp(request->start_sec, request->start_msec)}});
- if (!request_span_) throw InstrumentationFailure{};
+ if (!request_span_) throw std::runtime_error{"tracer->StartSpan failed"};
if (loc_conf_->enable_locations) {
ngx_log_debug3(
@@ -103,19 +103,16 @@ OpenTracingRequestInstrumentor::OpenTracingRequestInstrumentor(
span_ = tracer->StartSpan(
get_loc_operation_name(request_, core_loc_conf, loc_conf_),
{opentracing::ChildOf(&request_span_->context())});
- if (!span_) throw InstrumentationFailure{};
+ if (!span_) throw std::runtime_error{"tracer->StartSpan failed"};
}
-
- set_request_span_context();
}
//------------------------------------------------------------------------------
// on_change_block
//------------------------------------------------------------------------------
-void OpenTracingRequestInstrumentor::on_change_block(
+void OpenTracingContext::on_change_block(
ngx_http_core_loc_conf_t *core_loc_conf, opentracing_loc_conf_t *loc_conf) {
on_exit_block();
- auto prev_loc_conf = loc_conf_;
loc_conf_ = loc_conf;
if (loc_conf->enable_locations) {
@@ -126,20 +123,25 @@ void OpenTracingRequestInstrumentor::on_change_block(
span_ = request_span_->tracer().StartSpan(
get_loc_operation_name(request_, core_loc_conf, loc_conf),
{opentracing::ChildOf(&request_span_->context())});
- if (!span_) throw InstrumentationFailure{};
+ if (!span_) throw std::runtime_error{"tracer->StartSpan failed"};
}
+}
- // As an optimization, avoid injecting the request span context if neither the
- // previous nor current location blocks are traced since the active span
- // context will be the same.
- if (prev_loc_conf->enable_locations || loc_conf->enable_locations)
- set_request_span_context();
+//------------------------------------------------------------------------------
+// active_span
+//------------------------------------------------------------------------------
+opentracing::Span &OpenTracingContext::active_span() {
+ if (loc_conf_->enable_locations) {
+ return *span_;
+ } else {
+ return *request_span_;
+ }
}
//------------------------------------------------------------------------------
// on_exit_block
//------------------------------------------------------------------------------
-void OpenTracingRequestInstrumentor::on_exit_block(
+void OpenTracingContext::on_exit_block(
std::chrono::steady_clock::time_point finish_timestamp) {
// Set default and custom tags for the block. Many nginx variables won't be
// available when a block is first entered, so set tags when the block is
@@ -157,21 +159,10 @@ void OpenTracingRequestInstrumentor::on_exit_block(
}
}
-//------------------------------------------------------------------------------
-// set_request_span_context
-//------------------------------------------------------------------------------
-void OpenTracingRequestInstrumentor::set_request_span_context() {
- if (loc_conf_->enable_locations)
- inject_span_context(span_->tracer(), request_, span_->context());
- else
- inject_span_context(request_span_->tracer(), request_,
- request_span_->context());
-}
-
//------------------------------------------------------------------------------
// on_log_request
//------------------------------------------------------------------------------
-void OpenTracingRequestInstrumentor::on_log_request() {
+void OpenTracingContext::on_log_request() {
auto finish_timestamp = std::chrono::steady_clock::now();
on_exit_block(finish_timestamp);
@@ -192,4 +183,114 @@ void OpenTracingRequestInstrumentor::on_log_request() {
request_span_->Finish({opentracing::FinishTimestamp{finish_timestamp}});
}
+
+//------------------------------------------------------------------------------
+// lookup_span_context_value
+//------------------------------------------------------------------------------
+// Expands the active span context into a list of key-value pairs and returns
+// the value for `key` if it exists.
+//
+// Note: there's caching so that if lookup_span_context_value is repeatedly
+// called for the same active span context, it will only be expanded once.
+//
+// See propagate_opentracing_context
+ngx_str_t OpenTracingContext::lookup_span_context_value(
+ opentracing::string_view key) {
+ return span_context_querier_.lookup_value(request_, active_span(), key);
+}
+
+//------------------------------------------------------------------------------
+// cleanup_opentracing_context
+//------------------------------------------------------------------------------
+static void cleanup_opentracing_context(void *data) noexcept {
+ delete static_cast(data);
+}
+
+//------------------------------------------------------------------------------
+// find_opentracing_cleanup
+//------------------------------------------------------------------------------
+static ngx_pool_cleanup_t *find_opentracing_cleanup(
+ ngx_http_request_t *request) {
+ for (auto cleanup = request->pool->cleanup; cleanup;
+ cleanup = cleanup->next) {
+ if (cleanup->handler == cleanup_opentracing_context) {
+ return cleanup;
+ }
+ }
+ return nullptr;
+}
+
+//------------------------------------------------------------------------------
+// get_opentracing_context
+//------------------------------------------------------------------------------
+OpenTracingContext *get_opentracing_context(
+ ngx_http_request_t *request) noexcept {
+ auto context = static_cast(
+ ngx_http_get_module_ctx(request, ngx_http_opentracing_module));
+ if (context != nullptr || !request->internal) {
+ return context;
+ }
+
+ // If this is an internal redirect, the OpenTracingContext will have been
+ // reset, but we can still recover it from the cleanup handler.
+ //
+ // See set_opentracing_context below.
+ auto cleanup = find_opentracing_cleanup(request);
+ if (cleanup != nullptr) {
+ context = static_cast(cleanup->data);
+ }
+
+ // If we found a context, attach with ngx_http_set_ctx so that we don't have
+ // to loop through the cleanup handlers again.
+ if (context != nullptr) {
+ ngx_http_set_ctx(request, static_cast(context),
+ ngx_http_opentracing_module);
+ }
+
+ return context;
+}
+
+//------------------------------------------------------------------------------
+// set_opentracing_context
+//------------------------------------------------------------------------------
+// Attaches an OpenTracingContext to a request.
+//
+// Note that internal redirects for nginx will clear any data attached via
+// ngx_http_set_ctx. Since OpenTracingContext needs to persist across
+// redirection, as a workaround the context is stored in a cleanup handler where
+// it can be later recovered.
+//
+// See the discussion in
+// https://forum.nginx.org/read.php?29,272403,272403#msg-272403
+// or the approach taken by the standard nginx realip module.
+void set_opentracing_context(ngx_http_request_t *request,
+ OpenTracingContext *context) {
+ auto cleanup = ngx_pool_cleanup_add(request->pool, 0);
+ if (cleanup == nullptr) {
+ delete context;
+ throw std::runtime_error{"failed to allocate cleanup handler"};
+ }
+ cleanup->data = static_cast(context);
+ cleanup->handler = cleanup_opentracing_context;
+ ngx_http_set_ctx(request, static_cast(context),
+ ngx_http_opentracing_module);
+}
+
+//------------------------------------------------------------------------------
+// destroy_opentracing_context
+//------------------------------------------------------------------------------
+// Supports early destruction of the OpenTracingContext (in case of an
+// unrecoverable error).
+void destroy_opentracing_context(ngx_http_request_t *request) noexcept {
+ auto cleanup = find_opentracing_cleanup(request);
+ if (cleanup == nullptr) {
+ ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
+ "Unable to find OpenTracing cleanup handler for request %p",
+ request);
+ return;
+ }
+ delete static_cast(cleanup->data);
+ cleanup->data = nullptr;
+ ngx_http_set_ctx(request, nullptr, ngx_http_opentracing_module);
+}
} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_context.h b/opentracing/src/opentracing_context.h
new file mode 100644
index 00000000..08fd06a9
--- /dev/null
+++ b/opentracing/src/opentracing_context.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include "opentracing_conf.h"
+#include "span_context_querier.h"
+
+#include
+#include
+#include
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// OpenTracingContext
+//------------------------------------------------------------------------------
+class OpenTracingContext {
+ public:
+ OpenTracingContext(ngx_http_request_t *request,
+ ngx_http_core_loc_conf_t *core_loc_conf,
+ opentracing_loc_conf_t *loc_conf);
+
+ void on_change_block(ngx_http_core_loc_conf_t *core_loc_conf,
+ opentracing_loc_conf_t *loc_conf);
+
+ void on_log_request();
+
+ ngx_str_t lookup_span_context_value(opentracing::string_view key);
+
+ private:
+ ngx_http_request_t *request_;
+ opentracing_main_conf_t *main_conf_;
+ opentracing_loc_conf_t *loc_conf_;
+ SpanContextQuerier span_context_querier_;
+ std::unique_ptr request_span_;
+ std::unique_ptr span_;
+
+ opentracing::Span &active_span();
+
+ void on_exit_block(std::chrono::steady_clock::time_point finish_timestamp =
+ std::chrono::steady_clock::now());
+};
+
+//------------------------------------------------------------------------------
+// get_opentracing_context
+//------------------------------------------------------------------------------
+OpenTracingContext *get_opentracing_context(
+ ngx_http_request_t *request) noexcept;
+
+//------------------------------------------------------------------------------
+// set_opentracing_context
+//------------------------------------------------------------------------------
+void set_opentracing_context(ngx_http_request_t *request,
+ OpenTracingContext *context);
+
+//------------------------------------------------------------------------------
+// destroy_opentracing_context
+//------------------------------------------------------------------------------
+void destroy_opentracing_context(ngx_http_request_t *request) noexcept;
+} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_directive.cpp b/opentracing/src/opentracing_directive.cpp
new file mode 100644
index 00000000..d71296ad
--- /dev/null
+++ b/opentracing/src/opentracing_directive.cpp
@@ -0,0 +1,198 @@
+#include "opentracing_directive.h"
+
+#include "discover_span_context_keys.h"
+#include "ngx_script.h"
+#include "opentracing_conf.h"
+#include "opentracing_conf_handler.h"
+#include "opentracing_variable.h"
+#include "utility.h"
+
+#include
+
+#include
+#include
+
+extern "C" {
+extern ngx_module_t ngx_http_opentracing_module;
+}
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// set_script
+//------------------------------------------------------------------------------
+static char *set_script(ngx_conf_t *cf, ngx_command_t *command,
+ NgxScript &script) noexcept {
+ if (script.is_valid()) return const_cast("is duplicate");
+
+ auto value = static_cast(cf->args->elts);
+ auto pattern = &value[1];
+
+ if (script.compile(cf, *pattern) != NGX_OK)
+ return static_cast(NGX_CONF_ERROR);
+
+ return static_cast(NGX_CONF_OK);
+}
+
+//------------------------------------------------------------------------------
+// make_span_context_value_variable
+//------------------------------------------------------------------------------
+static ngx_str_t make_span_context_value_variable(
+ ngx_pool_t *pool, opentracing::string_view key) {
+ auto size = 1 + opentracing_context_variable_name.size() + key.size();
+ auto data = static_cast(ngx_palloc(pool, size));
+ if (data == nullptr) throw std::bad_alloc{};
+
+ int index = 0;
+ data[index] = '$';
+ index += 1;
+
+ std::copy_n(opentracing_context_variable_name.data(),
+ opentracing_context_variable_name.size(), data + index);
+ index += opentracing_context_variable_name.size();
+
+ std::transform(std::begin(key), std::end(key), data + index,
+ header_transform);
+
+ return {size, reinterpret_cast(data)};
+}
+
+//------------------------------------------------------------------------------
+// add_opentracing_tag
+//------------------------------------------------------------------------------
+char *add_opentracing_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key,
+ ngx_str_t value) noexcept {
+ if (!tags) return static_cast(NGX_CONF_ERROR);
+
+ auto tag = static_cast(ngx_array_push(tags));
+ if (!tag) return static_cast(NGX_CONF_ERROR);
+
+ ngx_memzero(tag, sizeof(opentracing_tag_t));
+ if (tag->key_script.compile(cf, key) != NGX_OK)
+ return static_cast(NGX_CONF_ERROR);
+ if (tag->value_script.compile(cf, value) != NGX_OK)
+ return static_cast(NGX_CONF_ERROR);
+
+ return static_cast(NGX_CONF_OK);
+}
+
+//------------------------------------------------------------------------------
+// propagate_opentracing_context
+//------------------------------------------------------------------------------
+// Sets up headers to be added so that the active span context is propagated
+// upstream when using ngx_http_proxy_module.
+//
+// The directive gets translated to the directives
+//
+// proxy_set_header span_context_key0 $opentracing_context_key0
+// proxy_set_header span_context_key1 $opentracing_context_key1
+// ...
+// proxy_set_header span_context_keyN $opentracing_context_keyN
+//
+// where opentracing_context is a prefix variable that expands to the
+// corresponding value of the active span context.
+//
+// The key value of proxy_set_header isn't allowed to be a variable, so the keys
+// used for propagation need to be discovered before this directive is called.
+// (See set_tracer below).
+//
+// This approach was dicussed here
+// http://mailman.nginx.org/pipermail/nginx-devel/2018-March/011008.html
+char *propagate_opentracing_context(ngx_conf_t *cf, ngx_command_t * /*command*/,
+ void * /*conf*/) noexcept try {
+ auto main_conf = static_cast(
+ ngx_http_conf_get_module_main_conf(cf, ngx_http_opentracing_module));
+ if (main_conf->span_context_keys == nullptr) {
+ return static_cast(NGX_CONF_OK);
+ }
+ auto keys = static_cast(
+ main_conf->span_context_keys->elts);
+ auto num_keys = static_cast(main_conf->span_context_keys->nelts);
+
+ auto old_args = cf->args;
+
+ ngx_str_t args[] = {ngx_string("proxy_set_header"), {}, {}};
+ ngx_array_t args_array;
+ args_array.elts = static_cast(&args);
+ args_array.nelts = 3;
+
+ cf->args = &args_array;
+ for (int key_index = 0; key_index < num_keys; ++key_index) {
+ args[1] = ngx_str_t{keys[key_index].size(),
+ reinterpret_cast(
+ const_cast(keys[key_index].data()))};
+ args[2] = make_span_context_value_variable(cf->pool, keys[key_index]);
+ auto rcode = opentracing_conf_handler(cf, 0);
+ if (rcode != NGX_OK) {
+ cf->args = old_args;
+ return static_cast(NGX_CONF_ERROR);
+ }
+ }
+ cf->args = old_args;
+ return static_cast(NGX_CONF_OK);
+} catch (const std::exception &e) {
+ ngx_log_error(NGX_LOG_ERR, cf->log, 0,
+ "opentracing_propatate_context failed: %s", e.what());
+ return static_cast(NGX_CONF_ERROR);
+}
+
+//------------------------------------------------------------------------------
+// set_opentracing_tag
+//------------------------------------------------------------------------------
+char *set_opentracing_tag(ngx_conf_t *cf, ngx_command_t *command,
+ void *conf) noexcept {
+ auto loc_conf = static_cast(conf);
+ if (!loc_conf->tags)
+ loc_conf->tags = ngx_array_create(cf->pool, 1, sizeof(opentracing_tag_t));
+ auto values = static_cast(cf->args->elts);
+ return add_opentracing_tag(cf, loc_conf->tags, values[1], values[2]);
+}
+
+//------------------------------------------------------------------------------
+// set_opentracing_operation_name
+//------------------------------------------------------------------------------
+char *set_opentracing_operation_name(ngx_conf_t *cf, ngx_command_t *command,
+ void *conf) noexcept {
+ auto loc_conf = static_cast(conf);
+ return set_script(cf, command, loc_conf->operation_name_script);
+}
+
+//------------------------------------------------------------------------------
+// set_opentracing_location_operation_name
+//------------------------------------------------------------------------------
+char *set_opentracing_location_operation_name(ngx_conf_t *cf,
+ ngx_command_t *command,
+ void *conf) noexcept {
+ auto loc_conf = static_cast(conf);
+ return set_script(cf, command, loc_conf->loc_operation_name_script);
+}
+
+//------------------------------------------------------------------------------
+// set_tracer
+//------------------------------------------------------------------------------
+char *set_tracer(ngx_conf_t *cf, ngx_command_t *command,
+ void *conf) noexcept try {
+ auto main_conf = static_cast(
+ ngx_http_conf_get_module_main_conf(cf, ngx_http_opentracing_module));
+ auto values = static_cast(cf->args->elts);
+ main_conf->tracer_library = values[1];
+ main_conf->tracer_conf_file = values[2];
+
+ // In order for span context propagation to work, the keys used by a tracer
+ // need to be known ahead of time. OpenTracing-C++ doesn't currently have any
+ // API for this, so we attempt to do this by creating and injecting a dummy
+ // span context.
+ //
+ // See also propagate_opentracing_context.
+ main_conf->span_context_keys = discover_span_context_keys(
+ cf->pool, cf->log, to_string(main_conf->tracer_library).c_str(),
+ to_string(main_conf->tracer_conf_file).c_str());
+ if (main_conf->span_context_keys == nullptr) {
+ return static_cast(NGX_CONF_ERROR);
+ }
+
+ return static_cast(NGX_CONF_OK);
+} catch (const std::exception &e) {
+ ngx_log_error(NGX_LOG_ERR, cf->log, 0, "set_tracer failed: %s", e.what());
+ return static_cast(NGX_CONF_ERROR);
+}
+} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_directive.h b/opentracing/src/opentracing_directive.h
new file mode 100644
index 00000000..52576c3e
--- /dev/null
+++ b/opentracing/src/opentracing_directive.h
@@ -0,0 +1,46 @@
+#pragma once
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// propagate_opentracing_context
+//------------------------------------------------------------------------------
+char *propagate_opentracing_context(ngx_conf_t *cf, ngx_command_t *command,
+ void *conf) noexcept;
+
+//------------------------------------------------------------------------------
+// add_opentracing_tag
+//------------------------------------------------------------------------------
+char *add_opentracing_tag(ngx_conf_t *cf, ngx_array_t *tags, ngx_str_t key,
+ ngx_str_t value) noexcept;
+
+//------------------------------------------------------------------------------
+// set_opentracing_tag
+//------------------------------------------------------------------------------
+char *set_opentracing_tag(ngx_conf_t *cf, ngx_command_t *command,
+ void *conf) noexcept;
+
+//------------------------------------------------------------------------------
+// set_opentracing_operation_name
+//------------------------------------------------------------------------------
+char *set_opentracing_operation_name(ngx_conf_t *cf, ngx_command_t *command,
+ void *conf) noexcept;
+
+//------------------------------------------------------------------------------
+// set_opentracing_location_operation_name
+//------------------------------------------------------------------------------
+char *set_opentracing_location_operation_name(ngx_conf_t *cf,
+ ngx_command_t *command,
+ void *conf) noexcept;
+
+//------------------------------------------------------------------------------
+// set_tracer
+//------------------------------------------------------------------------------
+char *set_tracer(ngx_conf_t *cf, ngx_command_t *command, void *conf) noexcept;
+} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_handler.cpp b/opentracing/src/opentracing_handler.cpp
index ed2e5df9..375d3f04 100644
--- a/opentracing/src/opentracing_handler.cpp
+++ b/opentracing/src/opentracing_handler.cpp
@@ -1,44 +1,19 @@
#include "opentracing_handler.h"
-#include
-#include
-#include "opentracing_conf.h"
-#include "opentracing_request_instrumentor.h"
+
+#include "opentracing_context.h"
extern "C" {
extern ngx_module_t ngx_http_opentracing_module;
}
namespace ngx_opentracing {
-//------------------------------------------------------------------------------
-// OpenTracingContext
-//------------------------------------------------------------------------------
-namespace {
-class OpenTracingContext {
- public:
- void on_enter_block(ngx_http_request_t *request);
- void on_log_request(ngx_http_request_t *request);
-
- private:
- std::unordered_map
- active_instrumentors_;
-};
-} // namespace
-
-//------------------------------------------------------------------------------
-// get_handler_context
-//------------------------------------------------------------------------------
-static OpenTracingContext &get_handler_context() {
- static OpenTracingContext handler_context{};
- return handler_context;
-}
-
//------------------------------------------------------------------------------
// is_opentracing_enabled
//------------------------------------------------------------------------------
static bool is_opentracing_enabled(
const ngx_http_request_t *request,
const ngx_http_core_loc_conf_t *core_loc_conf,
- const opentracing_loc_conf_t *loc_conf) {
+ const opentracing_loc_conf_t *loc_conf) noexcept {
// Check if this is a main request instead of a subrequest.
if (request == request->main)
return loc_conf->enable;
@@ -51,58 +26,50 @@ static bool is_opentracing_enabled(
//------------------------------------------------------------------------------
// on_enter_block
//------------------------------------------------------------------------------
-void OpenTracingContext::on_enter_block(ngx_http_request_t *request) {
+ngx_int_t on_enter_block(ngx_http_request_t *request) noexcept try {
auto core_loc_conf = static_cast(
ngx_http_get_module_loc_conf(request, ngx_http_core_module));
auto loc_conf = static_cast(
ngx_http_get_module_loc_conf(request, ngx_http_opentracing_module));
+ if (!is_opentracing_enabled(request, core_loc_conf, loc_conf))
+ return NGX_DECLINED;
- auto instrumentor_iter = active_instrumentors_.find(request);
- if (instrumentor_iter == active_instrumentors_.end()) {
- if (!is_opentracing_enabled(request, core_loc_conf, loc_conf)) return;
- try {
- active_instrumentors_.emplace(
- request,
- OpenTracingRequestInstrumentor{request, core_loc_conf, loc_conf});
- } catch (const InstrumentationFailure &) {
- ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
- "OpenTracing instrumentation failed for request %p",
- request);
- }
+ auto context = get_opentracing_context(request);
+ if (context == nullptr) {
+ context = new OpenTracingContext{request, core_loc_conf, loc_conf};
+ set_opentracing_context(request, context);
} else {
try {
- instrumentor_iter->second.on_change_block(core_loc_conf, loc_conf);
- } catch (const InstrumentationFailure &) {
- active_instrumentors_.erase(instrumentor_iter);
- ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
- "OpenTracing instrumentation failed for request %p",
- request);
+ context->on_change_block(core_loc_conf, loc_conf);
+ } catch (...) {
+ // The OpenTracingContext may be broken, destroy it so that we don't
+ // attempt to continue tracing.
+ destroy_opentracing_context(request);
+
+ throw;
}
}
-}
-
-ngx_int_t on_enter_block(ngx_http_request_t *request) {
- get_handler_context().on_enter_block(request);
+ return NGX_DECLINED;
+} catch (const std::exception &e) {
+ ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
+ "OpenTracing instrumentation failed for request %p: %s",
+ request, e.what());
return NGX_DECLINED;
}
//------------------------------------------------------------------------------
// on_log_request
//------------------------------------------------------------------------------
-void OpenTracingContext::on_log_request(ngx_http_request_t *request) {
- auto instrumentor_iter = active_instrumentors_.find(request);
- if (instrumentor_iter == active_instrumentors_.end()) return;
+ngx_int_t on_log_request(ngx_http_request_t *request) noexcept {
+ auto context = get_opentracing_context(request);
+ if (context == nullptr) return NGX_DECLINED;
try {
- instrumentor_iter->second.on_log_request();
- } catch (const InstrumentationFailure &) {
+ context->on_log_request();
+ } catch (const std::exception &e) {
ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
- "OpenTracing instrumentation failed for request %p", request);
+ "OpenTracing instrumentation failed for request %p: %s",
+ request, e.what());
}
- active_instrumentors_.erase(instrumentor_iter);
-}
-
-ngx_int_t on_log_request(ngx_http_request_t *request) {
- get_handler_context().on_log_request(request);
return NGX_DECLINED;
}
} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_handler.h b/opentracing/src/opentracing_handler.h
index c64a6b99..d021bc84 100644
--- a/opentracing/src/opentracing_handler.h
+++ b/opentracing/src/opentracing_handler.h
@@ -5,9 +5,18 @@ extern "C" {
#include
#include
#include
+
+extern ngx_module_t ngx_http_opentracing_module;
}
namespace ngx_opentracing {
-ngx_int_t on_enter_block(ngx_http_request_t *request);
-ngx_int_t on_log_request(ngx_http_request_t *request);
+//------------------------------------------------------------------------------
+// on_enter_block
+//------------------------------------------------------------------------------
+ngx_int_t on_enter_block(ngx_http_request_t *request) noexcept;
+
+//------------------------------------------------------------------------------
+// on_log_request
+//------------------------------------------------------------------------------
+ngx_int_t on_log_request(ngx_http_request_t *request) noexcept;
} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_request_instrumentor.h b/opentracing/src/opentracing_request_instrumentor.h
deleted file mode 100644
index eead2408..00000000
--- a/opentracing/src/opentracing_request_instrumentor.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include "opentracing_conf.h"
-
-extern "C" {
-#include
-#include
-#include
-#include
-}
-
-namespace ngx_opentracing {
-struct InstrumentationFailure : std::exception {
- InstrumentationFailure() = default;
- const char *what() const noexcept override {
- return "InstrumentationFailure";
- }
-};
-
-class OpenTracingRequestInstrumentor {
- public:
- OpenTracingRequestInstrumentor(ngx_http_request_t *request,
- ngx_http_core_loc_conf_t *core_loc_conf,
- opentracing_loc_conf_t *loc_conf);
-
- void on_change_block(ngx_http_core_loc_conf_t *core_loc_conf,
- opentracing_loc_conf_t *loc_conf);
-
- void on_log_request();
-
- private:
- ngx_http_request_t *request_;
- opentracing_main_conf_t *main_conf_;
- opentracing_loc_conf_t *loc_conf_;
- std::unique_ptr request_span_;
- std::unique_ptr span_;
-
- void on_exit_block(std::chrono::steady_clock::time_point finish_timestamp =
- std::chrono::steady_clock::now());
-
- void set_request_span_context();
-};
-} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_variable.cpp b/opentracing/src/opentracing_variable.cpp
new file mode 100644
index 00000000..ea337bff
--- /dev/null
+++ b/opentracing/src/opentracing_variable.cpp
@@ -0,0 +1,77 @@
+#include "opentracing_variable.h"
+
+#include "opentracing_context.h"
+#include "utility.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+extern "C" {
+extern ngx_module_t ngx_http_opentracing_module;
+}
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// opentracing_context_variable_name
+//------------------------------------------------------------------------------
+const opentracing::string_view opentracing_context_variable_name{
+ "opentracing_context_"};
+
+//------------------------------------------------------------------------------
+// expand_opentracing_context
+//------------------------------------------------------------------------------
+// Extracts the key specified by the variable's suffix and expands to the
+// corresponding value of the active span context.
+//
+// See propagate_opentracing_context
+static ngx_int_t expand_opentracing_context_variable(
+ ngx_http_request_t* request, ngx_http_variable_value_t* variable_value,
+ uintptr_t data) noexcept try {
+ auto variable_name = to_string_view(*reinterpret_cast(data));
+ auto prefix_length = opentracing_context_variable_name.size();
+
+ opentracing::string_view key{variable_name.data() + prefix_length,
+ variable_name.size() - prefix_length};
+
+ auto context = get_opentracing_context(request);
+ if (context == nullptr) {
+ throw std::runtime_error{"no OpenTracingContext attached to request"};
+ }
+
+ auto span_context_value = context->lookup_span_context_value(key);
+
+ variable_value->len = span_context_value.len;
+ variable_value->valid = 1;
+ variable_value->no_cacheable = 1;
+ variable_value->not_found = 0;
+ variable_value->data = span_context_value.data;
+
+ return NGX_OK;
+} catch (const std::exception& e) {
+ ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
+ "failed to expand %s"
+ " for request %p: %s",
+ opentracing_context_variable_name.data(), request, e.what());
+ return NGX_ERROR;
+}
+
+//------------------------------------------------------------------------------
+// add_variables
+//------------------------------------------------------------------------------
+ngx_int_t add_variables(ngx_conf_t* cf) noexcept {
+ auto opentracing_context = to_ngx_str(opentracing_context_variable_name);
+ auto opentracing_context_var = ngx_http_add_variable(
+ cf, &opentracing_context,
+ NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_NOHASH | NGX_HTTP_VAR_PREFIX);
+ opentracing_context_var->get_handler = expand_opentracing_context_variable;
+ opentracing_context_var->data = 0;
+
+ return NGX_OK;
+}
+} // namespace ngx_opentracing
diff --git a/opentracing/src/opentracing_variable.h b/opentracing/src/opentracing_variable.h
new file mode 100644
index 00000000..8a56b568
--- /dev/null
+++ b/opentracing/src/opentracing_variable.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+#include
+#include
+#include
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// opentracing_context_variable_name
+//------------------------------------------------------------------------------
+extern const opentracing::string_view opentracing_context_variable_name;
+
+//------------------------------------------------------------------------------
+// add_variables
+//------------------------------------------------------------------------------
+ngx_int_t add_variables(ngx_conf_t* cf) noexcept;
+} // namespace ngx_opentracing
diff --git a/opentracing/src/span_context_querier.cpp b/opentracing/src/span_context_querier.cpp
new file mode 100644
index 00000000..ce482398
--- /dev/null
+++ b/opentracing/src/span_context_querier.cpp
@@ -0,0 +1,80 @@
+#include "span_context_querier.h"
+
+#include "utility.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+namespace ngx_opentracing {
+//------------------------------------------------------------------------------
+// lookup_value
+//------------------------------------------------------------------------------
+ngx_str_t SpanContextQuerier::lookup_value(ngx_http_request_t* request,
+ const opentracing::Span& span,
+ opentracing::string_view key) {
+ if (&span != values_span_) {
+ expand_span_context_values(request, span);
+ }
+
+ for (auto& key_value : span_context_expansion_) {
+ if (key_value.first == key) {
+ return to_ngx_str(key_value.second);
+ }
+ }
+
+ auto ngx_key = to_ngx_str(key);
+ ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
+ "no opentracing context value found for span context key %V "
+ "for request %p",
+ &ngx_key, request);
+ return {};
+}
+
+//------------------------------------------------------------------------------
+// SpanContextValueExpander
+//------------------------------------------------------------------------------
+namespace {
+class SpanContextValueExpander : public opentracing::HTTPHeadersWriter {
+ public:
+ explicit SpanContextValueExpander(
+ std::vector>& span_context_expansion)
+ : span_context_expansion_{span_context_expansion} {}
+
+ opentracing::expected Set(
+ opentracing::string_view key,
+ opentracing::string_view value) const override {
+ std::string key_copy;
+ key_copy.reserve(key.size());
+ std::transform(std::begin(key), std::end(key), std::back_inserter(key_copy),
+ header_transform);
+
+ span_context_expansion_.emplace_back(std::move(key_copy), value);
+ return {};
+ }
+
+ private:
+ std::vector>& span_context_expansion_;
+};
+} // namespace
+
+//------------------------------------------------------------------------------
+// expand_span_context_values
+//------------------------------------------------------------------------------
+void SpanContextQuerier::expand_span_context_values(
+ ngx_http_request_t* request, const opentracing::Span& span) {
+ values_span_ = &span;
+ span_context_expansion_.clear();
+ SpanContextValueExpander carrier{span_context_expansion_};
+ auto was_successful = span.tracer().Inject(span.context(), carrier);
+ if (!was_successful) {
+ ngx_log_error(NGX_LOG_ERR, request->connection->log, 0,
+ "Tracer.inject() failed for request %p: %s", request,
+ was_successful.error().message().c_str());
+ }
+}
+} // namespace ngx_opentracing
diff --git a/opentracing/src/span_context_querier.h b/opentracing/src/span_context_querier.h
new file mode 100644
index 00000000..12399213
--- /dev/null
+++ b/opentracing/src/span_context_querier.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "opentracing_conf.h"
+
+#include
+
+#include
+#include
+
+extern "C" {
+#include
+#include
+#include
+#include
+}
+
+namespace ngx_opentracing {
+class SpanContextQuerier {
+ public:
+ SpanContextQuerier() noexcept = default;
+
+ ngx_str_t lookup_value(ngx_http_request_t* request,
+ const opentracing::Span& span,
+ opentracing::string_view key);
+
+ private:
+ const opentracing::Span* values_span_ = nullptr;
+
+ std::vector> span_context_expansion_;
+
+ void expand_span_context_values(ngx_http_request_t* request,
+ const opentracing::Span& span);
+};
+} // namespace ngx_opentracing
diff --git a/opentracing/src/utility.h b/opentracing/src/utility.h
index 0e91c374..9adc5931 100644
--- a/opentracing/src/utility.h
+++ b/opentracing/src/utility.h
@@ -2,6 +2,8 @@
#pragma once
+#include
+
#include
#include
#include
@@ -20,12 +22,26 @@ inline std::string to_string(const ngx_str_t &ngx_str) {
return {reinterpret_cast(ngx_str.data), ngx_str.len};
}
+//------------------------------------------------------------------------------
+// to_string_view
+//------------------------------------------------------------------------------
+inline opentracing::string_view to_string_view(ngx_str_t s) {
+ return {reinterpret_cast(s.data), s.len};
+}
+
//------------------------------------------------------------------------------
// to_ngx_str
//------------------------------------------------------------------------------
// Convert a std::string to an ngx_str_t
ngx_str_t to_ngx_str(ngx_pool_t *pool, const std::string &s);
+inline ngx_str_t to_ngx_str(opentracing::string_view s) {
+ ngx_str_t result;
+ result.len = s.size();
+ result.data = reinterpret_cast