示例#1
0
    async def call(self, module, method, wrapped, instance, args, kwargs):
        # Late import to avoid ImportErrors
        from elasticapm.contrib.tornado.utils import get_data_from_request, get_data_from_response

        request = instance.request
        trace_parent = TraceParent.from_headers(request.headers)
        client = instance.application.elasticapm_client
        client.begin_transaction("request", trace_parent=trace_parent)
        elasticapm.set_context(
            lambda: get_data_from_request(instance, request, client.config,
                                          constants.TRANSACTION), "request")
        # TODO: Can we somehow incorporate the routing rule itself here?
        elasticapm.set_transaction_name("{} {}".format(
            request.method,
            type(instance).__name__),
                                        override=False)

        ret = await wrapped(*args, **kwargs)

        elasticapm.set_context(
            lambda: get_data_from_response(instance, client.config, constants.
                                           TRANSACTION), "response")
        result = "HTTP {}xx".format(instance.get_status() // 100)
        elasticapm.set_transaction_result(result, override=False)
        client.end_transaction()

        return ret
示例#2
0
    def process_response(self, request, response):
        if django_settings.DEBUG and not self.client.config.debug:
            return response
        try:
            if hasattr(response, 'status_code'):
                if getattr(request, '_elasticapm_view_func', False):
                    transaction_name = get_name_from_func(
                        request._elasticapm_view_func
                    )
                    transaction_name = build_name_with_http_method_prefix(
                        transaction_name,
                        request
                    )
                    elasticapm.set_transaction_name(transaction_name, override=False)

                elasticapm.set_context(lambda: self.client.get_data_from_request(
                    request,
                    capture_body=self.client.config.capture_body in ('all', 'transactions')
                ), 'request')
                elasticapm.set_context(lambda: self.client.get_data_from_response(response), 'response')
                elasticapm.set_context(lambda: self.client.get_user_info(request), 'user')
                elasticapm.set_transaction_result('HTTP {}xx'.format(response.status_code // 100), override=False)
        except Exception:
            self.client.error_logger.error(
                'Exception during timing of request',
                exc_info=True,
            )
        return response
示例#3
0
 def process_response(self, request: HttpRequest, response: HttpResponse):
     if django_settings.DEBUG and not self.client.config.debug:
         return response
     try:
         if hasattr(response, "status_code"):
             if not getattr(request, "_elasticapm_name_set", False):
                 elasticapm.set_transaction_name(
                     self.get_transaction_name(request), override=False)
             elasticapm.set_context(
                 lambda: self.client.get_data_from_request(
                     request, constants.TRANSACTION), "request")
             elasticapm.set_context(
                 lambda: self.client.get_data_from_response(
                     response, constants.TRANSACTION), "response")
             elasticapm.set_context(
                 lambda: self.client.get_user_info(request), "user")
             elasticapm.set_transaction_result("HTTP {}xx".format(
                 response.status_code // 100),
                                               override=False)
             elasticapm.set_transaction_outcome(
                 http_status_code=response.status_code, override=False)
     except Exception:
         self.client.error_logger.error(
             "Exception during timing of request", exc_info=True)
     return response
示例#4
0
    def process_response(self, request, response):
        if django_settings.DEBUG and not self.client.config.debug:
            return response
        try:
            if hasattr(response, "status_code"):
                transaction_name = None
                if self.client.config.django_transaction_name_from_route and hasattr(request.resolver_match, "route"):
                    transaction_name = request.resolver_match.route
                elif getattr(request, "_elasticapm_view_func", False):
                    transaction_name = get_name_from_func(request._elasticapm_view_func)
                if transaction_name:
                    transaction_name = build_name_with_http_method_prefix(transaction_name, request)
                    elasticapm.set_transaction_name(transaction_name, override=False)

                elasticapm.set_context(
                    lambda: self.client.get_data_from_request(request, constants.TRANSACTION), "request"
                )
                elasticapm.set_context(
                    lambda: self.client.get_data_from_response(response, constants.TRANSACTION), "response"
                )
                elasticapm.set_context(lambda: self.client.get_user_info(request), "user")
                elasticapm.set_transaction_result("HTTP {}xx".format(response.status_code // 100), override=False)
                elasticapm.set_transaction_outcome(http_status_code=response.status_code, override=False)
        except Exception:
            self.client.error_logger.error("Exception during timing of request", exc_info=True)
        return response
示例#5
0
    async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response:
        """Processes the whole request APM capturing.

        Args:
            request (Request)
            call_next (RequestResponseEndpoint): Next request process in Starlette.

        Returns:
            Response
        """
        await self._request_started(request)

        try:
            response = await call_next(request)
            elasticapm.set_transaction_outcome(constants.OUTCOME.SUCCESS, override=False)
        except Exception:
            await self.capture_exception(
                context={"request": await get_data_from_request(request, self.client.config, constants.ERROR)}
            )
            elasticapm.set_transaction_result("HTTP 5xx", override=False)
            elasticapm.set_transaction_outcome(constants.OUTCOME.FAILURE, override=False)
            elasticapm.set_context({"status_code": 500}, "response")

            raise
        else:
            await self._request_finished(response)
        finally:
            self.client.end_transaction()

        return response
示例#6
0
 def request_finished(self, app, response):
     if not self.app.debug or self.client.config.debug:
         rule = request.url_rule.rule if request.url_rule is not None else ""
         rule = build_name_with_http_method_prefix(rule, request)
         elasticapm.set_context(
             lambda: get_data_from_request(
                 request,
                 capture_body=self.client.config.capture_body in
                 ("transactions", "all"),
                 capture_headers=self.client.config.capture_headers,
             ),
             "request",
         )
         elasticapm.set_context(
             lambda: get_data_from_response(response,
                                            capture_headers=self.client.
                                            config.capture_headers),
             "response")
         if response.status_code:
             result = "HTTP {}xx".format(response.status_code // 100)
         else:
             result = response.status
         elasticapm.set_transaction_name(rule, override=False)
         elasticapm.set_transaction_result(result, override=False)
         # Instead of calling end_transaction here, we defer the call until the response is closed.
         # This ensures that we capture things that happen until the WSGI server closes the response.
         response.call_on_close(self.client.end_transaction)
示例#7
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        if not hasattr(instance.application, "elasticapm_client"):
            # If tornado was instrumented but not as the main framework
            # (i.e. in Flower), we should skip it.
            return wrapped(*args, **kwargs)

        # Late import to avoid ImportErrors
        from tornado.web import Finish, HTTPError

        from elasticapm.contrib.tornado.utils import get_data_from_request

        e = args[0]
        if isinstance(e, Finish):
            # Not an error; Finish is an exception that ends a request without an error response
            return wrapped(*args, **kwargs)

        client = instance.application.elasticapm_client
        request = instance.request
        client.capture_exception(
            context={
                "request":
                get_data_from_request(instance, request, client.config,
                                      constants.ERROR)
            })
        elasticapm.set_transaction_outcome(constants.OUTCOME.FAILURE)
        if isinstance(e, HTTPError):
            elasticapm.set_transaction_result("HTTP {}xx".format(
                int(e.status_code / 100)),
                                              override=False)
            elasticapm.set_context({"status_code": e.status_code}, "response")
        else:
            elasticapm.set_transaction_result("HTTP 5xx", override=False)
            elasticapm.set_context({"status_code": 500}, "response")

        return wrapped(*args, **kwargs)
示例#8
0
    async def dispatch(self, request: Request,
                       call_next: RequestResponseEndpoint) -> Response:
        """Processes the whole request APM capturing.

        Args:
            request (Request)
            call_next (RequestResponseEndpoint): Next request process in Starlette.

        Returns:
            Response
        """
        await self._request_started(request)

        try:
            response = await call_next(request)
        except Exception:
            await self.capture_exception()
            elasticapm.set_transaction_result("HTTP 5xx", override=False)
            elasticapm.set_context({"status_code": 500}, "response")

            raise
        else:
            await self._request_finished(response)
        finally:
            self.client.end_transaction()

        return response
示例#9
0
    async def call(self, module, method, wrapped, instance, args, kwargs):
        if not hasattr(instance.application, "elasticapm_client"):
            # If tornado was instrumented but not as the main framework
            # (i.e. in Flower), we should skip it.
            return await wrapped(*args, **kwargs)

        # Late import to avoid ImportErrors
        from elasticapm.contrib.tornado.utils import get_data_from_request, get_data_from_response

        request = instance.request
        trace_parent = TraceParent.from_headers(request.headers)
        client = instance.application.elasticapm_client
        client.begin_transaction("request", trace_parent=trace_parent)
        elasticapm.set_context(
            lambda: get_data_from_request(instance, request, client.config,
                                          constants.TRANSACTION), "request")
        # TODO: Can we somehow incorporate the routing rule itself here?
        elasticapm.set_transaction_name("{} {}".format(
            request.method,
            type(instance).__name__),
                                        override=False)

        ret = await wrapped(*args, **kwargs)

        elasticapm.set_context(
            lambda: get_data_from_response(instance, client.config, constants.
                                           TRANSACTION), "response")
        status = instance.get_status()
        result = "HTTP {}xx".format(status // 100)
        elasticapm.set_transaction_result(result, override=False)
        elasticapm.set_transaction_outcome(http_status_code=status)
        client.end_transaction()

        return ret
示例#10
0
    def process_response(self, request, response):
        if django_settings.DEBUG and not self.client.config.debug:
            return response
        try:
            if hasattr(response, "status_code"):
                if getattr(request, "_elasticapm_view_func", False):
                    transaction_name = get_name_from_func(
                        request._elasticapm_view_func)
                    transaction_name = build_name_with_http_method_prefix(
                        transaction_name, request)
                    elasticapm.set_transaction_name(transaction_name,
                                                    override=False)

                elasticapm.set_context(
                    lambda: self.client.get_data_from_request(
                        request,
                        capture_body=self.client.config.capture_body in
                        ("all", "transactions")),
                    "request",
                )
                elasticapm.set_context(
                    lambda: self.client.get_data_from_response(response),
                    "response")
                elasticapm.set_context(
                    lambda: self.client.get_user_info(request), "user")
                elasticapm.set_transaction_result("HTTP {}xx".format(
                    response.status_code // 100),
                                                  override=False)
        except Exception:
            self.client.error_logger.error(
                "Exception during timing of request", exc_info=True)
        return response
示例#11
0
    def process_response(self, req, resp, resource, req_succeeded=None):
        if self.client and req.user_agent != 'mcod-heartbeat':
            rule = route_to_name(req.uri_template,
                                 prefix='api',
                                 method=req.method)
            elasticapm.set_context(
                lambda: get_data_from_request(
                    req,
                    capture_body=self.client.config.capture_body in
                    ("transactions", "all"),
                    capture_headers=self.client.config.capture_headers,
                ),
                "request",
            )
            elasticapm.set_context(
                lambda: get_data_from_response(
                    resp, capture_headers=self.client.config.capture_headers),
                "response")

            result = resp.status
            elasticapm.set_transaction_name(rule, override=False)
            if hasattr(req, 'user') and req.user.is_authenticated:
                elasticapm.set_user_context(email=req.user.email,
                                            user_id=req.user.id)

            elasticapm.set_transaction_result(result, override=False)
            # Instead of calling end_transaction here, we defer the call until the response is closed.
            # This ensures that we capture things that happen until the WSGI server closes the response.
            self.client.end_transaction(rule, result)
示例#12
0
    def call(self, module, method, wrapped, instance, args, kwargs):

        # Late import to avoid ImportErrors
        from tornado.web import Finish, HTTPError
        from elasticapm.contrib.tornado.utils import get_data_from_request

        e = args[0]
        if isinstance(e, Finish):
            # Not an error; Finish is an exception that ends a request without an error response
            return wrapped(*args, **kwargs)

        client = instance.application.elasticapm_client
        request = instance.request
        client.capture_exception(
            context={
                "request":
                get_data_from_request(instance, request, client.config,
                                      constants.ERROR)
            })
        if isinstance(e, HTTPError):
            elasticapm.set_transaction_result("HTTP {}xx".format(
                int(e.status_code / 100)),
                                              override=False)
            elasticapm.set_context({"status_code": e.status_code}, "response")
        else:
            elasticapm.set_transaction_result("HTTP 5xx", override=False)
            elasticapm.set_context({"status_code": 500}, "response")

        return wrapped(*args, **kwargs)
示例#13
0
    async def handle_request(request, handler):
        elasticapm_client = app.get(CLIENT_KEY)
        if elasticapm_client:
            request[CLIENT_KEY] = elasticapm_client
            trace_parent = AioHttpTraceParent.from_headers(request.headers)
            elasticapm_client.begin_transaction("request",
                                                trace_parent=trace_parent)
            resource = request.match_info.route.resource
            name = request.method
            if resource:
                # canonical has been added in 3.3, and returns one of path, formatter, prefix
                for attr in ("canonical", "_path", "_formatter", "_prefix"):
                    if hasattr(resource, attr):
                        name += " " + getattr(resource, attr)
                        break
                else:
                    name += " unknown route"
            else:
                name += " unknown route"
            elasticapm.set_transaction_name(name, override=False)
            elasticapm.set_context(
                lambda: get_data_from_request(
                    request,
                    capture_body=elasticapm_client.config.capture_body in
                    ("transactions", "all"),
                    capture_headers=elasticapm_client.config.capture_headers,
                ),
                "request",
            )

        try:
            response = await handler(request)
            elasticapm.set_transaction_result("HTTP {}xx".format(
                response.status // 100),
                                              override=False)
            elasticapm.set_context(
                lambda: get_data_from_response(
                    response,
                    capture_headers=elasticapm_client.config.capture_headers),
                "response",
            )
            return response
        except Exception:
            if elasticapm_client:
                elasticapm_client.capture_exception(
                    context={
                        "request":
                        get_data_from_request(request,
                                              capture_body=elasticapm_client.
                                              config.capture_body in (
                                                  "all", "errors"))
                    })
                elasticapm.set_transaction_result("HTTP 5xx", override=False)
                elasticapm.set_context({"status_code": 500}, "response")
            raise
        finally:
            elasticapm_client.end_transaction()
示例#14
0
    async def handle_request(request, handler):
        elasticapm_client = app.get(CLIENT_KEY)
        if elasticapm_client:
            request[CLIENT_KEY] = elasticapm_client
            trace_parent = AioHttpTraceParent.from_headers(request.headers)
            elasticapm_client.begin_transaction("request",
                                                trace_parent=trace_parent)
            resource = request.match_info.route.resource
            name = request.method
            if resource:
                # canonical has been added in 3.3, and returns one of path, formatter, prefix
                for attr in ("canonical", "_path", "_formatter", "_prefix"):
                    if hasattr(resource, attr):
                        name += " " + getattr(resource, attr)
                        break
                else:
                    name += " unknown route"
            else:
                name += " unknown route"
            elasticapm.set_transaction_name(name, override=False)
            elasticapm.set_context(
                lambda: get_data_from_request(request, elasticapm_client.
                                              config, constants.TRANSACTION),
                "request")

        try:
            response = await handler(request)
            elasticapm.set_transaction_result("HTTP {}xx".format(
                response.status // 100),
                                              override=False)
            elasticapm.set_context(
                lambda: get_data_from_response(response, elasticapm_client.
                                               config, constants.TRANSACTION),
                "response")
            return response
        except Exception as exc:
            if elasticapm_client:
                elasticapm_client.capture_exception(
                    context={
                        "request":
                        get_data_from_request(
                            request, elasticapm_client.config, constants.ERROR)
                    })
                elasticapm.set_transaction_result("HTTP 5xx", override=False)
                elasticapm.set_context({"status_code": 500}, "response")
                # some exceptions are response-like, e.g. have headers and status code. Let's try and capture them
                if isinstance(exc, (Response, HTTPException)):
                    elasticapm.set_context(
                        lambda: get_data_from_response(
                            exc, elasticapm_client.config, constants.ERROR
                        ),  # noqa: F821
                        "response",
                    )

            raise
        finally:
            elasticapm_client.end_transaction()
示例#15
0
 async def wrapped_send(message):
     if message.get("type") == "http.response.start":
         await set_context(
             lambda: get_data_from_response(message, self.client.config,
                                            constants.TRANSACTION),
             "response")
         result = "HTTP {}xx".format(message["status"] // 100)
         elasticapm.set_transaction_result(result, override=False)
     await send(message)
 def on_finish(self):
     apm_elastic = self.settings.get("apm_elastic")
     name_trasaction = '{} {}'.format(self.request.method, self.get_url())
     status = self.get_status()
     result = 'HTTP {}xx'.format(status // 100)
     data_request = get_data_from_request(self.request)
     data_response = get_data_from_response(self)
     elasticapm.set_context(lambda: data_request, "request")
     elasticapm.set_context(lambda: data_response, "response")
     elasticapm.set_transaction_name(name_trasaction, override=False)
     elasticapm.set_transaction_result(result, override=False)
     apm_elastic.client.end_transaction()
示例#17
0
    async def _request_finished(self, response: Response):
        """Captures the end of the request processing to APM.

        Args:
            response (Response)
        """
        await set_context(
            lambda: get_data_from_response(response, self.client.config,
                                           constants.TRANSACTION), "response")

        result = "HTTP {}xx".format(response.status_code // 100)
        elasticapm.set_transaction_result(result, override=False)
示例#18
0
 def request_finished(self, app, response):
     if not self.app.debug or self.client.config.debug:
         elasticapm.set_context(
             lambda: get_data_from_response(response, capture_headers=self.client.config.capture_headers), "response"
         )
         if response.status_code:
             result = "HTTP {}xx".format(response.status_code // 100)
         else:
             result = response.status
         elasticapm.set_transaction_result(result, override=False)
         # Instead of calling end_transaction here, we defer the call until the response is closed.
         # This ensures that we capture things that happen until the WSGI server closes the response.
         response.call_on_close(self.client.end_transaction)
示例#19
0
 async def _instrument_response(request: Request, response: HTTPResponse):
     await set_context(
         lambda: get_response_info(
             config=self._client.config,
             response=response,
         ),
         "response",
     )
     self._setup_transaction_name(request=request)
     result = f"HTTP {response.status // 100}xx"
     set_transaction_result(result=result, override=False)
     set_transaction_outcome(http_status_code=response.status, override=False)
     elastic_context(data={"status_code": response.status}, key="response")
     self._client.end_transaction()
示例#20
0
        async def _handler(request: Request, exception: BaseException):
            if not self._client:
                return

            self._client.capture_exception(
                exc_info=sys.exc_info(),
                context={
                    "request": await get_request_info(config=self._client.config, request=request),
                },
                handled=True,
            )
            self._setup_transaction_name(request=request)
            set_transaction_result(result="HTTP 5xx", override=False)
            set_transaction_outcome(outcome=constants.OUTCOME.FAILURE, override=False)
            elastic_context(data={"status_code": 500}, key="response")
            self._client.end_transaction()
示例#21
0
    def process_response(self, request, response):
        if django_settings.DEBUG and not self.client.config.debug:
            return response
        if request.META.get('HTTP_USER_AGENT') == 'mcod-heartbeat':
            return response
        try:
            if hasattr(response, "status_code"):
                try:
                    route = request.resolver_match.route
                except AttributeError:
                    route = request.path

                transaction_name = route_to_name(route,
                                                 prefix='admin',
                                                 method=request.method)
                if transaction_name:
                    elasticapm.set_transaction_name(transaction_name,
                                                    override=False)

                elasticapm.set_context(
                    lambda: self.client.get_data_from_request(
                        request,
                        capture_body=self.client.config.capture_body in
                        ("all", "transactions")),
                    "request",
                )
                elasticapm.set_context(
                    lambda: self.client.get_data_from_response(response),
                    "response")
                elasticapm.set_context(
                    lambda: self.client.get_user_info(request), "user")
                elasticapm.set_transaction_result("HTTP {}xx".format(
                    response.status_code // 100),
                                                  override=False)
        except Exception:
            self.client.error_logger.error(
                "Exception during timing of request", exc_info=True)
        return response
示例#22
0
    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        Transaction teardown
        """
        if self.response and isinstance(self.response, dict):
            elasticapm.set_context(
                lambda: get_data_from_response(self.response,
                                               capture_headers=self.client.
                                               config.capture_headers),
                "response",
            )
            if "statusCode" in self.response:
                try:
                    result = "HTTP {}xx".format(
                        int(self.response["statusCode"]) // 100)
                    elasticapm.set_transaction_result(result, override=False)
                except ValueError:
                    logger.warning(
                        "Lambda function's statusCode was not formed as an int. Assuming 5xx result."
                    )
                    elasticapm.set_transaction_result("HTTP 5xx",
                                                      override=False)
        if exc_val:
            self.client.capture_exception(exc_info=(exc_type, exc_val, exc_tb),
                                          handled=False)
            if self.source == "api":
                elasticapm.set_transaction_result("HTTP 5xx", override=False)
                elasticapm.set_transaction_outcome(http_status_code=500,
                                                   override=False)
                elasticapm.set_context({"status_code": 500}, "response")
            else:
                elasticapm.set_transaction_result("failure", override=False)
                elasticapm.set_transaction_outcome(outcome="failure",
                                                   override=False)

        self.client.end_transaction()

        try:
            logger.debug("flushing elasticapm")
            self.client._transport.flush()
            logger.debug("done flushing elasticapm")
        except ValueError:
            logger.warning("flush timed out")
示例#23
0
"""
Created on Tue Sep 12 11:02:46 2017

@author: tina
"""
import logging
import time
from slackclient import SlackClient
from archstats import stats
import configparser
from elasticapm import Client
import elasticapm

elasticapm.instrument()
elasticapm.set_transaction_name('processor')
elasticapm.set_transaction_result('SUCCESS')
from elasticapm.handlers.logging import LoggingHandler

from viaa.configuration import ConfigParser

#config = ConfigParser()
config = ConfigParser(config_file="config.yml")

bot_id = config.app_cfg['slack_api']['bot_id']
client_token = config.app_cfg['slack_api']['client_token']


def clean_up_exit():
    handlers = LOGGER.handlers[:]
    for handler in handlers:
        handler.close()
示例#24
0
    async def __call__(self, scope, receive, send):
        """
        Args:
            scope: ASGI scope dictionary
            receive: receive awaitable callable
            send: send awaitable callable
        """
        # we only handle the http scope, skip anything else.
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        @functools.wraps(send)
        async def wrapped_send(message):
            if message.get("type") == "http.response.start":
                await set_context(
                    lambda: get_data_from_response(message, self.client.config,
                                                   constants.TRANSACTION),
                    "response")
                result = "HTTP {}xx".format(message["status"] // 100)
                elasticapm.set_transaction_result(result, override=False)
            await send(message)

        # When we consume the body from receive, we replace the streaming
        # mechanism with a mocked version -- this workaround came from
        # https://github.com/encode/starlette/issues/495#issuecomment-513138055
        body = b""
        while True:
            message = await receive()
            if not message:
                break
            if message["type"] == "http.request":
                b = message.get("body", b"")
                if b:
                    body += b
                if not message.get("more_body", False):
                    break
            if message["type"] == "http.disconnect":
                break

        async def _receive() -> Message:
            await asyncio.sleep(0)
            return {"type": "http.request", "body": body}

        request = Request(scope, receive=_receive)
        await self._request_started(request)

        try:
            await self.app(scope, _receive, wrapped_send)
            elasticapm.set_transaction_outcome(constants.OUTCOME.SUCCESS,
                                               override=False)
        except Exception:
            await self.capture_exception(
                context={
                    "request":
                    await get_data_from_request(request, self.client.config,
                                                constants.ERROR)
                })
            elasticapm.set_transaction_result("HTTP 5xx", override=False)
            elasticapm.set_transaction_outcome(constants.OUTCOME.FAILURE,
                                               override=False)
            elasticapm.set_context({"status_code": 500}, "response")

            raise
        finally:
            self.client.end_transaction()
示例#25
0
def override_transaction_name_view(request):
    elasticapm.set_transaction_name("foo")
    elasticapm.set_transaction_result("okydoky")
    return HttpResponse()
示例#26
0
 def transaction_name():
     elasticapm.set_transaction_name('foo')
     elasticapm.set_transaction_result('okydoky')
     return Response('')
示例#27
0
def test_set_transaction_result(elasticapm_client):
    transaction = elasticapm_client.begin_transaction("test")
    elasticapm.set_transaction_result("success")
    assert "success" == transaction.result
示例#28
0
    def call(self, module, method, wrapped, instance, args, kwargs):
        topic = None
        destination_info = {
            "service": {
                "name": "kafka",
                "resource": "kafka/",
                "type": "messaging"
            },
        }
        self.destination_info = destination_info
        if method == "KafkaProducer.send":
            address = None
            port = None
            time_start = time.time()
            while not instance._metadata.controller:
                if time.time() - time_start > 1:
                    break
                continue
            if instance:
                if instance._metadata.controller:
                    address = instance._metadata.controller[1]
                    port = instance._metadata.controller[2]
            self.destination_info["port"] = port
            self.destination_info["address"] = address
            topic = args[0].encode("utf-8")
            transaction = execution_context.get_transaction()
            if transaction:
                return self._trace_send(wrapped, topic, **kwargs)

        if method == "KafkaConsumer.next":
            transaction = execution_context.get_transaction()
            if transaction and transaction.transaction_type != "messaging":
                action = "consume"
                with capture_span(
                        name="consumer",
                        span_type="messaging",
                        span_subtype=self.provider_name,
                        span_action=action,
                        extra={
                            "message": {
                                "queue": {
                                    "name": ""
                                }
                            },
                            "destination": self.destination_info,
                        },
                ) as span:
                    result = wrapped(*args, **kwargs)
                    topic = result[0]
                    new_trace_id = get_trace_id(result)
                    service = self.destination_info["service"]
                    service["resource"] = service["resource"] + topic
                    span.context["message"]["queue"]["name"] = topic
                    span.context["destination"]["service"] = service
                    span.name = "KafkaConsumer#receive from " + topic
                    transaction.trace_parent = TraceParent.from_string(
                        new_trace_id)
                    return result
            else:
                client = get_client()
                if transaction and transaction.transaction_type == "messaging":
                    client.end_transaction()

                result = wrapped(*args, **kwargs)
                topic = result[0]
                new_trace_id = None
                new_trace_id = get_trace_id(result)

                client.begin_transaction("messaging", trace_parent=None)
                transaction = execution_context.get_transaction()
                if result.timestamp_type == 0:
                    current_time_millis = int(round(time.time() * 1000))
                    age = current_time_millis - result.timestamp
                    transaction.context = {
                        "message": {
                            "age": {
                                "ms": age
                            },
                            "queue": {
                                "name": topic
                            }
                        }
                    }
                if new_trace_id:
                    transaction.trace_parent = TraceParent.from_string(
                        new_trace_id)
                t_name = "Kafka record from " + topic
                elasticapm.set_transaction_name(t_name, override=True)
                res = constants.OUTCOME.SUCCESS
                elasticapm.set_transaction_result(res, override=False)
                return result
示例#29
0
    async def handle_request(request, handler):
        elasticapm_client = get_client() if client is None else client
        should_trace = elasticapm_client and not elasticapm_client.should_ignore_url(
            request.path)
        if should_trace:
            trace_parent = AioHttpTraceParent.from_headers(request.headers)
            elasticapm_client.begin_transaction("request",
                                                trace_parent=trace_parent)
            resource = request.match_info.route.resource
            name = request.method
            if resource:
                # canonical has been added in 3.3, and returns one of path, formatter, prefix
                for attr in ("canonical", "_path", "_formatter", "_prefix"):
                    if hasattr(resource, attr):
                        name += " " + getattr(resource, attr)
                        break
                else:
                    name += " unknown route"
            else:
                name += " unknown route"
            elasticapm.set_transaction_name(name, override=False)
            elasticapm.set_context(
                lambda: get_data_from_request(request, elasticapm_client.
                                              config, constants.TRANSACTION),
                "request")

        try:
            response = await handler(request)
            if should_trace:
                elasticapm.set_transaction_result("HTTP {}xx".format(
                    response.status // 100),
                                                  override=False)
                elasticapm.set_transaction_outcome(
                    http_status_code=response.status, override=False)
                elasticapm.set_context(
                    lambda:
                    get_data_from_response(response, elasticapm_client.config,
                                           constants.TRANSACTION),
                    "response",
                )
            return response
        except HTTPException as exc:
            # HTTPExceptions are response-like, e.g. have headers and status code. They can represent an HTTP
            # response below a 500 status code and therefore not something to capture as exception. Like
            # HTTPOk can be raised but will most likely be wrongly tagged as an APM error. Let's try and
            # capture this according to the status.
            if exc.status_code < 500 and not should_trace:
                raise
            if elasticapm_client:
                elasticapm.set_transaction_result("HTTP {}xx".format(
                    exc.status_code // 100),
                                                  override=False)
                elasticapm.set_transaction_outcome(
                    http_status_code=exc.status_code, override=False)
                elasticapm.set_context(
                    lambda: get_data_from_response(
                        exc,  # noqa: F821
                        elasticapm_client.config,
                        constants.ERROR if exc.status_code >= 500 else
                        constants.TRANSACTION,  # noqa: F821
                    ),
                    "response",
                )
                if exc.status_code >= 500:
                    elasticapm_client.capture_exception(
                        context={
                            "request":
                            get_data_from_request(request, elasticapm_client.
                                                  config, constants.ERROR)
                        })
            raise
        except Exception:
            if elasticapm_client:
                elasticapm.set_transaction_result("HTTP 5xx", override=False)
                elasticapm.set_transaction_outcome(http_status_code=500,
                                                   override=False)
                elasticapm.set_context({"status_code": 500}, "response")
                elasticapm_client.capture_exception(
                    context={
                        "request":
                        get_data_from_request(
                            request, elasticapm_client.config, constants.ERROR)
                    })
            raise
        finally:
            elasticapm_client.end_transaction()
示例#30
0
 def transaction_name():
     elasticapm.set_transaction_name("foo")
     elasticapm.set_transaction_result("okydoky")
     return Response("")