Repository: DataDog/dd-trace-py

Issue:
TracePlugin not working for bottle + python 2.7.x
Hi, we have a backend using python 2.7.x, Im integrating Datadog APM following the documentation and I have the following error:
```
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/bottle.py", line 764, in _handle
    return route.call(**args)
  File "/usr/local/lib/python2.7/site-packages/bottle.py", line 1575, in wrapper
    rv = callback(*a, **ka)
  File "/usr/local/lib/python2.7/site-packages/ddtrace/contrib/bottle/trace.py", line 32, in wrapped
    resource = "%s %s" % (request.method, request.route.rule)
  File "/usr/local/lib/python2.7/site-packages/bottle.py", line 1237, in __getattr__
    raise AttributeError('Attribute %r not defined.' % name)
```

when I go to trace.py line 32, I find this:
`resource = "%s %s" % (request.method, request.route.rule)`

somehow request.route doesn't exist, I think that probably is related to a different python or bottle version being used on our end.
Anyway `route` is already provided as a parameter for this method (`TracePlugin.apply(self, callback, route):`) so there's no need to call `request.route.rule`, you can call `route.rule` instead,
`resource = "%s %s" % (request.method, route.rule)`

Otherwise let me know if you have more details about this error and what's the right way to solve it,
thanks



Discussion:
Hello @rodrigocollavo ! thanks for reporting your problem. Your description of the problem is perfect, can you provide us your Bottle version? I want to reproduce the problem so that we have a regression test for that. Thank you very much!
@palazzem we are using bottle 0.11.6

Resolving patch:
diff --git a/ddtrace/contrib/bottle/trace.py b/ddtrace/contrib/bottle/trace.py
--- a/ddtrace/contrib/bottle/trace.py
+++ b/ddtrace/contrib/bottle/trace.py
@@ -1,4 +1,3 @@
-
 # 3p
 from bottle import response, request
 
@@ -10,18 +9,18 @@
 from ...propagation.http import HTTPPropagator
 
 class TracePlugin(object):
-
     name = 'trace'
     api = 2
 
-    def __init__(self, service="bottle", tracer=None, distributed_tracing=None):
+    def __init__(self, service='bottle', tracer=None, distributed_tracing=None):
         self.service = service
         self.tracer = tracer or ddtrace.tracer
+        self.distributed_tracing = distributed_tracing
         self.tracer.set_service_info(
             service=service,
-            app="bottle",
-            app_type=AppTypes.web)
-        self.distributed_tracing = distributed_tracing
+            app='bottle',
+            app_type=AppTypes.web,
+        )
 
     def apply(self, callback, route):
 
@@ -29,7 +28,7 @@ def wrapped(*args, **kwargs):
             if not self.tracer or not self.tracer.enabled:
                 return callback(*args, **kwargs)
 
-            resource = "%s %s" % (request.method, request.route.rule)
+            resource = '{} {}'.format(request.method, route.rule)
 
             # Propagate headers such as x-datadog-trace-id.
             if self.distributed_tracing:
@@ -38,7 +37,7 @@ def wrapped(*args, **kwargs):
                 if context.trace_id:
                     self.tracer.context_provider.activate(context)
 
-            with self.tracer.trace("bottle.request", service=self.service, resource=resource) as s:
+            with self.tracer.trace('bottle.request', service=self.service, resource=resource) as s:
                 code = 0
                 try:
                     return callback(*args, **kwargs)


Test patch: