Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions sentry_sdk/integrations/aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ async def sentry_app_handle(
),
)

user_agent = request.headers.get("User-Agent")
if user_agent:
scope.set_attribute(SPANDATA.USER_AGENT_ORIGINAL, user_agent)

headers = dict(request.headers)

span_ctx: "ContextManager[Union[Span, StreamedSpan]]"
Expand Down
4 changes: 4 additions & 0 deletions sentry_sdk/integrations/sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ async def _context_enter(request: "Request") -> None:
),
)

user_agent = request.headers.get("user-agent")
if user_agent:
scope.set_attribute(SPANDATA.USER_AGENT_ORIGINAL, user_agent)

if is_span_streaming_enabled:
integration = client.get_integration(SanicIntegration)
if (
Expand Down
4 changes: 4 additions & 0 deletions sentry_sdk/integrations/tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ def _handle_request_impl(self: "RequestHandler") -> "Generator[None, None, None]
),
)

user_agent = headers.get("User-Agent")
if user_agent:
scope.set_attribute(SPANDATA.USER_AGENT_ORIGINAL, user_agent)

span_ctx: "ContextManager[Union[Span, StreamedSpan, None]]"

if is_span_streaming_enabled:
Expand Down
38 changes: 38 additions & 0 deletions tests/integrations/aiohttp/test_aiohttp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2472,6 +2472,44 @@ async def hello(request):
assert child_spans[0]["attributes"][SPANDATA.SENTRY_IS_LOCALHOST] == is_localhost


@pytest.mark.asyncio
async def test_user_agent_attribute(sentry_init, aiohttp_client, capture_items):
sentry_init(
integrations=[AioHttpIntegration()],
traces_sample_rate=1.0,
trace_lifecycle="stream",
)

async def hello(request):
with sentry_sdk.traces.start_span(name="child"):
pass
return web.Response(text="hello")

app = web.Application()
app.router.add_get("/", hello)

items = capture_items("span")

client = await aiohttp_client(app)
resp = await client.get("/", headers={"User-Agent": "TestBrowser/1.0"})
assert resp.status == 200

sentry_sdk.flush()

child_spans = [item.payload for item in items if not item.payload.get("is_segment")]
server_spans = [item.payload for item in items if item.payload.get("is_segment")]

assert len(server_spans) == 1
assert len(child_spans) == 1

assert (
server_spans[0]["attributes"][SPANDATA.USER_AGENT_ORIGINAL] == "TestBrowser/1.0"
)
assert (
child_spans[0]["attributes"][SPANDATA.USER_AGENT_ORIGINAL] == "TestBrowser/1.0"
)


@pytest.mark.asyncio
@pytest.mark.parametrize(
"init_kwargs, expect_remote_addr", DATA_COLLECTION_REMOTE_ADDR_CASES
Expand Down
34 changes: 34 additions & 0 deletions tests/integrations/sanic/test_sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -943,3 +943,37 @@ def child_span_handler_localhost(request):

assert server_span["attributes"]["sentry.is_localhost"] is is_localhost
assert child_span["attributes"]["sentry.is_localhost"] is is_localhost


@pytest.mark.skipif(
not PERFORMANCE_SUPPORTED, reason="Performance not supported on this Sanic version"
)
def test_user_agent_attribute(sentry_init, app, capture_items):
@app.route("/child-span")
def child_span_handler_ua(request):
with sentry_sdk.traces.start_span(name="child-span"):
pass
return response.text("ok")

sentry_init(
integrations=[SanicIntegration()],
default_integrations=False,
traces_sample_rate=1.0,
trace_lifecycle="stream",
)

items = capture_items("span")

c = get_client(app)
with c as client:
client.get(
"/child-span",
headers={"User-Agent": "TestBrowser/1.0"},
)

sentry_sdk.flush()

child_span, server_span = [item.payload for item in items]

assert server_span["attributes"]["user_agent.original"] == "TestBrowser/1.0"
assert child_span["attributes"]["user_agent.original"] == "TestBrowser/1.0"
28 changes: 28 additions & 0 deletions tests/integrations/tornado/test_tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -1165,6 +1165,34 @@ def test_is_localhost_span_attribute(
assert child_spans[0]["attributes"][SPANDATA.SENTRY_IS_LOCALHOST] == is_localhost


def test_user_agent_attribute(tornado_testcase, sentry_init, capture_items):
sentry_init(
integrations=[TornadoIntegration()],
traces_sample_rate=1.0,
trace_lifecycle="stream",
)

items = capture_items("span")

client = tornado_testcase(Application([(r"/hi", ChildSpanHandler)]))
client.fetch("/hi", headers={"User-Agent": "TestBrowser/1.0"})

sentry_sdk.flush()

child_spans = [item.payload for item in items if not item.payload.get("is_segment")]
server_spans = [item.payload for item in items if item.payload.get("is_segment")]

assert len(server_spans) == 1
assert len(child_spans) == 1

assert (
server_spans[0]["attributes"][SPANDATA.USER_AGENT_ORIGINAL] == "TestBrowser/1.0"
)
assert (
child_spans[0]["attributes"][SPANDATA.USER_AGENT_ORIGINAL] == "TestBrowser/1.0"
)


@pytest.mark.parametrize(
"init_kwargs, expect_remote_addr", DATA_COLLECTION_REMOTE_ADDR_CASES
)
Expand Down
Loading