Skip to content

Commit 2f6434e

Browse files
authored
webapp2: New automatic instrumentation (#194)
* Initial webapp2 automatic instrumentation * Remove trailing whitespace
1 parent 66e678e commit 2f6434e

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

instana/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def boot_agent():
7979
from .instrumentation import sqlalchemy
8080
from .instrumentation import sudsjurko
8181
from .instrumentation import urllib3
82+
from .instrumentation import webapp2_inst
8283
from .instrumentation.django import middleware
8384

8485

@@ -114,7 +115,7 @@ def boot_agent():
114115
else:
115116
if "INSTANA_MAGIC" in os.environ:
116117
# If we're being loaded into an already running process, then delay agent initialization
117-
t = Timer(3.0, boot_agent)
118+
t = Timer(2.0, boot_agent)
118119
t.start()
119120
else:
120121
boot_agent()
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from __future__ import absolute_import
2+
import wrapt
3+
4+
import opentracing as ot
5+
import opentracing.ext.tags as tags
6+
7+
from ..log import logger
8+
from ..singletons import agent, tracer
9+
from ..util import strip_secrets
10+
11+
12+
try:
13+
import webapp2
14+
15+
logger.debug("Instrumenting webapp2")
16+
17+
@wrapt.patch_function_wrapper('webapp2', 'WSGIApplication.__call__')
18+
def call_with_instana(wrapped, instance, argv, kwargs):
19+
env = argv[0]
20+
start_response = argv[1]
21+
22+
def new_start_response(status, headers, exc_info=None):
23+
"""Modified start response with additional headers."""
24+
if 'stan_scope' in env:
25+
scope = env['stan_scope']
26+
tracer.inject(scope.span.context, ot.Format.HTTP_HEADERS, headers)
27+
headers.append(('Server-Timing', "intid;desc=%s" % scope.span.context.trace_id))
28+
29+
res = start_response(status, headers, exc_info)
30+
31+
sc = status.split(' ')[0]
32+
if 500 <= int(sc) <= 511:
33+
scope.span.set_tag("error", True)
34+
ec = scope.span.tags.get('ec', 0)
35+
scope.span.set_tag("ec", ec+1)
36+
37+
scope.span.set_tag(tags.HTTP_STATUS_CODE, sc)
38+
scope.close()
39+
return res
40+
else:
41+
return start_response(status, headers, exc_info)
42+
43+
ctx = tracer.extract(ot.Format.HTTP_HEADERS, env)
44+
scope = env['stan_scope'] = tracer.start_active_span("wsgi", child_of=ctx)
45+
46+
if agent.extra_headers is not None:
47+
for custom_header in agent.extra_headers:
48+
# Headers are available in this format: HTTP_X_CAPTURE_THIS
49+
wsgi_header = ('HTTP_' + custom_header.upper()).replace('-', '_')
50+
if wsgi_header in env:
51+
scope.span.set_tag("http.%s" % custom_header, env[wsgi_header])
52+
53+
if 'PATH_INFO' in env:
54+
scope.span.set_tag('http.path', env['PATH_INFO'])
55+
if 'QUERY_STRING' in env and len(env['QUERY_STRING']):
56+
scrubbed_params = strip_secrets(env['QUERY_STRING'], agent.secrets_matcher, agent.secrets_list)
57+
scope.span.set_tag("http.params", scrubbed_params)
58+
if 'REQUEST_METHOD' in env:
59+
scope.span.set_tag(tags.HTTP_METHOD, env['REQUEST_METHOD'])
60+
if 'HTTP_HOST' in env:
61+
scope.span.set_tag("http.host", env['HTTP_HOST'])
62+
63+
return wrapped(env, new_start_response)
64+
except ImportError:
65+
pass

0 commit comments

Comments
 (0)