Skip to content

Instantly share code, notes, and snippets.

@majorgreys
Last active Dec 14, 2018
Embed
What would you like to do?

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment