Start application
DD_API_KEY=... docker-compose up --build app
Test application traces To
ab -c 10 -n 200 http://127.0.0.1:8080/
from flask import Flask | |
import concurrent.futures | |
import urllib.request | |
URLS = ['https://httpbin.org/bytes/1024', | |
'https://httpbin.org/bytes/4096'] | |
# Retrieve a single page and report the URL and contents | |
def load_url(url, timeout): | |
with urllib.request.urlopen(url, timeout=timeout) as conn: | |
return conn.read() | |
def use_futures(): | |
# We can use a with statement to ensure threads are cleaned up promptly | |
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: | |
# Start the load operations and mark each future with its URL | |
future_to_url = {executor.submit(load_url, url, 60): url for url in URLS} | |
for future in concurrent.futures.as_completed(future_to_url): | |
url = future_to_url[future] | |
try: | |
data = future.result() | |
except Exception as exc: | |
print('{} generated an exception: {}\n'.format(url, exc)) | |
else: | |
print('{} page is {} bytes\n'.format(url, len(data))) | |
def no_futures(): | |
for url in URLS: | |
print('No future', load_url(url, 60)) | |
app = Flask(__name__) | |
@app.route("/") | |
def hello(): | |
use_futures() | |
# no_futures() | |
return u'Hello!' | |
if __name__ == "__main__": | |
app.run() |
version: '3' | |
services: | |
app: | |
build: . | |
depends_on: | |
- agent | |
environment: | |
- 'DATADOG_TRACE_ENABLED=true' | |
- 'DATADOG_TRACE_AGENT_HOSTNAME=agent' | |
- 'DATADOG_PATCH_MODULES=futures:true,gevent:true' | |
ports: | |
- '8080:8080' | |
agent: | |
image: 'datadog/docker-dd-agent' | |
environment: | |
- 'DD_APM_ENABLED=true' | |
- 'DD_HOSTNAME=multiple-traces' | |
- 'DD_TAGS=env:dev' | |
- 'DD_API_KEY=${DD_API_KEY}' | |
ports: | |
- 8125 | |
- 8126 | |
volumes: | |
- '/var/run/docker.sock:/var/run/docker.sock:ro' | |
- '/proc/:/host/proc/:ro' | |
- '/sys/fs/cgroup/:/host/sys/fs/cgroup:ro' |
FROM ubuntu:trusty | |
WORKDIR /opt/code | |
ENV PYENV_ROOT="/opt/pyenv" \ | |
PATH="/opt/pyenv/bin:/opt/pyenv/shims:$PATH" \ | |
LC_ALL="C.UTF-8" \ | |
LANG="C.UTF-8" | |
RUN apt-get update && apt-get install -y --no-install-recommends \ | |
build-essential \ | |
ca-certificates \ | |
curl \ | |
git \ | |
libbz2-dev \ | |
libffi-dev \ | |
libncurses5-dev \ | |
libncursesw5-dev \ | |
libreadline-dev \ | |
libsqlite3-dev \ | |
libssl-dev \ | |
llvm \ | |
make \ | |
netbase \ | |
pkg-config \ | |
tk-dev \ | |
wget \ | |
xz-utils \ | |
zlib1g-dev \ | |
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* | |
RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash \ | |
&& pyenv install 3.6.7 \ | |
&& pyenv global 3.6.7 | |
COPY requirements.txt . | |
RUN pip install -r requirements.txt | |
COPY app.py . | |
COPY Gunicorn . | |
COPY gunicorn.ini . | |
EXPOSE 8080 | |
ENV DATADOG_TRACE_DEBUG true | |
# CMD ["ddtrace-run", "python", "Gunicorn"] | |
CMD ["ddtrace-run", "gunicorn", "--log-level", "debug", "-c", "gunicorn.ini", "app:app"] |
from gunicorn.app.base import Application | |
from gunicorn import util | |
from os import getenv | |
GUNICORN_CONFIG = { | |
'bind': '0.0.0.0:8080', | |
'workers': 1, | |
'worker-class': 'gevent', | |
'threads': 8, | |
'timeout': 120, | |
'sendfile': False, # since it's disabled in Nginx by default | |
} | |
class GunicornApp(Application): | |
def __init__(self, options=None): | |
self.options = options or {} | |
self.usage = None | |
self.callable = None | |
super().__init__() | |
self.do_load_config() | |
def init(self, *args): | |
cfg = {} | |
for k, v in self.options.items(): | |
if k.lower() in self.cfg.settings and v is not None: | |
cfg[k.lower()] = v | |
return cfg | |
def load(self): | |
return util.import_app("app:app") | |
if __name__ == '__main__': | |
options = GUNICORN_CONFIG | |
if getenv('DEBUG') is not None: | |
options['reload'] = True | |
GunicornApp(options).run() |
bind = '0.0.0.0:8080' | |
workers = 1 | |
worker_class = 'gevent' | |
threads = 8 | |
timeout = 120 | |
sendfile = False # since it's disabled in Nginx by default |
bind = "0.0.0.0:8080" | |
workers = 1 | |
worker_class = "gevent" | |
threads = 8 | |
timeout = 120 | |
sendfile = False |
ddtrace==0.17.0 | |
Flask==0.12 | |
future==0.17.1 | |
gevent==1.2.2 | |
gunicorn==19.7.1 |