skywalking/plugins/sw_falcon.py (54 lines of code) (raw):

# # 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. # from skywalking import Layer, Component, config from skywalking.trace.carrier import Carrier from skywalking.trace.context import get_context, NoopContext from skywalking.trace.span import NoopSpan from skywalking.trace.tags import TagHttpMethod, TagHttpURL, TagHttpParams, TagHttpStatusCode, TagHttpStatusMsg link_vector = ['https://falcon.readthedocs.io/en/stable/'] support_matrix = { 'hug': { '>=3.11': [], '>=3.10': ['2.5', '2.6'], # api deprecated for 3.10 '>=3.7': ['2.4.1', '2.5', '2.6'], # support begins 2.4.1 } } note = """While Falcon is instrumented, only Hug is tested. Hug is believed to be abandoned project, use this plugin with a bit more caution. Instead of Hug, plugin test should move to test actual Falcon.""" def install(): from falcon import API, request, RequestOptions _original_falcon_api = API.__call__ def _sw_falcon_api(this: API, env, start_response): context = get_context() carrier = Carrier() req = request.Request(env, RequestOptions()) headers = req.headers method = req.method for item in carrier: key = item.key.upper() if key in headers: item.val = headers[key] span = NoopSpan(NoopContext()) if config.ignore_http_method_check(method) \ else context.new_entry_span(op=req.path, carrier=carrier) with span: span.layer = Layer.Http span.component = Component.Falcon span.peer = req.remote_addr span.tag(TagHttpMethod(method)) span.tag(TagHttpURL(str(req.url))) if req.params: span.tag(TagHttpParams(','.join([f'{k}={v}' for k, v in req.params.items()]))) def _start_response(resp_status, headers): try: code, msg = resp_status.split(' ', 1) code = int(code) except Exception: code, msg = 500, 'Internal Server Error' if code >= 400: span.error_occurred = True span.tag(TagHttpStatusCode(code)) span.tag(TagHttpStatusMsg(msg)) return start_response(resp_status, headers) try: return _original_falcon_api(this, env, _start_response) except Exception: span.raised() raise API.__call__ = _sw_falcon_api