Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion instana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def boot_agent():
from .instrumentation import sqlalchemy
from .instrumentation import sudsjurko
from .instrumentation import urllib3
from .instrumentation import webapp2_inst
from .instrumentation.django import middleware


Expand Down Expand Up @@ -114,7 +115,7 @@ def boot_agent():
else:
if "INSTANA_MAGIC" in os.environ:
# If we're being loaded into an already running process, then delay agent initialization
t = Timer(3.0, boot_agent)
t = Timer(2.0, boot_agent)
t.start()
else:
boot_agent()
65 changes: 65 additions & 0 deletions instana/instrumentation/webapp2_inst.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from __future__ import absolute_import
import wrapt

import opentracing as ot
import opentracing.ext.tags as tags

from ..log import logger
from ..singletons import agent, tracer
from ..util import strip_secrets


try:
import webapp2

logger.debug("Instrumenting webapp2")

@wrapt.patch_function_wrapper('webapp2', 'WSGIApplication.__call__')
def call_with_instana(wrapped, instance, argv, kwargs):
env = argv[0]
start_response = argv[1]

def new_start_response(status, headers, exc_info=None):
"""Modified start response with additional headers."""
if 'stan_scope' in env:
scope = env['stan_scope']
tracer.inject(scope.span.context, ot.Format.HTTP_HEADERS, headers)
headers.append(('Server-Timing', "intid;desc=%s" % scope.span.context.trace_id))

res = start_response(status, headers, exc_info)

sc = status.split(' ')[0]
if 500 <= int(sc) <= 511:
scope.span.set_tag("error", True)
ec = scope.span.tags.get('ec', 0)
scope.span.set_tag("ec", ec+1)

scope.span.set_tag(tags.HTTP_STATUS_CODE, sc)
scope.close()
return res
else:
return start_response(status, headers, exc_info)

ctx = tracer.extract(ot.Format.HTTP_HEADERS, env)
scope = env['stan_scope'] = tracer.start_active_span("wsgi", child_of=ctx)

if agent.extra_headers is not None:
for custom_header in agent.extra_headers:
# Headers are available in this format: HTTP_X_CAPTURE_THIS
wsgi_header = ('HTTP_' + custom_header.upper()).replace('-', '_')
if wsgi_header in env:
scope.span.set_tag("http.%s" % custom_header, env[wsgi_header])

if 'PATH_INFO' in env:
scope.span.set_tag('http.path', env['PATH_INFO'])
if 'QUERY_STRING' in env and len(env['QUERY_STRING']):
scrubbed_params = strip_secrets(env['QUERY_STRING'], agent.secrets_matcher, agent.secrets_list)
scope.span.set_tag("http.params", scrubbed_params)
if 'REQUEST_METHOD' in env:
scope.span.set_tag(tags.HTTP_METHOD, env['REQUEST_METHOD'])
if 'HTTP_HOST' in env:
scope.span.set_tag("http.host", env['HTTP_HOST'])

return wrapped(env, new_start_response)
except ImportError:
pass