|
22 | 22 |
|
23 | 23 | from botocore.response import StreamingBody |
24 | 24 |
|
25 | | -from newrelic.api.datastore_trace import datastore_trace |
| 25 | +from newrelic.api.datastore_trace import DatastoreTrace |
26 | 26 | from newrelic.api.external_trace import ExternalTrace |
27 | 27 | from newrelic.api.function_trace import FunctionTrace |
28 | 28 | from newrelic.api.message_trace import MessageTrace, message_trace |
@@ -841,6 +841,118 @@ def handle_chat_completion_event(transaction, bedrock_attrs): |
841 | 841 | ) |
842 | 842 |
|
843 | 843 |
|
| 844 | +def dynamodb_datastore_trace( |
| 845 | + product, |
| 846 | + target, |
| 847 | + operation, |
| 848 | + host=None, |
| 849 | + port_path_or_id=None, |
| 850 | + database_name=None, |
| 851 | + async_wrapper=None, |
| 852 | +): |
| 853 | + @function_wrapper |
| 854 | + def _nr_dynamodb_datastore_trace_wrapper_(wrapped, instance, args, kwargs): |
| 855 | + wrapper = async_wrapper if async_wrapper is not None else get_async_wrapper(wrapped) |
| 856 | + if not wrapper: |
| 857 | + parent = current_trace() |
| 858 | + if not parent: |
| 859 | + return wrapped(*args, **kwargs) |
| 860 | + else: |
| 861 | + parent = None |
| 862 | + |
| 863 | + if callable(product): |
| 864 | + if instance is not None: |
| 865 | + _product = product(instance, *args, **kwargs) |
| 866 | + else: |
| 867 | + _product = product(*args, **kwargs) |
| 868 | + else: |
| 869 | + _product = product |
| 870 | + |
| 871 | + if callable(target): |
| 872 | + if instance is not None: |
| 873 | + _target = target(instance, *args, **kwargs) |
| 874 | + else: |
| 875 | + _target = target(*args, **kwargs) |
| 876 | + else: |
| 877 | + _target = target |
| 878 | + |
| 879 | + if callable(operation): |
| 880 | + if instance is not None: |
| 881 | + _operation = operation(instance, *args, **kwargs) |
| 882 | + else: |
| 883 | + _operation = operation(*args, **kwargs) |
| 884 | + else: |
| 885 | + _operation = operation |
| 886 | + |
| 887 | + if callable(host): |
| 888 | + if instance is not None: |
| 889 | + _host = host(instance, *args, **kwargs) |
| 890 | + else: |
| 891 | + _host = host(*args, **kwargs) |
| 892 | + else: |
| 893 | + _host = host |
| 894 | + |
| 895 | + if callable(port_path_or_id): |
| 896 | + if instance is not None: |
| 897 | + _port_path_or_id = port_path_or_id(instance, *args, **kwargs) |
| 898 | + else: |
| 899 | + _port_path_or_id = port_path_or_id(*args, **kwargs) |
| 900 | + else: |
| 901 | + _port_path_or_id = port_path_or_id |
| 902 | + |
| 903 | + if callable(database_name): |
| 904 | + if instance is not None: |
| 905 | + _database_name = database_name(instance, *args, **kwargs) |
| 906 | + else: |
| 907 | + _database_name = database_name(*args, **kwargs) |
| 908 | + else: |
| 909 | + _database_name = database_name |
| 910 | + |
| 911 | + trace = DatastoreTrace( |
| 912 | + _product, _target, _operation, _host, _port_path_or_id, _database_name, parent=parent, source=wrapped |
| 913 | + ) |
| 914 | + |
| 915 | + # Try to capture AWS DynamoDB info as agent attributes. Log any exception to debug. |
| 916 | + agent_attrs = {} |
| 917 | + try: |
| 918 | + region = None |
| 919 | + if hasattr(instance, "_client_config") and hasattr(instance._client_config, "region_name"): |
| 920 | + region = instance._client_config.region_name |
| 921 | + |
| 922 | + transaction = current_transaction() |
| 923 | + settings = transaction.settings if transaction.settings else global_settings() |
| 924 | + account_id = settings.cloud.aws.account_id if settings and settings.cloud.aws.account_id else None |
| 925 | + |
| 926 | + # There are 3 different partition options. |
| 927 | + # See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html for details. |
| 928 | + partition = None |
| 929 | + if hasattr(instance, "_endpoint") and hasattr(instance._endpoint, "host"): |
| 930 | + _db_host = instance._endpoint.host |
| 931 | + partition = "aws" |
| 932 | + if "amazonaws.cn" in _db_host: |
| 933 | + partition = "aws-cn" |
| 934 | + elif "amazonaws-us-gov.com" in _db_host: |
| 935 | + partition = "aws-us-gov" |
| 936 | + |
| 937 | + if partition and region and account_id and _target: |
| 938 | + agent_attrs["cloud.resource_id"] = ( |
| 939 | + f"arn:{partition}:dynamodb:{region}:{account_id:012d}:table/{_target}" |
| 940 | + ) |
| 941 | + agent_attrs["db.system"] = "DynamoDB" |
| 942 | + |
| 943 | + except Exception as e: |
| 944 | + _logger.debug("Failed to capture AWS DynamoDB info.", exc_info=True) |
| 945 | + trace.agent_attributes.update(agent_attrs) |
| 946 | + |
| 947 | + if wrapper: # pylint: disable=W0125,W0126 |
| 948 | + return wrapper(wrapped, trace)(*args, **kwargs) |
| 949 | + |
| 950 | + with trace: |
| 951 | + return wrapped(*args, **kwargs) |
| 952 | + |
| 953 | + return _nr_dynamodb_datastore_trace_wrapper_ |
| 954 | + |
| 955 | + |
844 | 956 | def sqs_message_trace( |
845 | 957 | operation, |
846 | 958 | destination_type, |
@@ -891,14 +1003,14 @@ def _nr_sqs_message_trace_wrapper_(wrapped, instance, args, kwargs): |
891 | 1003 |
|
892 | 1004 | CUSTOM_TRACE_POINTS = { |
893 | 1005 | ("sns", "publish"): message_trace("SNS", "Produce", "Topic", extract(("TopicArn", "TargetArn"), "PhoneNumber")), |
894 | | - ("dynamodb", "put_item"): datastore_trace("DynamoDB", extract("TableName"), "put_item"), |
895 | | - ("dynamodb", "get_item"): datastore_trace("DynamoDB", extract("TableName"), "get_item"), |
896 | | - ("dynamodb", "update_item"): datastore_trace("DynamoDB", extract("TableName"), "update_item"), |
897 | | - ("dynamodb", "delete_item"): datastore_trace("DynamoDB", extract("TableName"), "delete_item"), |
898 | | - ("dynamodb", "create_table"): datastore_trace("DynamoDB", extract("TableName"), "create_table"), |
899 | | - ("dynamodb", "delete_table"): datastore_trace("DynamoDB", extract("TableName"), "delete_table"), |
900 | | - ("dynamodb", "query"): datastore_trace("DynamoDB", extract("TableName"), "query"), |
901 | | - ("dynamodb", "scan"): datastore_trace("DynamoDB", extract("TableName"), "scan"), |
| 1006 | + ("dynamodb", "put_item"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "put_item"), |
| 1007 | + ("dynamodb", "get_item"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "get_item"), |
| 1008 | + ("dynamodb", "update_item"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "update_item"), |
| 1009 | + ("dynamodb", "delete_item"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "delete_item"), |
| 1010 | + ("dynamodb", "create_table"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "create_table"), |
| 1011 | + ("dynamodb", "delete_table"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "delete_table"), |
| 1012 | + ("dynamodb", "query"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "query"), |
| 1013 | + ("dynamodb", "scan"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "scan"), |
902 | 1014 | ("sqs", "send_message"): sqs_message_trace( |
903 | 1015 | "Produce", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs |
904 | 1016 | ), |
|
0 commit comments