blob: 04b58caad16ecb598ca087949213ffc9ba69ffcb [file]
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import inspect
import logging
import traceback
from skywalking import Layer, Component
from skywalking.trace import tags
from skywalking.trace.carrier import Carrier
from skywalking.trace.context import get_context
from skywalking.trace.tags import Tag
logger = logging.getLogger(__name__)
def install():
# noinspection PyBroadException
try:
from http.server import BaseHTTPRequestHandler
_handle = BaseHTTPRequestHandler.handle
def _sw_handle(handler: BaseHTTPRequestHandler):
clazz = handler.__class__
if 'werkzeug.serving.WSGIRequestHandler' == ".".join([clazz.__module__, clazz.__name__]):
wrap_werkzeug_request_handler(handler)
else:
wrap_default_request_handler(handler)
_handle(handler)
BaseHTTPRequestHandler.handle = _sw_handle
except Exception:
logger.warning('failed to install plugin %s', __name__)
traceback.print_exc()
def wrap_werkzeug_request_handler(handler):
"""
Wrap run_wsgi of werkzeug.serving.WSGIRequestHandler to add skywalking instrument code.
"""
_run_wsgi = handler.run_wsgi
def _wrap_run_wsgi():
context = get_context()
carrier = Carrier()
for item in carrier:
item.val = handler.headers[item.key.capitalize()]
with context.new_entry_span(op=handler.path, carrier=carrier) as span:
span.layer = Layer.Http
span.component = Component.General
span.peer = '%s:%s' % handler.client_address
span.tag(Tag(key=tags.HttpMethod, val=handler.command))
return _run_wsgi()
handler.run_wsgi = _wrap_run_wsgi
def wrap_default_request_handler(handler):
http_methods = ('GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH')
for method in http_methods:
_wrap_do_method(handler, method)
def _wrap_do_method(handler, method):
if hasattr(handler, 'do_' + method) and inspect.ismethod(getattr(handler, 'do_' + method)):
_do_method = getattr(handler, 'do_' + method)
def _sw_do_method():
context = get_context()
carrier = Carrier()
for item in carrier:
item.val = handler.headers[item.key.capitalize()]
with context.new_entry_span(op=handler.path, carrier=carrier) as span:
span.layer = Layer.Http
span.component = Component.General
span.peer = '%s:%s' % handler.client_address
span.tag(Tag(key=tags.HttpMethod, val=method))
_do_method()
setattr(handler, 'do_' + method, _sw_do_method)