diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 335d9025d7..6b10de08d6 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -63,6 +63,7 @@ Span ops are now a smaller, framework-neutral set. - The Django integration now emits `view.render` instead of `view.response.render`, `view` instead of `view.authenticate`, and `function` instead of `event.django`. - The Django, Starlette, Starlite, and Litestar integrations now emit `middleware` instead of `middleware.django`, `middleware.starlette`, `middleware.starlette.receive`, `middleware.starlette.send`, `middleware.starlite`, `middleware.starlite.receive`, `middleware.starlite.send`, `middleware.litestar`, `middleware.litestar.receive`, and `middleware.litestar.send`. - The ARQ, Celery, Django, Dramatiq, Huey, RQ, and Ray integrations now emit `queue.publish` and `queue.process` instead of `queue.submit.arq`, `queue.task.arq`, `queue.submit.celery`, `queue.task.celery`, `queue.submit.django`, `queue.task.dramatiq`, `queue.submit.huey`, `queue.task.huey`, `queue.task.rq`, `queue.submit.ray`, and `queue.task.ray`. +- The Boto3 integration now emits `rpc` instead of `http.client` for AWS API calls. #### GenAI span attributes diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index abf1464b68..7ab271473e 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -1389,6 +1389,7 @@ class OP: QUEUE_TASK_RAY = "queue.task.ray" QUEUE_TASK_DRAMATIQ = "queue.task.dramatiq" QUEUE_SUBMIT_DJANGO = "queue.submit.django" + RPC = "rpc" SUBPROCESS = "subprocess" SUBPROCESS_WAIT = "subprocess.wait" SUBPROCESS_COMMUNICATE = "subprocess.communicate" diff --git a/sentry_sdk/integrations/boto3/_instrumentation.py b/sentry_sdk/integrations/boto3/_instrumentation.py index e3ee4fd7d6..fab0122ccb 100644 --- a/sentry_sdk/integrations/boto3/_instrumentation.py +++ b/sentry_sdk/integrations/boto3/_instrumentation.py @@ -169,7 +169,7 @@ def _start_client_span( # `sentry.op` and `sentry.origin` are set to generic defaults; # a service extension can override them with `get_span_op()` and `get_span_origin()`. - span_op = OP.HTTP_CLIENT + span_op = OP.RPC span_origin = ORIGIN if service_ext is not None: diff --git a/tests/integrations/boto3/test_client.py b/tests/integrations/boto3/test_client.py index 087a6ec7df..163fc515bc 100644 --- a/tests/integrations/boto3/test_client.py +++ b/tests/integrations/boto3/test_client.py @@ -146,7 +146,7 @@ def record_client_span(request, **kwargs): if span["name"] == "S3.GetObject" and ( span.get("attributes", {}).get(SPANDATA.SENTRY_ORIGIN) == ORIGIN - and span.get("attributes", {}).get(SPANDATA.SENTRY_OP) == OP.HTTP_CLIENT + and span.get("attributes", {}).get(SPANDATA.SENTRY_OP) == OP.RPC ) ] http_spans = [ @@ -231,7 +231,7 @@ def invoke(): assert sentry_sdk.get_current_span() is parent spans_by_op = _capture_boto3_spans_by_op(invoke, capture_items) - (client_span,) = spans_by_op[OP.HTTP_CLIENT] + (client_span,) = spans_by_op[OP.RPC] (stream_span,) = spans_by_op[OP.HTTP_CLIENT_STREAM] assert stream_span.get("parent_span_id") == client_span["span_id"] @@ -251,7 +251,7 @@ def test_omit_url_data_if_parsing_fails(capture_items, client_factory): ) parse_url.assert_called() - (span,) = spans_by_op[OP.HTTP_CLIENT] + (span,) = spans_by_op[OP.RPC] attributes = span.get("attributes", {}) assert SPANDATA.URL_FULL not in attributes assert SPANDATA.URL_FRAGMENT not in attributes @@ -326,7 +326,7 @@ def test_url_query_data_collection( (span,) = [ item.payload for item in items - if item.payload.get("attributes", {}).get(SPANDATA.SENTRY_OP) == OP.HTTP_CLIENT + if item.payload.get("attributes", {}).get(SPANDATA.SENTRY_OP) == OP.RPC ] attributes = span.get("attributes", {}) @@ -428,7 +428,7 @@ def _capture_stubbed_client_span( ) stubber.assert_no_pending_responses() - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) assert len(client_spans) == 1 return client_spans[0] @@ -580,7 +580,7 @@ def test_client_call_has_common_attributes( assert span["name"] == span_name assert span.get("end_timestamp") is not None - assert attributes[SPANDATA.SENTRY_OP] == OP.HTTP_CLIENT + assert attributes[SPANDATA.SENTRY_OP] == OP.RPC assert attributes[SPANDATA.SENTRY_ORIGIN] == ORIGIN assert attributes[SPANDATA.SENTRY_KIND] == "client" assert attributes[SPANDATA.CLOUD_PROVIDER] == CLOUD_PROVIDER @@ -651,7 +651,7 @@ def test_client_call_has_response_header_attributes( capture_items, ) - spans = spans_by_op[OP.HTTP_CLIENT] + spans = spans_by_op[OP.RPC] assert len(spans) == 1 attributes = spans[0].get("attributes", {}) assert attributes[SPANDATA.HTTP_STATUS_CODE] == 200 @@ -670,7 +670,7 @@ def test_retry_attempts_share_one_client_span( spans_by_op = _capture_boto3_spans_by_op( lambda: client.head_object(Bucket="bucket", Key="foo"), capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) assert len(request_span_ids) == attempt_count # all `AWSRequest` instances created during retries reference the same client span. @@ -693,7 +693,7 @@ def attempt_failed_head_object_call(): spans_by_op = _capture_boto3_spans_by_op( attempt_failed_head_object_call, capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) assert len(request_span_ids) == 2 assert len(set(request_span_ids)) == 1 @@ -749,14 +749,14 @@ def invoke_failing_client_method(): spans_by_op = _capture_boto3_spans_by_op( invoke_failing_client_method, capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) _assert_one_failed_span(client_spans) attributes = client_spans[0].get("attributes", {}) span = client_spans[0] assert span["name"] == "S3.HeadObject" assert span.get("end_timestamp") is not None - assert attributes[SPANDATA.SENTRY_OP] == OP.HTTP_CLIENT + assert attributes[SPANDATA.SENTRY_OP] == OP.RPC assert attributes[SPANDATA.SENTRY_ORIGIN] == ORIGIN assert attributes[SPANDATA.SENTRY_KIND] == "client" assert attributes[SPANDATA.CLOUD_PROVIDER] == CLOUD_PROVIDER @@ -810,7 +810,7 @@ def invoke_failing_client_method(): spans_by_op = _capture_boto3_spans_by_op( invoke_failing_client_method, capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) _assert_one_failed_span(client_spans) expected_error_type = ( @@ -856,7 +856,7 @@ def invoke_client_method(): stubber.add_response("head_object", original_response, api_params) spans_by_op = _capture_boto3_spans_by_op(invoke_client_method, capture_items) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) assert returned_responses == [original_response] assert returned_responses[0] is original_response if failing_instrumentation == "_get_response_attributes": @@ -893,7 +893,7 @@ def invoke_failing_client_method(): spans_by_op = _capture_boto3_spans_by_op( invoke_failing_client_method, capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) assert len(client_spans) == 1 assert client_spans[0]["status"] == "error" @@ -926,7 +926,7 @@ def invoke_client_method_and_read_body(): spans_by_op = _capture_boto3_spans_by_op( invoke_client_method_and_read_body, capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) stream_spans = spans_by_op.get(OP.HTTP_CLIENT_STREAM, []) assert len(client_spans) == 1 @@ -975,7 +975,7 @@ def invoke_client_method_and_read_body(): spans_by_op = _capture_boto3_spans_by_op( invoke_client_method_and_read_body, capture_items ) - client_spans = spans_by_op.get(OP.HTTP_CLIENT, []) + client_spans = spans_by_op.get(OP.RPC, []) stream_spans = spans_by_op.get(OP.HTTP_CLIENT_STREAM, []) assert len(client_spans) == 1 diff --git a/tests/integrations/boto3/test_dynamodb.py b/tests/integrations/boto3/test_dynamodb.py index 339628099c..5399e035ae 100644 --- a/tests/integrations/boto3/test_dynamodb.py +++ b/tests/integrations/boto3/test_dynamodb.py @@ -36,7 +36,7 @@ def test_request_attributes( lambda: getattr(client, method)(**params), capture_items ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] if expected_resource_id is None: assert SPANDATA.CLOUD_ACCOUNT_ID not in attributes diff --git a/tests/integrations/boto3/test_kinesis.py b/tests/integrations/boto3/test_kinesis.py index c3911b078d..c643d62595 100644 --- a/tests/integrations/boto3/test_kinesis.py +++ b/tests/integrations/boto3/test_kinesis.py @@ -18,7 +18,7 @@ def test_request_attributes(client_factory, capture_items): capture_items, ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" assert attributes[SPANDATA.CLOUD_RESOURCE_ID] == stream_arn diff --git a/tests/integrations/boto3/test_lambda.py b/tests/integrations/boto3/test_lambda.py index d74818fd3b..00c5d58df1 100644 --- a/tests/integrations/boto3/test_lambda.py +++ b/tests/integrations/boto3/test_lambda.py @@ -16,7 +16,7 @@ def test_request_attributes(client_factory, capture_items): capture_items, ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" assert attributes[SPANDATA.CLOUD_RESOURCE_ID] == function_arn diff --git a/tests/integrations/boto3/test_s3.py b/tests/integrations/boto3/test_s3.py index c21dfbb713..0e1ef6a6e5 100644 --- a/tests/integrations/boto3/test_s3.py +++ b/tests/integrations/boto3/test_s3.py @@ -26,12 +26,12 @@ def _stubbed_span(client, capture_items, method, params, response): lambda: getattr(client, method)(**params), capture_items ) stubber.assert_no_pending_responses() - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] operation = client.meta.method_to_api_mapping[method] assert span["name"] == "S3.%s" % operation assert span.get("end_timestamp") is not None attributes = span.get("attributes", {}) - assert attributes[SPANDATA.SENTRY_OP] == OP.HTTP_CLIENT + assert attributes[SPANDATA.SENTRY_OP] == OP.RPC assert attributes[SPANDATA.SENTRY_ORIGIN] == ORIGIN assert attributes[SPANDATA.SENTRY_KIND] == "client" assert attributes[SPANDATA.CLOUD_PROVIDER] == "aws" diff --git a/tests/integrations/boto3/test_secretsmanager.py b/tests/integrations/boto3/test_secretsmanager.py index f44f25515a..da0a844e13 100644 --- a/tests/integrations/boto3/test_secretsmanager.py +++ b/tests/integrations/boto3/test_secretsmanager.py @@ -22,7 +22,7 @@ def test_request_attributes(client_factory, capture_items): capture_items, ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" assert attributes[SPANDATA.CLOUD_RESOURCE_ID] == secret_arn diff --git a/tests/integrations/boto3/test_sns.py b/tests/integrations/boto3/test_sns.py index 7e613e919e..7f593d357e 100644 --- a/tests/integrations/boto3/test_sns.py +++ b/tests/integrations/boto3/test_sns.py @@ -15,7 +15,7 @@ def test_request_attributes(client_factory, capture_items): lambda: client.delete_topic(**{"TopicArn": topic_arn}), capture_items ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" assert attributes[SPANDATA.CLOUD_RESOURCE_ID] == topic_arn diff --git a/tests/integrations/boto3/test_sqs.py b/tests/integrations/boto3/test_sqs.py index b05d40de91..ecc81c69d9 100644 --- a/tests/integrations/boto3/test_sqs.py +++ b/tests/integrations/boto3/test_sqs.py @@ -33,7 +33,7 @@ def test_request_attributes(client_factory, capture_items, source): lambda: getattr(client, method)(**params), capture_items ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" if resource_id is None: diff --git a/tests/integrations/boto3/test_stepfunctions.py b/tests/integrations/boto3/test_stepfunctions.py index 52de542eb3..e080effc46 100644 --- a/tests/integrations/boto3/test_stepfunctions.py +++ b/tests/integrations/boto3/test_stepfunctions.py @@ -20,7 +20,7 @@ def test_request_attributes(client_factory, capture_items): capture_items, ) - (span,) = spans[OP.HTTP_CLIENT] + (span,) = spans[OP.RPC] attributes = span["attributes"] assert attributes[SPANDATA.CLOUD_ACCOUNT_ID] == "123456789012" assert attributes[SPANDATA.CLOUD_RESOURCE_ID] == state_machine_arn