From 4679dc3c332c1a63f6e0bf0af24402bd601e680f Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 16:33:01 -0400 Subject: [PATCH 01/10] add type to span pprint --- ddtrace/span.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ddtrace/span.py b/ddtrace/span.py index fa0e57c6223..24134e35d5e 100644 --- a/ddtrace/span.py +++ b/ddtrace/span.py @@ -120,6 +120,7 @@ def pprint(self): ("parent_id", self.parent_id), ("service", self.service), ("resource", self.resource), + ('type', self.span_type), ("start", self.start), ("end", "" if not self.duration else self.start + self.duration), ("duration", self.duration), From 2d5475ed37afbe3619d2b50746546474013dcb21 Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 16:33:14 -0400 Subject: [PATCH 02/10] fix import paths --- ddtrace/compat.py | 7 +++++ ddtrace/contrib/flask/__init__.py | 6 ++-- ddtrace/contrib/flask/test_flask.py | 8 +++--- ddtrace/contrib/psycopg/__init__.py | 19 +++++++++++-- ddtrace/contrib/psycopg/test_psycopg.py | 13 +++++---- ddtrace/contrib/pylons/__init__.py | 2 +- ddtrace/contrib/pylons/test_pylons.py | 8 +++--- ddtrace/contrib/sqlite3/__init__.py | 2 +- ddtrace/contrib/sqlite3/test_sqlite3.py | 6 ++-- ddtrace/reporter.py | 4 +-- ddtrace/tracer.py | 1 + setup.py | 37 +++++++++++++++++++------ 12 files changed, 80 insertions(+), 33 deletions(-) diff --git a/ddtrace/compat.py b/ddtrace/compat.py index 5ea8599bf80..1155d3cfc82 100644 --- a/ddtrace/compat.py +++ b/ddtrace/compat.py @@ -4,3 +4,10 @@ except ImportError: from Queue import Queue +try: + import ujson as json +except ImportError: + try: + import simplejson as json + except ImportError: + import json diff --git a/ddtrace/contrib/flask/__init__.py b/ddtrace/contrib/flask/__init__.py index 2c5976eaad1..284e287e9ad 100644 --- a/ddtrace/contrib/flask/__init__.py +++ b/ddtrace/contrib/flask/__init__.py @@ -10,7 +10,7 @@ import logging # project -from tracer.ext import http +from ...ext import http # 3p from flask import g, request, signals @@ -20,6 +20,7 @@ class TraceMiddleware(object): def __init__(self, app, tracer, service="flask", use_signals=True): self.app = app + self.app.logger.info("initializing trace middleware") # save our traces. self._tracer = tracer @@ -30,6 +31,7 @@ def __init__(self, app, tracer, service="flask", use_signals=True): if self.use_signals and signals.signals_available: # if we're using signals, and things are correctly installed, use # signal hooks to track the responses. + self.app.logger.info("connecting trace signals") signals.request_started.connect(self._request_started, sender=self.app) signals.request_finished.connect(self._request_finished, sender=self.app) signals.got_request_exception.connect(self._request_exception, sender=self.app) @@ -37,7 +39,7 @@ def __init__(self, app, tracer, service="flask", use_signals=True): signals.template_rendered.connect(self._template_done, sender=self.app) else: if self.use_signals: # warn the user that signals lib isn't installed - self.app.logger.warn(_blinker_not_installed_msg) + self.app.logger.info(_blinker_not_installed_msg) # Fallback to using after request hook. Unfortunately, this won't # handle exceptions. diff --git a/ddtrace/contrib/flask/test_flask.py b/ddtrace/contrib/flask/test_flask.py index 9fe5cbb9877..f883b2449c0 100644 --- a/ddtrace/contrib/flask/test_flask.py +++ b/ddtrace/contrib/flask/test_flask.py @@ -6,10 +6,10 @@ from flask import Flask, render_template from nose.tools import eq_ -from tracer import Tracer -from tracer.contrib.flask import TraceMiddleware -from tracer.test_tracer import DummyWriter -from tracer.ext import http +from ... import Tracer +from ...contrib.flask import TraceMiddleware +from ...test_tracer import DummyWriter +from ...ext import http log = logging.getLogger(__name__) diff --git a/ddtrace/contrib/psycopg/__init__.py b/ddtrace/contrib/psycopg/__init__.py index 2ae759567ec..be44f475009 100644 --- a/ddtrace/contrib/psycopg/__init__.py +++ b/ddtrace/contrib/psycopg/__init__.py @@ -4,12 +4,21 @@ # stdlib import functools +import logging -from tracer.ext import net -from tracer.ext import sql as sqlx +from ...ext import net +from ...ext import sql as sqlx # 3p -from psycopg2.extensions import connection, cursor +_installed = False +try: + from psycopg2.extensions import connection, cursor + _installed = True +except ImportError: + connection, cursor = object, object + + +log = logging.getLogger(__name__) def connection_factory(tracer, service="postgres"): @@ -19,6 +28,10 @@ def connection_factory(tracer, service="postgres"): >>> factory = connection_factor(my_tracer, service="my_db_service") >>> conn = pyscopg2.connect(..., connection_factory=factory) """ + if not _installed: + log.info("missing psycopg import") + return None + return functools.partial(TracedConnection, datadog_tracer=tracer, datadog_service=service, diff --git a/ddtrace/contrib/psycopg/test_psycopg.py b/ddtrace/contrib/psycopg/test_psycopg.py index 1b0bf7ee3bf..02ac4f7c62e 100644 --- a/ddtrace/contrib/psycopg/test_psycopg.py +++ b/ddtrace/contrib/psycopg/test_psycopg.py @@ -1,15 +1,18 @@ import time -import psycopg2 from nose.tools import eq_ from nose.plugins.skip import SkipTest -from tracer import Tracer -from tracer.contrib.psycopg import connection_factory -from tracer.test_tracer import DummyWriter +from ... import Tracer +from ...contrib.psycopg import connection_factory +from ...test_tracer import DummyWriter def test_wrap(): - raise SkipTest("matt") + + try: + import psycopg2 + except ImportError: + raise SkipTest("missing psycopg") writer = DummyWriter() tracer = Tracer(writer=writer) diff --git a/ddtrace/contrib/pylons/__init__.py b/ddtrace/contrib/pylons/__init__.py index b1df4965eb3..e73231a67ff 100644 --- a/ddtrace/contrib/pylons/__init__.py +++ b/ddtrace/contrib/pylons/__init__.py @@ -1,6 +1,6 @@ import logging -from tracer.ext import http +from ...ext import http log = logging.getLogger(__name__) diff --git a/ddtrace/contrib/pylons/test_pylons.py b/ddtrace/contrib/pylons/test_pylons.py index af6211b9b11..a487a49605e 100644 --- a/ddtrace/contrib/pylons/test_pylons.py +++ b/ddtrace/contrib/pylons/test_pylons.py @@ -3,10 +3,10 @@ from nose.tools import eq_ -from tracer import Tracer -from tracer.contrib.pylons import PylonsTraceMiddleware -from tracer.test_tracer import DummyWriter -from tracer.ext import http +from ... import Tracer +from ...contrib.pylons import PylonsTraceMiddleware +from ...test_tracer import DummyWriter +from ...ext import http class FakeWSGIApp(object): diff --git a/ddtrace/contrib/sqlite3/__init__.py b/ddtrace/contrib/sqlite3/__init__.py index 79d603ebd08..9f6722f30fa 100644 --- a/ddtrace/contrib/sqlite3/__init__.py +++ b/ddtrace/contrib/sqlite3/__init__.py @@ -2,7 +2,7 @@ import functools from sqlite3 import Connection, Cursor -from tracer.ext import sql as sqlx +from ...ext import sql as sqlx def connection_factory(tracer, service="sqlite3"): diff --git a/ddtrace/contrib/sqlite3/test_sqlite3.py b/ddtrace/contrib/sqlite3/test_sqlite3.py index 98403fdee12..55c3a4e2820 100644 --- a/ddtrace/contrib/sqlite3/test_sqlite3.py +++ b/ddtrace/contrib/sqlite3/test_sqlite3.py @@ -4,9 +4,9 @@ from nose.tools import eq_ -from tracer import Tracer -from tracer.contrib.sqlite3 import connection_factory -from tracer.test_tracer import DummyWriter +from ... import Tracer +from ...contrib.sqlite3 import connection_factory +from ...test_tracer import DummyWriter def test_foo(): writer = DummyWriter() diff --git a/ddtrace/reporter.py b/ddtrace/reporter.py index 303bbebf1bc..88428d5fe51 100644 --- a/ddtrace/reporter.py +++ b/ddtrace/reporter.py @@ -9,10 +9,10 @@ import logging import threading from time import sleep, time -import ujson as json import os -from compat import Queue +# project +from compat import Queue, json DEFAULT_TIMEOUT = 10 diff --git a/ddtrace/tracer.py b/ddtrace/tracer.py index 15ad1f5cc07..4aa717fa376 100644 --- a/ddtrace/tracer.py +++ b/ddtrace/tracer.py @@ -104,5 +104,6 @@ def write(self, spans): log.info("submitting %s spans", len(spans)) for span in spans: log.info("\n%s" % span.pprint()) + print span.pprint() self._writer.write(spans) diff --git a/setup.py b/setup.py index a8a96eaca47..36020a6b3be 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,31 @@ from setuptools import setup -setup(name='ddtrace', - version='0.1', - description='Datadog tracing code', - url='https://github.com/DataDog/dd-trace-py', - author='Datadog, Inc.', - author_email='dev@datadoghq.com', - license='BSD', - packages=['ddtrace']) +tests_require = [ + 'nose', + #'psycopg2', + #'sqlite3' + 'flask', + 'blinker', +] + +setup( + name='ddtrace', + version='0.2', + description='Datadog tracing code', + url='https://github.com/DataDog/dd-trace-py', + author='Datadog, Inc.', + author_email='dev@datadoghq.com', + license='BSD', + packages=[ + 'ddtrace', + 'ddtrace.contrib', + 'ddtrace.contrib.flask', + 'ddtrace.contrib.psycopg', + 'ddtrace.contrib.pylons', + 'ddtrace.contrib.sqlite3', + 'ddtrace.ext', + ], + tests_require=tests_require, + test_suite="nose.collector", +) + From 305700e8a0b73976f6f9323a8ff68f50e001ee49 Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:05:33 -0400 Subject: [PATCH 03/10] remove print --- ddtrace/tracer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/ddtrace/tracer.py b/ddtrace/tracer.py index 4aa717fa376..15ad1f5cc07 100644 --- a/ddtrace/tracer.py +++ b/ddtrace/tracer.py @@ -104,6 +104,5 @@ def write(self, spans): log.info("submitting %s spans", len(spans)) for span in spans: log.info("\n%s" % span.pprint()) - print span.pprint() self._writer.write(spans) From f664be84d3f6d878d7bb05ce140afb01d9b72f2a Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:07:37 -0400 Subject: [PATCH 04/10] fix flask tests --- ddtrace/contrib/flask/test_flask.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ddtrace/contrib/flask/test_flask.py b/ddtrace/contrib/flask/test_flask.py index f883b2449c0..14f72dd285f 100644 --- a/ddtrace/contrib/flask/test_flask.py +++ b/ddtrace/contrib/flask/test_flask.py @@ -74,8 +74,6 @@ def handle_my_exception(e): class TestFlask(object): def setUp(self): - from nose.plugins.skip import SkipTest - raise SkipTest("fix deps") # ensure the last test didn't leave any trash spans = writer.pop() assert not spans, spans @@ -133,7 +131,7 @@ def test_success(self): assert s.start >= start assert s.duration <= end - start eq_(s.error, 0) - eq_(s.meta.get(http.STATUS_CODE), 200) + eq_(s.meta.get(http.STATUS_CODE), '200') def test_template(self): start = time.time() @@ -155,7 +153,7 @@ def test_template(self): assert s.start >= start assert s.duration <= end - start eq_(s.error, 0) - eq_(s.meta.get(http.STATUS_CODE), 200) + eq_(s.meta.get(http.STATUS_CODE), '200') t = by_name["flask.template"] eq_(t.get_tag("flask.template"), "test.html") @@ -184,7 +182,7 @@ def test_template_err(self): assert s.start >= start assert s.duration <= end - start eq_(s.error, 1) - eq_(s.meta.get(http.STATUS_CODE), 500) + eq_(s.meta.get(http.STATUS_CODE), '500') def test_error(self): start = time.time() @@ -204,7 +202,7 @@ def test_error(self): eq_(s.resource, "error") assert s.start >= start assert s.duration <= end - start - eq_(s.meta.get(http.STATUS_CODE), 500) + eq_(s.meta.get(http.STATUS_CODE), '500') def test_fatal(self): if not traced_app.use_signals: @@ -228,5 +226,5 @@ def test_fatal(self): eq_(s.resource, "fatal") assert s.start >= start assert s.duration <= end - start - eq_(s.meta.get(http.STATUS_CODE), 500) + eq_(s.meta.get(http.STATUS_CODE), '500') From c6f977d66366d1dd7ec04548550e4eff253a0a4e Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:08:10 -0400 Subject: [PATCH 05/10] lib version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 36020a6b3be..cc591519f50 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ setup( name='ddtrace', - version='0.2', + version='0.1', description='Datadog tracing code', url='https://github.com/DataDog/dd-trace-py', author='Datadog, Inc.', From bd22829ba34b2747b0cbc3d2d1a597dc7b9b57f3 Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:20:26 -0400 Subject: [PATCH 06/10] build script --- Rakefile | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index fe3e2c38f93..189ba25eca3 100644 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,27 @@ task :test do sh "nosetests" end -task :dist do - sh "python setup.py sdist" +task :build do + sh "pip wheel ./" end + +task :test do + sh "python setup.py test" +end + +task :install => :build do + sh "pip install *.whl" +end + +task :upgrade => :build do + sh "pip install -U *.whl" +end + +task :clean do + sh "python setup.py clean" + sh "rm -f *.whl" + sh "rm -rf dist" + sh "rm -rf *.egg-info" +end + +task :ci => [:clean, :test, :build] From db4efd48b9bc51b047450aa11abf0cffceaba5fd Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:20:35 -0400 Subject: [PATCH 07/10] add debug logging --- ddtrace/tracer.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ddtrace/tracer.py b/ddtrace/tracer.py index 15ad1f5cc07..b1ca15224fd 100644 --- a/ddtrace/tracer.py +++ b/ddtrace/tracer.py @@ -101,8 +101,11 @@ def write(self, spans): """ Submit the given spans to the agent. """ if spans: if self.debug_logging: - log.info("submitting %s spans", len(spans)) + log.debug("submitting %s spans", len(spans)) for span in spans: - log.info("\n%s" % span.pprint()) + log.debug("\n%s" % span.pprint()) self._writer.write(spans) + + + From 8ffae7e1f8f1ff07e1a2618a5574276b7222326e Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:22:35 -0400 Subject: [PATCH 08/10] add template tyupe to flask span --- .gitignore | 1 + ddtrace/contrib/flask/__init__.py | 1 + ddtrace/ext/http.py | 3 +++ 3 files changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index 72364f99fe4..e274e606a3f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ var/ *.egg-info/ .installed.cfg *.egg +*.whl # PyInstaller # Usually these files are written by a python script from a template diff --git a/ddtrace/contrib/flask/__init__.py b/ddtrace/contrib/flask/__init__.py index 284e287e9ad..eeb42288a8f 100644 --- a/ddtrace/contrib/flask/__init__.py +++ b/ddtrace/contrib/flask/__init__.py @@ -119,6 +119,7 @@ def _request_exception(self, *args, **kwargs): def _template_started(self, sender, template, *args, **kwargs): span = self._tracer.trace('flask.template') try: + span.span_type = http.TEMPLATE span.set_tag("flask.template", template.name or "string") finally: g.flask_datadog_tmpl_span = span diff --git a/ddtrace/ext/http.py b/ddtrace/ext/http.py index ff816611120..4cef84b4cc4 100644 --- a/ddtrace/ext/http.py +++ b/ddtrace/ext/http.py @@ -14,3 +14,6 @@ URL = "http.url" METHOD = "http.method" STATUS_CODE = "http.status_code" + +# template render span type +TEMPLATE = 'template' From 42e7a57879143686a7be608ce95da3b56cd89d78 Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:28:38 -0400 Subject: [PATCH 09/10] remove dupe test task --- Rakefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Rakefile b/Rakefile index 189ba25eca3..45b948c5241 100644 --- a/Rakefile +++ b/Rakefile @@ -1,8 +1,4 @@ -task :test do - sh "nosetests" -end - task :build do sh "pip wheel ./" end From 0686738f0b55fb678504fd2baa55b630ba231a6b Mon Sep 17 00:00:00 2001 From: Matt Perpick Date: Tue, 21 Jun 2016 17:30:12 -0400 Subject: [PATCH 10/10] fix clean --- Rakefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index 45b948c5241..d1d51f87e60 100644 --- a/Rakefile +++ b/Rakefile @@ -17,9 +17,7 @@ end task :clean do sh "python setup.py clean" - sh "rm -f *.whl" - sh "rm -rf dist" - sh "rm -rf *.egg-info" + sh "rm -rf *.whl dist *.egg-info build" end task :ci => [:clean, :test, :build]