Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions sentry_sdk/integrations/_wsgi_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,15 @@ def _is_json_content_type(ct: "Optional[str]") -> bool:
)


def _serialize_request_body_data(data: "Any") -> str:
def _default(value: "Any") -> "Any":
if isinstance(value, AnnotatedValue):
return value.value
return str(value)

return json.dumps(data, default=_default)


Comment thread
ericapisani marked this conversation as resolved.
Outdated
def _filter_headers(
headers: "Mapping[str, str]",
use_annotated_value: bool = True,
Expand Down
58 changes: 51 additions & 7 deletions sentry_sdk/integrations/flask.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
from typing import TYPE_CHECKING

import sentry_sdk
from sentry_sdk.integrations import _check_minimum_version, DidNotEnable, Integration
from sentry_sdk.integrations import DidNotEnable, Integration, _check_minimum_version
from sentry_sdk.integrations._wsgi_common import (
_RAW_DATA_EXCEPTIONS,
Comment thread
ericapisani marked this conversation as resolved.
Outdated
DEFAULT_HTTP_METHODS_TO_CAPTURE,
RequestExtractor,
_serialize_request_body_data,
request_body_within_bounds,
)
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
from sentry_sdk.scope import should_send_default_pii
from sentry_sdk.traces import StreamedSpan, _get_current_streamed_span
from sentry_sdk.tracing import SOURCE_FOR_STYLE
from sentry_sdk.tracing_utils import has_span_streaming_enabled
from sentry_sdk.utils import (
AnnotatedValue,
capture_internal_exceptions,
ensure_integration_enabled,
event_from_exception,
package_version,
)

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Any, Callable, Dict, Union

from werkzeug.datastructures import FileStorage, ImmutableMultiDict

from sentry_sdk._types import Event, EventProcessor
from sentry_sdk.integrations.wsgi import _ScopedResponse
from werkzeug.datastructures import FileStorage, ImmutableMultiDict


try:
Expand Down Expand Up @@ -94,10 +101,9 @@ def setup_once() -> None:
def sentry_patched_wsgi_app(
self: "Any", environ: "Dict[str, str]", start_response: "Callable[..., Any]"
) -> "_ScopedResponse":
if sentry_sdk.get_client().get_integration(FlaskIntegration) is None:
return old_app(self, environ, start_response)

integration = sentry_sdk.get_client().get_integration(FlaskIntegration)
if integration is None:
return old_app(self, environ, start_response)

middleware = SentryWsgiMiddleware(
lambda *a, **kw: old_app(self, *a, **kw),
Expand Down Expand Up @@ -158,6 +164,44 @@ def _request_started(app: "Flask", **kwargs: "Any") -> None:
evt_processor = _make_request_event_processor(app, request, integration)
scope.add_event_processor(evt_processor)

client = sentry_sdk.get_client()
if has_span_streaming_enabled(client.options):
_set_request_body_data_on_streaming_segment(request, client)
Comment thread
ericapisani marked this conversation as resolved.
Outdated


def _set_request_body_data_on_streaming_segment(
request: "Request", client: "sentry_sdk.client.BaseClient"
) -> None:
current_span = _get_current_streamed_span()
if type(current_span) is not StreamedSpan:
return

with capture_internal_exceptions():
content_length = int(request.content_length or 0)
extractor = FlaskRequestExtractor(request)

if not request_body_within_bounds(client, content_length):
data = AnnotatedValue.substituted_because_over_size_limit()
Comment thread
ericapisani marked this conversation as resolved.
Outdated
else:
raw_data = None
try:
raw_data = extractor.raw_data()
except _RAW_DATA_EXCEPTIONS:
pass

parsed_body = extractor.parsed_body()
if parsed_body is not None:
data = parsed_body
elif raw_data:
data = AnnotatedValue.substituted_because_raw_data()
else:
return

current_span._segment.set_attribute(
"http.request.body.data",
_serialize_request_body_data(data),
)


class FlaskRequestExtractor(RequestExtractor):
def env(self) -> "Dict[str, str]":
Expand Down
12 changes: 1 addition & 11 deletions sentry_sdk/integrations/starlette.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import functools
import json
import sys
import warnings
from collections.abc import Set
Expand All @@ -18,6 +17,7 @@
DEFAULT_HTTP_METHODS_TO_CAPTURE,
HttpCodeRangeContainer,
_is_json_content_type,
_serialize_request_body_data,
request_body_within_bounds,
)
from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
Expand Down Expand Up @@ -242,16 +242,6 @@ async def _sentry_send(*args: "Any", **kwargs: "Any") -> "Any":
return middleware_class


def _serialize_request_body_data(data: "Any") -> str:
# data may be a JSON-serializable value, an AnnotatedValue, or a dict with AnnotatedValue values
def _default(value: "Any") -> "Any":
if isinstance(value, AnnotatedValue):
return value.value
return str(value)

return json.dumps(data, default=_default)


def _set_request_body_data_on_streaming_segment(
info: "Optional[Dict[str, Any]]",
) -> None:
Expand Down
Loading
Loading