Esempio n. 1
0
def response(func, event, context, transaction_name=''):
    """
    Calls `func(event, context)` and returns a properly formatted response,
    also reporting the transaction results to APM using either the given
    `transaction_name` or `func`'s name.
    """
    if not transaction_name:
        transaction_name = func.__name__

    apm.begin_transaction('Request')
    elasticapm.set_custom_context({
        'event': event,
        'function_name': context.function_name,
        'aws_request_id': context.aws_request_id,
    })
    # https://docs.aws.amazon.com/pt_br/lambda/latest/dg/python-context-object.html

    try:
        body = func(event, context)
        response = {'statusCode': 200, 'body': json.dumps(body)}
        return response
    except Exception as e:
        error = {'code': type(e).__name__, 'message': str(e)}
        body = {'errors': [error]}
        response = {'statusCode': 500, 'body': json.dumps(body)}
        apm.capture_exception()
        return response
    finally:
        apm.end_transaction(transaction_name)
Esempio n. 2
0
def search_documents(finder, question_request,
                     start_time) -> List[AnswersToIndividualQuestion]:
    results = []
    for question in question_request.questions:
        if question_request.filters:
            # put filter values into a list and remove filters with null value
            filters = {
                key: [value]
                for key, value in question_request.filters.items()
                if value is not None
            }
            logger.info(f" [{datetime.now()}] Request: {question_request}")
        else:
            filters = {}

        result = finder.get_answers(
            question=question,
            top_k_retriever=question_request.top_k_retriever,
            top_k_reader=question_request.top_k_reader,
            filters=filters,
        )
        results.append(result)
    elasticapm.set_custom_context({"results": results})
    end_time = time.time()
    logger.info(
        json.dumps({
            "request": question_request.dict(),
            "results": results,
            "time": f"{(end_time - start_time):.2f}"
        }))
    return results
Esempio n. 3
0
def update_stats():
    if random.random() > 0.8:
        dict_for_truncation = {k: k for k in range(500)}
        assert False, "Bad luck!"
    elasticapm.label(a="x", b="y")
    elasticapm.set_custom_context({"a": "x", "b": "y"})
    cache.set(utils.stats.cache_key, utils.stats(), 60)
Esempio n. 4
0
def doc_qa(model_id: int, request: Question):
    with doc_qa_limiter.run():
        start_time = time.time()
        finder = FINDERS.get(model_id, None)
        if not finder:
            raise HTTPException(
                status_code=404, detail=f"Couldn't get Finder with ID {model_id}. Available IDs: {list(FINDERS.keys())}"
            )

        results = []
        for question in request.questions:
            if request.filters:
                # put filter values into a list and remove filters with null value
                filters = {key: [value] for key, value in request.filters.items() if value is not None}
                logger.info(f" [{datetime.now()}] Request: {request}")
            else:
                filters = {}

            result = finder.get_answers(
                question=question,
                top_k_retriever=request.top_k_retriever,
                top_k_reader=request.top_k_reader,
                filters=filters,
            )
            results.append(result)

        elasticapm.set_custom_context({"results": results})
        end_time = time.time()
        logger.info(json.dumps({"request": request.dict(), "results": results, "time": f"{(end_time - start_time):.2f}"}))

        return {"results": results}
Esempio n. 5
0
def faq_qa(model_id: int, request: Question):
    finder = FINDERS.get(model_id, None)
    if not finder:
        raise HTTPException(
            status_code=404,
            detail=
            f"Couldn't get Finder with ID {model_id}. Available IDs: {list(FINDERS.keys())}"
        )

    results = []
    for question in request.questions:
        if request.filters:
            # put filter values into a list and remove filters with null value
            filters = {
                key: [value]
                for key, value in request.filters.items() if value is not None
            }
            logger.info(f" [{datetime.now()}] Request: {request}")
        else:
            filters = {}

        result = finder.get_answers_via_similar_questions(
            question=question,
            top_k_retriever=request.top_k_retriever,
            filters=filters,
        )
        results.append(result)

    elasticapm.set_custom_context({"results": results})
    logger.info({"request": request.json(), "results": results})

    return {"results": results}
Esempio n. 6
0
def get_courses(student_id, semester):
    """
    提供学号与学期,返回学生当前学期的课表。

    :param student_id: 学号
    :param semester: 学期
    """
    import json
    from everyclass.server.db.dao import get_classes_for_student
    from everyclass.server.db.model import Semester
    from everyclass.server.exceptions import IllegalSemesterException, NoStudentException

    try:
        courses = get_classes_for_student(student_id, Semester(semester))
        # TODO: handle if semester does not exist

        elasticapm.set_custom_context(stu_id=student_id, semester=semester)

        courses_to_return = {}
        for k, v in courses.items():
            if str(k[0]) not in courses_to_return:
                courses_to_return[str(k[0])] = {}
            courses_to_return[str(k[0])][str(k[1])] = v
        return json.dumps({'courses': courses_to_return})
    except IllegalSemesterException:
        response = jsonify({'error': 'wrong semester'})
        response.status_code = 400
        return response
    except NoStudentException:
        response = jsonify({'error': 'no such student'})
        response.status_code = 400
        return response
Esempio n. 7
0
def post_order(request):
    data = json.loads(request.body)
    if 'customer_id' not in data:
        return HttpResponse(status=400)
    customer_obj = get_object_or_404(m.Customer, pk=data['customer_id'])
    order_obj = m.Order.objects.create(customer=customer_obj)

    total_amount = 0
    for line in data['lines']:
        product_obj = get_object_or_404(m.Product, pk=line['id'])
        m.OrderLine.objects.create(order=order_obj,
                                   product=product_obj,
                                   amount=line['amount'])
        total_amount += line['amount'] * product_obj.selling_price

    # store lines count in and total amount in tags
    label(
        lines_count=len(data['lines']),
        total_amount=total_amount / 100.0,
    )

    # store customer in transaction custom data
    elasticapm.set_custom_context({
        'customer_name': customer_obj.full_name,
        'customer_email': customer_obj.email,
    })
    return JsonResponse({'id': order_obj.pk})
Esempio n. 8
0
def ask_faq(model_id: int, request: Query):
    finder = FINDERS.get(model_id, None)
    if not finder:
        raise HTTPException(
            status_code=404, detail=f"Couldn't get Finder with ID {model_id}. Available IDs: {list(FINDERS.keys())}"
        )

    results = []
    for question in request.questions:
        if request.filters:
            # put filter values into a list and remove filters with null value
            request.filters = {key: [value] for key, value in request.filters.items() if value is not None}
            logger.info(f" [{datetime.now()}] Request: {request}")

        # temporary routing of requests by language
        result = finder.get_answers_via_similar_questions(
            question=question, top_k_retriever=request.top_k_retriever, filters=request.filters,
        )
        results.append(result)

        elasticapm.set_custom_context({"results": results})
        logger.info({"request": request.json(), "results": results})

        # remember questions with result in the autocomplete
        if len(results) > 0:
            addQuestionToAutocomplete(question)

        return {"results": results}
Esempio n. 9
0
    def ListRecommendations(self, request, context):
        # manually populate service map
        # this can be removed once 7.8 is out and the python agent adds this by itself
        product_catalog_destination_info = {
            "address": os.environ.get('PRODUCT_CATALOG_SERVICE_ADDR', ''),
            "port": int(os.environ.get('PORT', 8080)),
            "service": {
                "name": "grpc",
                "resource": os.environ.get('PRODUCT_CATALOG_SERVICE_ADDR', ''),
                "type": "external"
            },
        }

        trace_parent = self.extract_trace_parent(context)
        transaction = client.begin_transaction('request',
                                               trace_parent=trace_parent)
        request_dict = MessageToDict(request)
        elasticapm.label(**{'request': request_dict})
        max_responses = 5
        # fetch list of products from product catalog stub
        list_product_req = demo_pb2.Empty()
        with elasticapm.capture_span(
                '/hipstershop.ProductCatalogService/ListProducts',
                labels=MessageToDict(list_product_req),
                extra={"destination":
                       product_catalog_destination_info}) as span:
            trace_parent = transaction.trace_parent.copy_from(
                span_id=span.id, trace_options=TracingOptions(recorded=True))
            cat_response, call = product_catalog_stub.ListProducts.with_call(
                list_product_req,
                metadata=[(constants.TRACEPARENT_HEADER_NAME,
                           trace_parent.to_string())])
        with elasticapm.capture_span('CalculateRecommendations',
                                     span_subtype='grpc',
                                     span_action='calculate') as span:
            product_ids = [x.id for x in cat_response.products]
            filtered_products = list(
                set(product_ids) - set(request.product_ids))
            num_products = len(filtered_products)
            num_return = min(max_responses, num_products)
            # sample list of indicies to return
            indices = random.sample(range(num_products), num_return)
            # fetch product ids from indices
            prod_list = [filtered_products[i] for i in indices]
            logger.info(
                '[Recv ListRecommendations] product_ids={}'.format(prod_list),
                extra=get_extra_logging_payload())
            # build and return response
        response = demo_pb2.ListRecommendationsResponse()
        response.product_ids.extend(prod_list)
        elasticapm.label(**{'response': MessageToDict(response)})
        elasticapm.set_custom_context({
            'request': request_dict,
            'response': MessageToDict(response)
        })
        client.end_transaction(
            '/hipstershop.RecommendationService/ListRecommendations',
            'success')
        return response
Esempio n. 10
0
    def SendEmail(self, request, context, send_mail=True):
        trace_parent = None
        for key, value in context.invocation_metadata():
            if key.lower() == TRACEPARENT_HEADER_NAME:
                trace_parent = TraceParent.from_string(value)
        tx = client.begin_transaction('request', trace_parent=trace_parent)

        tx.ensure_parent_id()

        request_dict = MessageToDict(request)
        elasticapm.label(**{'request': request_dict})
        elasticapm.set_custom_context({
            'request':
            request_dict,
            'response':
            MessageToDict(demo_pb2.Empty())
        })
        email = request.email
        order = request.order
        parent_id = trace_parent.span_id

        span = tx._begin_span('template.render',
                              None,
                              parent_span_id=parent_id)

        try:
            confirmation = template.render(order=order)
            span.end()
        except TemplateError as err:
            client.capture_exception(context=request_dict, handled=True)
            context.set_details(
                'An error occurred when preparing the confirmation mail.')
            logger.error(err.message, extra=default_fields)
            context.set_code(grpc.StatusCode.INTERNAL)
            span.end()
            client.end_transaction(
                '/hipstershop.EmailService/SendOrderConfirmation', 'failure')
            return demo_pb2.Empty()

        span = tx._begin_span('send_email', None, parent_span_id=parent_id)
        try:
            self.send_email(email, confirmation, send_mail)
            span.end()
        except EmailSendException as err:
            client.capture_exception(context=request_dict, handled=True)
            context.set_details('An error occurred when sending the email.')
            logger.error('Failed to send email to %s' % email,
                         extra=get_extra_logging_payload())
            logger.error(err.message, extra=get_extra_logging_payload())
            context.set_code(grpc.StatusCode.INTERNAL)
            span.end()
            client.end_transaction(
                '/hipstershop.EmailService/SendOrderConfirmation', 'failure')
            return demo_pb2.Empty()
        elasticapm.label(**{'response': MessageToDict(demo_pb2.Empty())})
        client.end_transaction(
            '/hipstershop.EmailService/SendOrderConfirmation', 'success')
        return demo_pb2.Empty()
Esempio n. 11
0
def test_set_transaction_custom_data(elasticapm_client):
    elasticapm_client.begin_transaction("test")

    elasticapm.set_custom_context({"foo": "bar"})

    elasticapm_client.end_transaction("foo", 200)
    transactions = elasticapm_client.events[TRANSACTION]

    assert transactions[0]["context"]["custom"] == {"foo": "bar"}
Esempio n. 12
0
def test_set_transaction_custom_data(elasticapm_client):
    elasticapm_client.begin_transaction("test")

    elasticapm.set_custom_context({"foo": "bar"})

    elasticapm_client.end_transaction("foo", 200)
    transactions = elasticapm_client.transaction_store.get_all()

    assert transactions[0]["context"]["custom"] == {"foo": "bar"}
Esempio n. 13
0
def test_set_transaction_custom_data(elasticapm_client):
    elasticapm_client.begin_transaction('test')

    elasticapm.set_custom_context({'foo': 'bar'})

    elasticapm_client.end_transaction('foo', 200)
    transactions = elasticapm_client.instrumentation_store.get_all()

    assert transactions[0]['context']['custom'] == {'foo': 'bar'}
Esempio n. 14
0
def test_transaction_context_is_used_in_errors(elasticapm_client):
    elasticapm_client.begin_transaction("test")
    elasticapm.tag(foo="baz")
    elasticapm.set_custom_context({"a": "b"})
    elasticapm.set_user_context(username="******", email="*****@*****.**", user_id=42)
    elasticapm_client.capture_message("x", custom={"foo": "bar"})
    transaction = elasticapm_client.end_transaction("test", "OK")
    message = elasticapm_client.events[ERROR][0]
    assert message["context"]["custom"] == {"a": "b", "foo": "bar"}
    assert message["context"]["user"] == {"username": "******", "email": "*****@*****.**", "id": 42}
    assert message["context"]["tags"] == {"foo": "baz"}
    assert "a" in transaction.context["custom"]
    assert "foo" not in transaction.context["custom"]
Esempio n. 15
0
def test_transaction_context_is_used_in_errors(elasticapm_client):
    elasticapm_client.begin_transaction('test')
    elasticapm.tag(foo='baz')
    elasticapm.set_custom_context({'a': 'b'})
    elasticapm.set_user_context(username='******', email='*****@*****.**', user_id=42)
    elasticapm_client.capture_message('x', custom={'foo': 'bar'})
    transaction = elasticapm_client.end_transaction('test', 'OK')
    message = elasticapm_client.events[0]['errors'][0]
    assert message['context']['custom'] == {'a': 'b', 'foo': 'bar'}
    assert message['context']['user'] == {'username': '******', 'email': '*****@*****.**', 'id': 42}
    assert message['context']['tags'] == {'foo': 'baz'}
    assert 'a' in transaction.context['custom']
    assert 'foo' not in transaction.context['custom']
Esempio n. 16
0
    def process_request(self, req, resp):
        """
        req.stream corresponds to the WSGI wsgi.input environ variable,
        and allows you to read bytes from the request body.
        See also: PEP 3333
        """
        self.client.begin_transaction('web.falcon')

        context = {}
        context = self.get_data_from_request(req)
        context['hostname'] = self.hostname

        elasticapm.set_custom_context(context)
Esempio n. 17
0
def get_semesters(student_id):
    """
    提供学号,返回一个学生可用的学期。

    :param student_id: 学号
    """
    from everyclass.server.db.dao import get_my_semesters

    # todo: handle if student doesn't exist
    semesters, student_name = get_my_semesters(student_id)

    # Elastic apm 业务 context
    elasticapm.set_custom_context(stu_id=student_id)

    response = jsonify({'name': student_name,
                        'semesters': [s.to_str() for s in semesters]
                        })
    return response
Esempio n. 18
0
 async def _setup_custom_context(self, request: Request):
     if self._custom_context_callback:
         set_custom_context(data=await self._custom_context_callback(request))
     else:
         set_custom_context(data=await self._setup_default_custom_context(request=request))