-
Notifications
You must be signed in to change notification settings - Fork 555
Capturing Performance monitoring transactions for AWS and GCP #830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
86af238
25edf3c
57d3df6
23b6112
38c4862
a871932
067d051
e397dac
675a8e3
f971d4e
8a2a177
0ee84ba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,9 +3,9 @@ | |
import sys | ||
|
||
from sentry_sdk.hub import Hub, _should_send_default_pii | ||
from sentry_sdk.tracing import Transaction | ||
from sentry_sdk._compat import reraise | ||
from sentry_sdk.utils import ( | ||
AnnotatedValue, | ||
capture_internal_exceptions, | ||
event_from_exception, | ||
logger, | ||
|
@@ -78,7 +78,6 @@ def sentry_handler(event, context, *args, **kwargs): | |
with hub.push_scope() as scope: | ||
with capture_internal_exceptions(): | ||
scope.clear_breadcrumbs() | ||
scope.transaction = context.function_name | ||
scope.add_event_processor( | ||
_make_request_event_processor(event, context, configured_time) | ||
) | ||
|
@@ -99,17 +98,22 @@ def sentry_handler(event, context, *args, **kwargs): | |
# Starting the thread to raise timeout warning exception | ||
timeout_thread.start() | ||
|
||
try: | ||
return handler(event, context, *args, **kwargs) | ||
except Exception: | ||
exc_info = sys.exc_info() | ||
event, hint = event_from_exception( | ||
exc_info, | ||
client_options=client.options, | ||
mechanism={"type": "aws_lambda", "handled": False}, | ||
) | ||
hub.capture_event(event, hint=hint) | ||
reraise(*exc_info) | ||
headers = _filter_headers(event.get("headers", {})) | ||
transaction = Transaction.continue_from_headers( | ||
headers, op="serverless.function", name=context.function_name | ||
) | ||
with hub.start_transaction(transaction): | ||
try: | ||
return handler(event, context, *args, **kwargs) | ||
except Exception: | ||
exc_info = sys.exc_info() | ||
event, hint = event_from_exception( | ||
exc_info, | ||
client_options=client.options, | ||
mechanism={"type": "aws_lambda", "handled": False}, | ||
) | ||
hub.capture_event(event, hint=hint) | ||
reraise(*exc_info) | ||
|
||
return sentry_handler # type: ignore | ||
|
||
|
@@ -277,10 +281,8 @@ def event_processor(event, hint, start_time=start_time): | |
if "headers" in aws_event: | ||
request["headers"] = _filter_headers(aws_event["headers"]) | ||
|
||
if aws_event.get("body", None): | ||
# Unfortunately couldn't find a way to get structured body from AWS | ||
# event. Meaning every body is unstructured to us. | ||
request["data"] = AnnotatedValue("", {"rem": [["!raw", "x", 0, 0]]}) | ||
if "body" in aws_event: | ||
request["data"] = aws_event.get("body", "") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @untitaker I made this change to display the request body appear on Sentry Dashboard as shown below. This change was discussed with AJ. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please restore the old behavior when the client option Also please restore the code comment. The reason for this is that we want to be safe by default: the request body can contain a lot of sensitive data and setting sendDefaultPii is our way of having the user say "I accept the risks". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @untitaker you mean that essentially, I move this section of code I've written to the if section for send_default_pii part and revert the changes here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry I mean
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I'll make these changes asap. |
||
|
||
if _should_send_default_pii(): | ||
user_info = event.setdefault("user", {}) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
from datetime import datetime, timedelta | ||
from os import environ | ||
import sys | ||
import json | ||
|
||
from sentry_sdk.hub import Hub | ||
from sentry_sdk.tracing import Transaction | ||
from sentry_sdk._compat import reraise | ||
from sentry_sdk.utils import ( | ||
capture_internal_exceptions, | ||
|
@@ -11,6 +13,7 @@ | |
TimeoutThread, | ||
) | ||
from sentry_sdk.integrations import Integration | ||
from sentry_sdk.integrations._wsgi_common import _filter_headers | ||
|
||
from sentry_sdk._types import MYPY | ||
|
||
|
@@ -31,13 +34,13 @@ | |
|
||
def _wrap_func(func): | ||
# type: (F) -> F | ||
def sentry_func(*args, **kwargs): | ||
# type: (*Any, **Any) -> Any | ||
def sentry_func(functionhandler, event, *args, **kwargs): | ||
# type: (Any, Any, *Any, **Any) -> Any | ||
untitaker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
hub = Hub.current | ||
integration = hub.get_integration(GcpIntegration) | ||
if integration is None: | ||
return func(*args, **kwargs) | ||
return func(functionhandler, event, *args, **kwargs) | ||
untitaker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# If an integration is there, a client has to be there. | ||
client = hub.client # type: Any | ||
|
@@ -47,7 +50,7 @@ def sentry_func(*args, **kwargs): | |
logger.debug( | ||
"The configured timeout could not be fetched from Cloud Functions configuration." | ||
) | ||
return func(*args, **kwargs) | ||
return func(functionhandler, event, *args, **kwargs) | ||
untitaker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
configured_time = int(configured_time) | ||
|
||
|
@@ -56,11 +59,9 @@ def sentry_func(*args, **kwargs): | |
with hub.push_scope() as scope: | ||
with capture_internal_exceptions(): | ||
scope.clear_breadcrumbs() | ||
scope.transaction = environ.get("FUNCTION_NAME") | ||
scope.add_event_processor( | ||
_make_request_event_processor(configured_time, initial_time) | ||
_make_request_event_processor(event, configured_time, initial_time) | ||
) | ||
try: | ||
if ( | ||
integration.timeout_warning | ||
and configured_time > TIMEOUT_WARNING_BUFFER | ||
|
@@ -71,19 +72,28 @@ def sentry_func(*args, **kwargs): | |
|
||
# Starting the thread to raise timeout warning exception | ||
timeout_thread.start() | ||
return func(*args, **kwargs) | ||
except Exception: | ||
exc_info = sys.exc_info() | ||
event, hint = event_from_exception( | ||
exc_info, | ||
client_options=client.options, | ||
mechanism={"type": "gcp", "handled": False}, | ||
) | ||
hub.capture_event(event, hint=hint) | ||
reraise(*exc_info) | ||
finally: | ||
# Flush out the event queue | ||
hub.flush() | ||
|
||
headers = {} | ||
if hasattr(event, "headers"): | ||
headers = _filter_headers(event.headers) | ||
untitaker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
transaction = Transaction.continue_from_headers( | ||
headers, op="serverless.function", name=environ.get("FUNCTION_NAME", "") | ||
) | ||
with hub.start_transaction(transaction): | ||
try: | ||
return func(functionhandler, event, *args, **kwargs) | ||
except Exception: | ||
exc_info = sys.exc_info() | ||
event, hint = event_from_exception( | ||
exc_info, | ||
client_options=client.options, | ||
mechanism={"type": "gcp", "handled": False}, | ||
) | ||
hub.capture_event(event, hint=hint) | ||
reraise(*exc_info) | ||
finally: | ||
# Flush out the event queue | ||
hub.flush() | ||
|
||
return sentry_func # type: ignore | ||
|
||
|
@@ -113,8 +123,8 @@ def setup_once(): | |
) | ||
|
||
|
||
def _make_request_event_processor(configured_timeout, initial_time): | ||
# type: (Any, Any) -> EventProcessor | ||
def _make_request_event_processor(gcp_event, configured_timeout, initial_time): | ||
# type: (Any, Any, Any) -> EventProcessor | ||
|
||
def event_processor(event, hint): | ||
# type: (Event, Hint) -> Optional[Event] | ||
|
@@ -143,6 +153,18 @@ def event_processor(event, hint): | |
|
||
request["url"] = "gcp:///{}".format(environ.get("FUNCTION_NAME")) | ||
|
||
if hasattr(gcp_event, "method"): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @untitaker I've modified event processor for GCP integration to get request related for Sentry dashboard. |
||
request["method"] = gcp_event.method | ||
|
||
if hasattr(gcp_event, "query_string"): | ||
request["query_string"] = gcp_event.query_string.decode("utf-8") | ||
|
||
if hasattr(gcp_event, "headers"): | ||
request["headers"] = _filter_headers(gcp_event.headers) | ||
|
||
if hasattr(gcp_event, "data"): | ||
shantanu73 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
request["data"] = json.loads(gcp_event.data) | ||
|
||
event["request"] = request | ||
|
||
return event | ||
|
Uh oh!
There was an error while loading. Please reload this page.