Skip to content

Commit de08634

Browse files
authored
AWS Kinesis Delivery Streams (Firehose) Entity Mapping (#1300)
* Fix tox naming convention for botocore * Firehose instrumentation * Firehose testing * Fix broken s3transfer test * Correct naming of firehose ARN * Clean up boto3 tests * Correct naming of list_delivery_streams * Convert firehose message traces to function traces * Correct behaviors of kinesis operations without stream targets * Control flow tweaks
1 parent 819b6d7 commit de08634

File tree

5 files changed

+329
-40
lines changed

5 files changed

+329
-40
lines changed

newrelic/hooks/external_botocore.py

+89-27
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,18 @@ def extract_sqs(*args, **kwargs):
6060

6161
def extract_kinesis(*args, **kwargs):
6262
# The stream name can be passed as the StreamName or as part of the StreamARN.
63-
stream_value = kwargs.get("StreamName", "Unknown")
64-
if stream_value == "Unknown":
63+
stream_value = kwargs.get("StreamName", None)
64+
if stream_value is None:
6565
arn = kwargs.get("StreamARN", None)
66-
if arn:
66+
if arn is not None:
6767
stream_value = arn.split("/", 1)[-1]
6868
return stream_value
6969

7070

71+
def extract_firehose(*args, **kwargs):
72+
return kwargs.get("DeliveryStreamName", None)
73+
74+
7175
def extract_sqs_agent_attrs(instance, *args, **kwargs):
7276
# Try to capture AWS SQS info as agent attributes. Log any exception to debug.
7377
agent_attrs = {}
@@ -110,6 +114,29 @@ def extract_kinesis_agent_attrs(instance, *args, **kwargs):
110114
return agent_attrs
111115

112116

117+
def extract_firehose_agent_attrs(instance, *args, **kwargs):
118+
# Try to generate AWS Kinesis Delivery Stream (Firehose) ARN from the DeliveryStreamName parameter and from various
119+
# discoverable info. Log any exception to debug.
120+
agent_attrs = {}
121+
try:
122+
stream_name = kwargs.get("DeliveryStreamName", None)
123+
if stream_name:
124+
transaction = current_transaction()
125+
settings = transaction.settings if transaction.settings else global_settings()
126+
account_id = settings.cloud.aws.account_id if settings and settings.cloud.aws.account_id else None
127+
region = None
128+
if hasattr(instance, "_client_config") and hasattr(instance._client_config, "region_name"):
129+
region = instance._client_config.region_name
130+
if account_id and region:
131+
agent_attrs["cloud.platform"] = "aws_kinesis_delivery_streams"
132+
agent_attrs["cloud.resource_id"] = (
133+
f"arn:aws:firehose:{region}:{account_id}:deliverystream/{stream_name}"
134+
)
135+
except Exception as e:
136+
_logger.debug("Failed to capture AWS Kinesis Delivery Stream (Firehose) info.", exc_info=True)
137+
return agent_attrs
138+
139+
113140
def extract(argument_names, default=None):
114141
def extractor_list(*args, **kwargs):
115142
for argument_name in argument_names:
@@ -991,7 +1018,7 @@ def _nr_dynamodb_datastore_trace_wrapper_(wrapped, instance, args, kwargs):
9911018

9921019
def aws_function_trace(
9931020
operation,
994-
destination_name,
1021+
destination_name=None,
9951022
params={},
9961023
terminal=False,
9971024
async_wrapper=None,
@@ -1008,19 +1035,20 @@ def _nr_aws_function_trace_wrapper_(wrapped, instance, args, kwargs):
10081035
else:
10091036
parent = None
10101037

1011-
_destination_name = destination_name(*args, **kwargs)
1038+
_destination_name = destination_name(*args, **kwargs) if destination_name is not None else None
1039+
name = f"{operation}/{_destination_name}" if _destination_name else operation
10121040

10131041
trace = FunctionTrace(
1014-
name=_destination_name,
1015-
group=f"{library}/{operation}",
1042+
name=name,
1043+
group=library,
10161044
params=params,
10171045
terminal=terminal,
10181046
parent=parent,
10191047
source=wrapped,
10201048
)
10211049

10221050
# Attach extracted agent attributes.
1023-
_agent_attrs = extract_agent_attrs(instance, *args, **kwargs)
1051+
_agent_attrs = extract_agent_attrs(instance, *args, **kwargs) if extract_agent_attrs is not None else {}
10241052
trace.agent_attributes.update(_agent_attrs)
10251053

10261054
if wrapper: # pylint: disable=W0125,W0126
@@ -1055,7 +1083,7 @@ def _nr_aws_message_trace_wrapper_(wrapped, instance, args, kwargs):
10551083
_library = library
10561084
_operation = operation
10571085
_destination_type = destination_type
1058-
_destination_name = destination_name(*args, **kwargs)
1086+
_destination_name = destination_name(*args, **kwargs) or "Unknown"
10591087

10601088
trace = MessageTrace(
10611089
_library,
@@ -1150,9 +1178,7 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
11501178
extract_agent_attrs=extract_kinesis_agent_attrs,
11511179
library="Kinesis",
11521180
),
1153-
("kinesis", "delete_resource_policy"): aws_function_trace(
1154-
"delete_resource_policy", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
1155-
),
1181+
("kinesis", "delete_resource_policy"): aws_function_trace("delete_resource_policy", library="Kinesis"),
11561182
("kinesis", "delete_stream"): aws_function_trace(
11571183
"delete_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
11581184
),
@@ -1162,9 +1188,7 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
11621188
extract_agent_attrs=extract_kinesis_agent_attrs,
11631189
library="Kinesis",
11641190
),
1165-
("kinesis", "describe_limits"): aws_function_trace(
1166-
"describe_limits", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
1167-
),
1191+
("kinesis", "describe_limits"): aws_function_trace("describe_limits", library="Kinesis"),
11681192
("kinesis", "describe_stream"): aws_function_trace(
11691193
"describe_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
11701194
),
@@ -1186,9 +1210,7 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
11861210
extract_agent_attrs=extract_kinesis_agent_attrs,
11871211
library="Kinesis",
11881212
),
1189-
("kinesis", "get_resource_policy"): aws_function_trace(
1190-
"get_resource_policy", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
1191-
),
1213+
("kinesis", "get_resource_policy"): aws_function_trace("get_resource_policy", library="Kinesis"),
11921214
("kinesis", "get_shard_iterator"): aws_function_trace(
11931215
"get_shard_iterator", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
11941216
),
@@ -1204,18 +1226,14 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
12041226
("kinesis", "list_stream_consumers"): aws_function_trace(
12051227
"list_stream_consumers", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12061228
),
1207-
("kinesis", "list_streams"): aws_function_trace(
1208-
"list_streams", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
1209-
),
1229+
("kinesis", "list_streams"): aws_function_trace("list_streams", library="Kinesis"),
12101230
("kinesis", "list_tags_for_stream"): aws_function_trace(
12111231
"list_tags_for_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12121232
),
12131233
("kinesis", "merge_shards"): aws_function_trace(
12141234
"merge_shards", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12151235
),
1216-
("kinesis", "put_resource_policy"): aws_function_trace(
1217-
"put_resource_policy", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
1218-
),
1236+
("kinesis", "put_resource_policy"): aws_function_trace("put_resource_policy", library="Kinesis"),
12191237
("kinesis", "register_stream_consumer"): aws_function_trace(
12201238
"register_stream_consumer", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12211239
),
@@ -1231,9 +1249,7 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
12311249
("kinesis", "stop_stream_encryption"): aws_function_trace(
12321250
"stop_stream_encryption", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12331251
),
1234-
("kinesis", "subscribe_to_shard"): aws_function_trace(
1235-
"subscribe_to_shard", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
1236-
),
1252+
("kinesis", "subscribe_to_shard"): aws_function_trace("subscribe_to_shard", library="Kinesis"),
12371253
("kinesis", "update_shard_count"): aws_function_trace(
12381254
"update_shard_count", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12391255
),
@@ -1249,6 +1265,52 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
12491265
("kinesis", "get_records"): aws_message_trace(
12501266
"Consume", "Stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
12511267
),
1268+
("firehose", "create_delivery_stream"): aws_function_trace(
1269+
"create_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1270+
),
1271+
("firehose", "delete_delivery_stream"): aws_function_trace(
1272+
"delete_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1273+
),
1274+
("firehose", "describe_delivery_stream"): aws_function_trace(
1275+
"describe_delivery_stream",
1276+
extract_firehose,
1277+
extract_agent_attrs=extract_firehose_agent_attrs,
1278+
library="Firehose",
1279+
),
1280+
("firehose", "list_delivery_streams"): aws_function_trace("list_delivery_streams", library="Firehose"),
1281+
("firehose", "list_tags_for_delivery_stream"): aws_function_trace(
1282+
"list_tags_for_delivery_stream",
1283+
extract_firehose,
1284+
extract_agent_attrs=extract_firehose_agent_attrs,
1285+
library="Firehose",
1286+
),
1287+
("firehose", "put_record"): aws_function_trace(
1288+
"put_record", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1289+
),
1290+
("firehose", "put_record_batch"): aws_function_trace(
1291+
"put_record_batch", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1292+
),
1293+
("firehose", "start_delivery_stream_encryption"): aws_function_trace(
1294+
"start_delivery_stream_encryption",
1295+
extract_firehose,
1296+
extract_agent_attrs=extract_firehose_agent_attrs,
1297+
library="Firehose",
1298+
),
1299+
("firehose", "stop_delivery_stream_encryption"): aws_function_trace(
1300+
"stop_delivery_stream_encryption",
1301+
extract_firehose,
1302+
extract_agent_attrs=extract_firehose_agent_attrs,
1303+
library="Firehose",
1304+
),
1305+
("firehose", "tag_delivery_stream"): aws_function_trace(
1306+
"tag_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1307+
),
1308+
("firehose", "untag_delivery_stream"): aws_function_trace(
1309+
"untag_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1310+
),
1311+
("firehose", "update_destination"): aws_function_trace(
1312+
"update_destination", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
1313+
),
12521314
("sqs", "send_message"): aws_message_trace(
12531315
"Produce", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs, library="SQS"
12541316
),

0 commit comments

Comments
 (0)