From 2be58f30c0281d23bb408a4b3cf131ae54341d60 Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Thu, 23 Jun 2016 17:33:41 -0400 Subject: [PATCH 1/7] Reorganize package for simpler tests and packaging --- setup.cfg | 2 ++ setup.py | 20 +++++++------------ tests/__init__.py | 0 tests/contrib/__init__.py | 0 tests/contrib/elasticsearch/__init__.py | 0 .../contrib/elasticsearch/test.py | 10 +++++----- tests/contrib/flask/__init__.py | 0 .../contrib/flask/test_flask.py | 7 ++++--- .../contrib/flask/test_templates/err.html | 0 .../contrib/flask/test_templates/test.html | 0 tests/contrib/psycopg/__init__.py | 0 .../contrib/psycopg/test_psycopg.py | 6 ++++-- tests/contrib/pylons/__init__.py | 0 .../contrib/pylons/test_pylons.py | 8 ++++---- tests/contrib/sqlite3/__init__.py | 0 .../contrib/sqlite3/test_sqlite3.py | 7 ++++--- {ddtrace => tests}/test_buffer.py | 3 +-- {ddtrace => tests}/test_span.py | 4 ++-- {ddtrace => tests}/test_tracer.py | 2 +- 19 files changed, 34 insertions(+), 35 deletions(-) create mode 100644 setup.cfg create mode 100644 tests/__init__.py create mode 100644 tests/contrib/__init__.py create mode 100644 tests/contrib/elasticsearch/__init__.py rename {ddtrace => tests}/contrib/elasticsearch/test.py (93%) create mode 100644 tests/contrib/flask/__init__.py rename {ddtrace => tests}/contrib/flask/test_flask.py (98%) rename {ddtrace => tests}/contrib/flask/test_templates/err.html (100%) rename {ddtrace => tests}/contrib/flask/test_templates/test.html (100%) create mode 100644 tests/contrib/psycopg/__init__.py rename {ddtrace => tests}/contrib/psycopg/test_psycopg.py (96%) create mode 100644 tests/contrib/pylons/__init__.py rename {ddtrace => tests}/contrib/pylons/test_pylons.py (92%) create mode 100644 tests/contrib/sqlite3/__init__.py rename {ddtrace => tests}/contrib/sqlite3/test_sqlite3.py (94%) rename {ddtrace => tests}/test_buffer.py (91%) rename {ddtrace => tests}/test_span.py (97%) rename {ddtrace => tests}/test_tracer.py (98%) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000000..0656f066541 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[nosetests] +verbosity=2 diff --git a/setup.py b/setup.py index ae3711fd903..2afa67f8954 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,14 @@ -from setuptools import setup +from setuptools import setup, find_packages tests_require = [ 'nose', - #'psycopg2', - #'sqlite3' 'flask', 'blinker', + + # Not installed as long as we don't hace a proper CI setup + #'psycopg2', + #'sqlite3', + #'elasticsearch'. ] setup( @@ -16,16 +19,7 @@ author='Datadog, Inc.', author_email='dev@datadoghq.com', license='BSD', - packages=[ - 'ddtrace', - 'ddtrace.contrib', - 'ddtrace.contrib.elasticsearch', - 'ddtrace.contrib.flask', - 'ddtrace.contrib.psycopg', - 'ddtrace.contrib.pylons', - 'ddtrace.contrib.sqlite3', - 'ddtrace.ext', - ], + packages=find_packages(exclude=['tests*']), tests_require=tests_require, test_suite="nose.collector", ) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/contrib/__init__.py b/tests/contrib/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/contrib/elasticsearch/__init__.py b/tests/contrib/elasticsearch/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ddtrace/contrib/elasticsearch/test.py b/tests/contrib/elasticsearch/test.py similarity index 93% rename from ddtrace/contrib/elasticsearch/test.py rename to tests/contrib/elasticsearch/test.py index 6668f953f56..e50c130e2e1 100644 --- a/ddtrace/contrib/elasticsearch/test.py +++ b/tests/contrib/elasticsearch/test.py @@ -7,11 +7,11 @@ except ImportError: elasticsearch = None -from . import metadata -from .transport import get_traced_transport -from ...tracer import Tracer -from ...test_tracer import DummyWriter +from ddtrace.contrib.elasticsearch import metadata +from ddtrace.contrib.elasticsearch import get_traced_transport +from ddtrace.tracer import Tracer +from ...test_tracer import DummyWriter class ElasticsearchTest(unittest.TestCase): @@ -28,7 +28,7 @@ class ElasticsearchTest(unittest.TestCase): def setUp(self): """Prepare ES""" if not elasticsearch: - self.SkipTest("elasticsearch module isn't available") + raise unittest.SkipTest("elasticsearch module isn't available") es = elasticsearch.Elasticsearch() es.indices.delete(index=self.ES_INDEX, ignore=[400, 404]) diff --git a/tests/contrib/flask/__init__.py b/tests/contrib/flask/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ddtrace/contrib/flask/test_flask.py b/tests/contrib/flask/test_flask.py similarity index 98% rename from ddtrace/contrib/flask/test_flask.py rename to tests/contrib/flask/test_flask.py index 9f011239b1e..2128bc5155c 100644 --- a/ddtrace/contrib/flask/test_flask.py +++ b/tests/contrib/flask/test_flask.py @@ -6,10 +6,11 @@ from flask import Flask, render_template from nose.tools import eq_ -from ... import Tracer -from ...contrib.flask import TraceMiddleware +from ddtrace import Tracer +from ddtrace.contrib.flask import TraceMiddleware +from ddtrace.ext import http, errors + from ...test_tracer import DummyWriter -from ...ext import http, errors log = logging.getLogger(__name__) diff --git a/ddtrace/contrib/flask/test_templates/err.html b/tests/contrib/flask/test_templates/err.html similarity index 100% rename from ddtrace/contrib/flask/test_templates/err.html rename to tests/contrib/flask/test_templates/err.html diff --git a/ddtrace/contrib/flask/test_templates/test.html b/tests/contrib/flask/test_templates/test.html similarity index 100% rename from ddtrace/contrib/flask/test_templates/test.html rename to tests/contrib/flask/test_templates/test.html diff --git a/tests/contrib/psycopg/__init__.py b/tests/contrib/psycopg/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ddtrace/contrib/psycopg/test_psycopg.py b/tests/contrib/psycopg/test_psycopg.py similarity index 96% rename from ddtrace/contrib/psycopg/test_psycopg.py rename to tests/contrib/psycopg/test_psycopg.py index 02ac4f7c62e..18d2609dc1b 100644 --- a/ddtrace/contrib/psycopg/test_psycopg.py +++ b/tests/contrib/psycopg/test_psycopg.py @@ -3,10 +3,12 @@ from nose.tools import eq_ from nose.plugins.skip import SkipTest -from ... import Tracer -from ...contrib.psycopg import connection_factory +from ddtrace import Tracer +from ddtrace.contrib.psycopg import connection_factory + from ...test_tracer import DummyWriter + def test_wrap(): try: diff --git a/tests/contrib/pylons/__init__.py b/tests/contrib/pylons/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ddtrace/contrib/pylons/test_pylons.py b/tests/contrib/pylons/test_pylons.py similarity index 92% rename from ddtrace/contrib/pylons/test_pylons.py rename to tests/contrib/pylons/test_pylons.py index a487a49605e..5df6e83d928 100644 --- a/ddtrace/contrib/pylons/test_pylons.py +++ b/tests/contrib/pylons/test_pylons.py @@ -3,11 +3,11 @@ from nose.tools import eq_ -from ... import Tracer -from ...contrib.pylons import PylonsTraceMiddleware -from ...test_tracer import DummyWriter -from ...ext import http +from ddtrace import Tracer +from ddtrace.contrib.pylons import PylonsTraceMiddleware +from ddtrace.ext import http +from ...test_tracer import DummyWriter class FakeWSGIApp(object): diff --git a/tests/contrib/sqlite3/__init__.py b/tests/contrib/sqlite3/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/ddtrace/contrib/sqlite3/test_sqlite3.py b/tests/contrib/sqlite3/test_sqlite3.py similarity index 94% rename from ddtrace/contrib/sqlite3/test_sqlite3.py rename to tests/contrib/sqlite3/test_sqlite3.py index 6b4f65b30cc..c23e4112f4d 100644 --- a/ddtrace/contrib/sqlite3/test_sqlite3.py +++ b/tests/contrib/sqlite3/test_sqlite3.py @@ -4,10 +4,11 @@ from nose.tools import eq_ -from ... import Tracer -from ...contrib.sqlite3 import connection_factory +from ddtrace import Tracer +from ddtrace.contrib.sqlite3 import connection_factory +from ddtrace.ext import errors + from ...test_tracer import DummyWriter -from ...ext import errors def test_foo(): writer = DummyWriter() diff --git a/ddtrace/test_buffer.py b/tests/test_buffer.py similarity index 91% rename from ddtrace/test_buffer.py rename to tests/test_buffer.py index c7b8677fba7..1ba94c2c093 100644 --- a/ddtrace/test_buffer.py +++ b/tests/test_buffer.py @@ -1,10 +1,9 @@ - import random import threading from nose.tools import eq_ -from .buffer import ThreadLocalSpanBuffer +from ddtrace.buffer import ThreadLocalSpanBuffer def _get_test_span(): diff --git a/ddtrace/test_span.py b/tests/test_span.py similarity index 97% rename from ddtrace/test_span.py rename to tests/test_span.py index d5bde66df40..0095c5ced23 100644 --- a/ddtrace/test_span.py +++ b/tests/test_span.py @@ -2,8 +2,8 @@ from nose.tools import eq_ -from .span import Span -from .ext import errors +from ddtrace.span import Span +from ddtrace.ext import errors def test_ids(): diff --git a/ddtrace/test_tracer.py b/tests/test_tracer.py similarity index 98% rename from ddtrace/test_tracer.py rename to tests/test_tracer.py index 1d8ace16583..b43b95fdee3 100644 --- a/ddtrace/test_tracer.py +++ b/tests/test_tracer.py @@ -5,7 +5,7 @@ import time from nose.tools import eq_ -from .tracer import Tracer +from ddtrace.tracer import Tracer def test_tracer_vars(): From f5f755e1e0a8a7c18ef1f9ec7c8e8b4561876aad Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Thu, 23 Jun 2016 17:42:55 -0400 Subject: [PATCH 2/7] Add CircleCI badge to README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000000..a8361623b5a --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# dd-trace-py + +[![CircleCI](https://circleci.com/gh/DataDog/dd-trace-py.svg?style=svg&circle-token=f9bf80ce9281bc638c6f7465512d65c96ddc075a)](https://circleci.com/gh/DataDog/dd-trace-py) From 78c0e73692647d966edb84fcd176866b990532c5 Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Fri, 24 Jun 2016 11:06:02 -0400 Subject: [PATCH 3/7] Test 2.7 and 3.4 in CircleCI --- circle.yml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 circle.yml diff --git a/circle.yml b/circle.yml new file mode 100644 index 00000000000..a13c37c004a --- /dev/null +++ b/circle.yml @@ -0,0 +1,7 @@ +machine: + post: + - pyenv global 2.7.9 3.4.2 +test: + override: + - python2.7 setup.py test + - python3.4 setup.py test From 1fb444c906c155911bb552010d616ea29e9f93bb Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Fri, 24 Jun 2016 11:40:16 -0400 Subject: [PATCH 4/7] Fix on Python 3.4 --- ddtrace/compat.py | 31 +++++++++++++++++++++++-------- ddtrace/reporter.py | 4 ++-- ddtrace/span.py | 9 ++++----- tests/contrib/flask/test_flask.py | 14 ++++++-------- tests/test_span.py | 2 +- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/ddtrace/compat.py b/ddtrace/compat.py index 06db272bd25..9a30b96c666 100644 --- a/ddtrace/compat.py +++ b/ddtrace/compat.py @@ -1,15 +1,24 @@ import sys PY2 = sys.version_info[0] == 2 + +stringify = str + if PY2: from urllib import urlencode + import httplib + stringify = unicode + from Queue import Queue + try: + from cStringIO import StringIO + except ImportError: + from StringIO import StringIO else: + from queue import Queue from urllib.parse import urlencode + import http.client as httplib + from io import StringIO -try: - from queue import Queue -except ImportError: - from Queue import Queue try: import ujson as json @@ -19,7 +28,13 @@ except ImportError: import json -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO + +__all__ = [ + 'PY2', + 'urlencode', + 'httplib', + 'stringify', + 'Queue', + 'StringIO', + 'json', +] diff --git a/ddtrace/reporter.py b/ddtrace/reporter.py index 88428d5fe51..004d6545759 100644 --- a/ddtrace/reporter.py +++ b/ddtrace/reporter.py @@ -5,14 +5,14 @@ """ import atexit -import httplib +from .compat import httplib import logging import threading from time import sleep, time import os # project -from compat import Queue, json +from .compat import Queue, json DEFAULT_TIMEOUT = 10 diff --git a/ddtrace/span.py b/ddtrace/span.py index 9f88de460c7..0da43e25341 100644 --- a/ddtrace/span.py +++ b/ddtrace/span.py @@ -1,11 +1,10 @@ - -from compat import StringIO import logging import random import sys import time import traceback +from .compat import StringIO, stringify from .ext import errors @@ -97,9 +96,9 @@ def set_tag(self, key, value): be ignored. """ try: - self.meta[key] = unicode(value) + self.meta[key] = stringify(value) except Exception: - log.warn("error setting tag. ignoring", exc_info=True) + log.warning("error setting tag. ignoring", exc_info=True) def get_tag(self, key): """ Return the given tag or None if it doesn't exist""" @@ -110,7 +109,7 @@ def set_tags(self, tags): must be strings (or stringable) """ if tags: - for k, v in tags.iteritems(): + for k, v in iter(tags.items()): self.set_tag(k, v) # backwards compatilibility, kill this diff --git a/tests/contrib/flask/test_flask.py b/tests/contrib/flask/test_flask.py index 2128bc5155c..8b4050940b8 100644 --- a/tests/contrib/flask/test_flask.py +++ b/tests/contrib/flask/test_flask.py @@ -64,7 +64,7 @@ def handle_my_exception(e): # add tracing to the app (we use a global app to help ensure multiple requests # work) service = "test.flask.service" -assert not writer.pop() # should always be empty +assert not writer.pop() # should always be empty traced_app = TraceMiddleware(app, tracer, service=service) # make the app testable @@ -77,8 +77,6 @@ class TestFlask(object): def setUp(self): # ensure the last test didn't leave any trash spans = writer.pop() - assert not spans, spans - assert not tracer.current_span(), tracer.current_span() def test_child(self): start = time.time() @@ -86,7 +84,7 @@ def test_child(self): end = time.time() # ensure request worked eq_(rv.status_code, 200) - eq_(rv.data, 'child') + eq_(rv.data, b'child') # ensure trace worked spans = writer.pop() eq_(len(spans), 2) @@ -120,7 +118,7 @@ def test_success(self): # ensure request worked eq_(rv.status_code, 200) - eq_(rv.data, 'hello') + eq_(rv.data, b'hello') # ensure trace worked assert not tracer.current_span(), tracer.current_span().pprint() @@ -141,7 +139,7 @@ def test_template(self): # ensure request worked eq_(rv.status_code, 200) - eq_(rv.data, 'hello earth') + eq_(rv.data, b'hello earth') # ensure trace worked assert not tracer.current_span(), tracer.current_span().pprint() @@ -192,7 +190,7 @@ def test_error(self): # ensure the request itself worked eq_(rv.status_code, 500) - eq_(rv.data, 'error') + eq_(rv.data, b'error') # ensure the request was traced. assert not tracer.current_span() @@ -230,5 +228,5 @@ def test_fatal(self): eq_(s.meta.get(http.STATUS_CODE), '500') assert "ZeroDivisionError" in s.meta.get(errors.ERROR_TYPE) msg = s.meta.get(errors.ERROR_MSG) - assert "integer division" in msg, msg + assert "by zero" in msg, msg diff --git a/tests/test_span.py b/tests/test_span.py index 0095c5ced23..9322f3f177b 100644 --- a/tests/test_span.py +++ b/tests/test_span.py @@ -68,7 +68,7 @@ def test_traceback_with_error(): assert s.error assert 'by zero' in s.get_tag(errors.ERROR_MSG) - eq_("exceptions.ZeroDivisionError", s.get_tag(errors.ERROR_TYPE)) + assert "ZeroDivisionError" in s.get_tag(errors.ERROR_TYPE) assert s.get_tag(errors.ERROR_STACK) def test_traceback_without_error(): From be5524972086bdabb633b18cf94c2d65acd08650 Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Fri, 24 Jun 2016 14:26:19 -0400 Subject: [PATCH 5/7] Test elasticsearch integration in CircleCI --- circle.yml | 3 +++ setup.py | 2 +- tests/contrib/elasticsearch/test.py | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/circle.yml b/circle.yml index a13c37c004a..06fd4085e7f 100644 --- a/circle.yml +++ b/circle.yml @@ -1,7 +1,10 @@ machine: + services: + - docker post: - pyenv global 2.7.9 3.4.2 test: override: + - docker run -d -p 9200:9200 elasticsearch:2.3; sleep 10 - python2.7 setup.py test - python3.4 setup.py test diff --git a/setup.py b/setup.py index 2afa67f8954..0f32deb3cfd 100644 --- a/setup.py +++ b/setup.py @@ -4,11 +4,11 @@ 'nose', 'flask', 'blinker', + 'elasticsearch', # Not installed as long as we don't hace a proper CI setup #'psycopg2', #'sqlite3', - #'elasticsearch'. ] setup( diff --git a/tests/contrib/elasticsearch/test.py b/tests/contrib/elasticsearch/test.py index e50c130e2e1..ad420017c3e 100644 --- a/tests/contrib/elasticsearch/test.py +++ b/tests/contrib/elasticsearch/test.py @@ -88,8 +88,8 @@ def test_elasticsearch(self): eq_(span.resource, "GET /%s/%s/_search" % (self.ES_INDEX, self.ES_TYPE)) eq_(span.get_tag(metadata.METHOD), "GET") eq_(span.get_tag(metadata.URL), "/%s/%s/_search" % (self.ES_INDEX, self.ES_TYPE)) - eq_(span.get_tag(metadata.PARAMS), 'sort=name%3Adesc&size=100') - eq_(span.get_tag(metadata.BODY), '{"query":{"match_all":{}}}') + eq_(span.get_tag(metadata.BODY).replace(" ", ""), '{"query":{"match_all":{}}}') + eq_(set(span.get_tag(metadata.PARAMS).split('&')), {'sort=name%3Adesc', 'size=100'}) self.assertTrue(int(span.get_tag(metadata.TOOK)) > 0) From 013d5ccad7195a74a8273fbd6a13392ccb616b6e Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Fri, 24 Jun 2016 14:46:18 -0400 Subject: [PATCH 6/7] Test psycopg integration in CircleCI --- circle.yml | 7 ++++++- setup.py | 5 +---- tests/contrib/psycopg/test_psycopg.py | 10 +++++----- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/circle.yml b/circle.yml index 06fd4085e7f..22dd1776bc5 100644 --- a/circle.yml +++ b/circle.yml @@ -3,8 +3,13 @@ machine: - docker post: - pyenv global 2.7.9 3.4.2 +dependencies: + pre: + - sudo service postgresql stop test: override: - - docker run -d -p 9200:9200 elasticsearch:2.3; sleep 10 + - docker run -d -p 9200:9200 elasticsearch:2.3 + - docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=test -e POSTGRES_USER=test -e POSTGRES_DB=test postgres:9.5 + - sleep 10 - python2.7 setup.py test - python3.4 setup.py test diff --git a/setup.py b/setup.py index 0f32deb3cfd..6a8081c5a81 100644 --- a/setup.py +++ b/setup.py @@ -5,10 +5,7 @@ 'flask', 'blinker', 'elasticsearch', - - # Not installed as long as we don't hace a proper CI setup - #'psycopg2', - #'sqlite3', + 'psycopg2', ] setup( diff --git a/tests/contrib/psycopg/test_psycopg.py b/tests/contrib/psycopg/test_psycopg.py index 18d2609dc1b..eae7349691d 100644 --- a/tests/contrib/psycopg/test_psycopg.py +++ b/tests/contrib/psycopg/test_psycopg.py @@ -20,11 +20,11 @@ def test_wrap(): tracer = Tracer(writer=writer) params = { - 'host' : 'localhost', - 'port' : 5432, - 'user' : 'dog', - 'password' :'dog', - 'dbname' : 'dogdata', + 'host': 'localhost', + 'port': 5432, + 'user': 'test', + 'password':'test', + 'dbname': 'test', } services = ["db", "another"] From 2d60bc57a05fb83989312172d286231fa6ecbd05 Mon Sep 17 00:00:00 2001 From: Benjamin Fernandes Date: Mon, 27 Jun 2016 12:39:42 +0200 Subject: [PATCH 7/7] Remove unecessary sleep in CircleCI setup --- circle.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/circle.yml b/circle.yml index 22dd1776bc5..0379c2d6573 100644 --- a/circle.yml +++ b/circle.yml @@ -10,6 +10,5 @@ test: override: - docker run -d -p 9200:9200 elasticsearch:2.3 - docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=test -e POSTGRES_USER=test -e POSTGRES_DB=test postgres:9.5 - - sleep 10 - python2.7 setup.py test - python3.4 setup.py test