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)
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
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)
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}
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}
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
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})
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}
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
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()
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"}
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"}
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'}
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"]
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']
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)
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
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))