Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: newrelic/newrelic-python-agent
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v10.5.0
Choose a base ref
...
head repository: newrelic/newrelic-python-agent
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v10.6.0
Choose a head ref
  • 6 commits
  • 6 files changed
  • 4 contributors

Commits on Jan 30, 2025

  1. Use name instead of ref

    hmstepanek committed Jan 30, 2025

    Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    8465b9a View commit details
  2. Merge branch 'main' into fix-ref

    mergify[bot] authored Jan 30, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    f4cc3ae View commit details
  3. Merge pull request #1297 from newrelic/fix-ref

    Use name instead of ref
    hmstepanek authored Jan 30, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    95d54a7 View commit details

Commits on Feb 3, 2025

  1. Add aws entity support for Kinesis (#1283)

    * Add support for kinesis
    
    * Fixup: comment
    
    * Minor tweaks to kinesis
    
    * Fixup: missing library name
    
    ---------
    
    Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
    Co-authored-by: Tim Pansino <timpansino@gmail.com>
    3 people authored Feb 3, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    819b6d7 View commit details

Commits on Feb 5, 2025

  1. 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
    TimPansino authored Feb 5, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    de08634 View commit details

Commits on Feb 6, 2025

  1. Kinesis ResourceARN and ConsumerARN Parsing (#1302)

    * Add parsing for kinesis ResourceARN and ConsumerARN
    
    * Add updated testing for kinesis
    
    * Fixup: lint errors
    
    ---------
    
    Co-authored-by: Hannah Stepanek <hstepanek@newrelic.com>
    TimPansino and hmstepanek authored Feb 6, 2025

    Partially verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    We cannot verify signatures from co-authors, and some of the co-authors attributed to this commit require their commits to be signed.
    Copy the full SHA
    9abd5a1 View commit details
6 changes: 3 additions & 3 deletions .github/workflows/deploy-python.yml
Original file line number Diff line number Diff line change
@@ -187,9 +187,9 @@ jobs:

- name: Create release tags for Lambda and K8s Init Containers
run: |
RELEASE_TITLE="New Relic Python Agent ${GITHUB_REF}.0"
RELEASE_TAG="${GITHUB_REF}.0_python"
RELEASE_NOTES="Automated release for [Python Agent ${GITHUB_REF}](https://github.com/newrelic/newrelic-python-agent/releases/tag/${GITHUB_REF})"
RELEASE_TITLE="New Relic Python Agent ${GITHUB_REF_NAME}.0"
RELEASE_TAG="${GITHUB_REF_NAME}.0_python"
RELEASE_NOTES="Automated release for [Python Agent ${GITHUB_REF_NAME}](https://github.com/newrelic/newrelic-python-agent/releases/tag/${GITHUB_REF_NAME})"
gh auth login --with-token <<< $GH_RELEASE_TOKEN
echo "newrelic/newrelic-lambda-layers - Releasing \"${RELEASE_TITLE}\" with tag ${RELEASE_TAG}"
gh release create "${RELEASE_TAG}" --title="${RELEASE_TITLE}" --repo=newrelic/newrelic-lambda-layers --notes="${RELEASE_NOTES}"
297 changes: 284 additions & 13 deletions newrelic/hooks/external_botocore.py
Original file line number Diff line number Diff line change
@@ -58,7 +58,22 @@ def extract_sqs(*args, **kwargs):
return queue_value.rsplit("/", 1)[-1]


def extract_sqs_agent_attrs(*args, **kwargs):
def extract_kinesis(*args, **kwargs):
# The stream name can be passed as the StreamName or as part of the StreamARN, ResourceARN, or ConsumerARN.
stream_name = kwargs.get("StreamName", None)
if stream_name is not None:
return stream_name

arn = kwargs.get("StreamARN", None) or kwargs.get("ResourceARN", None) or kwargs.get("ConsumerARN", None)
if arn is not None:
return arn.split("/")[1]


def extract_firehose(*args, **kwargs):
return kwargs.get("DeliveryStreamName", None)


def extract_sqs_agent_attrs(instance, *args, **kwargs):
# Try to capture AWS SQS info as agent attributes. Log any exception to debug.
agent_attrs = {}
try:
@@ -75,6 +90,64 @@ def extract_sqs_agent_attrs(*args, **kwargs):
return agent_attrs


def extract_kinesis_agent_attrs(instance, *args, **kwargs):
# Try to capture AWS Kinesis ARN from the StreamARN, ConsumerARN, or ResourceARN parameters, or by generating the
# ARN from various discoverable info. Log any exception to debug.
agent_attrs = {}
try:
stream_arn = kwargs.get("StreamARN", None)
if stream_arn is not None:
agent_attrs["cloud.platform"] = "aws_kinesis_data_streams"
agent_attrs["cloud.resource_id"] = stream_arn
return agent_attrs

stream_name = kwargs.get("StreamName", None)
if stream_name is not None:
transaction = current_transaction()
settings = transaction.settings if transaction.settings else global_settings()
account_id = settings.cloud.aws.account_id if settings and settings.cloud.aws.account_id else None
region = None
if hasattr(instance, "_client_config") and hasattr(instance._client_config, "region_name"):
region = instance._client_config.region_name
if stream_name and account_id and region:
agent_attrs["cloud.platform"] = "aws_kinesis_data_streams"
agent_attrs["cloud.resource_id"] = f"arn:aws:kinesis:{region}:{account_id}:stream/{stream_name}"

resource_arn = kwargs.get("ResourceARN", None) or kwargs.get("ConsumerARN", None)
if resource_arn is not None:
# Extract just the StreamARN out of ConsumerARNs.
agent_attrs["cloud.resource_id"] = "/".join(resource_arn.split("/")[0:2])
agent_attrs["cloud.platform"] = "aws_kinesis_data_streams"
return agent_attrs

except Exception as e:
_logger.debug("Failed to capture AWS Kinesis info.", exc_info=True)
return agent_attrs


def extract_firehose_agent_attrs(instance, *args, **kwargs):
# Try to generate AWS Kinesis Delivery Stream (Firehose) ARN from the DeliveryStreamName parameter and from various
# discoverable info. Log any exception to debug.
agent_attrs = {}
try:
stream_name = kwargs.get("DeliveryStreamName", None)
if stream_name:
transaction = current_transaction()
settings = transaction.settings if transaction.settings else global_settings()
account_id = settings.cloud.aws.account_id if settings and settings.cloud.aws.account_id else None
region = None
if hasattr(instance, "_client_config") and hasattr(instance._client_config, "region_name"):
region = instance._client_config.region_name
if account_id and region:
agent_attrs["cloud.platform"] = "aws_kinesis_delivery_streams"
agent_attrs["cloud.resource_id"] = (
f"arn:aws:firehose:{region}:{account_id}:deliverystream/{stream_name}"
)
except Exception as e:
_logger.debug("Failed to capture AWS Kinesis Delivery Stream (Firehose) info.", exc_info=True)
return agent_attrs


def extract(argument_names, default=None):
def extractor_list(*args, **kwargs):
for argument_name in argument_names:
@@ -954,17 +1027,62 @@ def _nr_dynamodb_datastore_trace_wrapper_(wrapped, instance, args, kwargs):
return _nr_dynamodb_datastore_trace_wrapper_


def sqs_message_trace(
def aws_function_trace(
operation,
destination_name=None,
params={},
terminal=False,
async_wrapper=None,
extract_agent_attrs=None,
library=None,
):
@function_wrapper
def _nr_aws_function_trace_wrapper_(wrapped, instance, args, kwargs):
wrapper = async_wrapper if async_wrapper is not None else get_async_wrapper(wrapped)
if not wrapper:
parent = current_trace()
if not parent:
return wrapped(*args, **kwargs)
else:
parent = None

_destination_name = destination_name(*args, **kwargs) if destination_name is not None else None
name = f"{operation}/{_destination_name}" if _destination_name else operation

trace = FunctionTrace(
name=name,
group=library,
params=params,
terminal=terminal,
parent=parent,
source=wrapped,
)

# Attach extracted agent attributes.
_agent_attrs = extract_agent_attrs(instance, *args, **kwargs) if extract_agent_attrs is not None else {}
trace.agent_attributes.update(_agent_attrs)

if wrapper: # pylint: disable=W0125,W0126
return wrapper(wrapped, trace)(*args, **kwargs)

with trace:
return wrapped(*args, **kwargs)

return _nr_aws_function_trace_wrapper_


def aws_message_trace(
operation,
destination_type,
destination_name,
params={},
terminal=True,
async_wrapper=None,
extract_agent_attrs=None,
library=None,
):
@function_wrapper
def _nr_sqs_message_trace_wrapper_(wrapped, instance, args, kwargs):
def _nr_aws_message_trace_wrapper_(wrapped, instance, args, kwargs):
wrapper = async_wrapper if async_wrapper is not None else get_async_wrapper(wrapped)
if not wrapper:
parent = current_trace()
@@ -973,10 +1091,10 @@ def _nr_sqs_message_trace_wrapper_(wrapped, instance, args, kwargs):
else:
parent = None

_library = "SQS"
_library = library
_operation = operation
_destination_type = destination_type
_destination_name = destination_name(*args, **kwargs)
_destination_name = destination_name(*args, **kwargs) or "Unknown"

trace = MessageTrace(
_library,
@@ -990,7 +1108,7 @@ def _nr_sqs_message_trace_wrapper_(wrapped, instance, args, kwargs):
)

# Attach extracted agent attributes.
_agent_attrs = extract_agent_attrs(*args, **kwargs)
_agent_attrs = extract_agent_attrs(instance, *args, **kwargs)
trace.agent_attributes.update(_agent_attrs)

if wrapper: # pylint: disable=W0125,W0126
@@ -999,7 +1117,7 @@ def _nr_sqs_message_trace_wrapper_(wrapped, instance, args, kwargs):
with trace:
return wrapped(*args, **kwargs)

return _nr_sqs_message_trace_wrapper_
return _nr_aws_message_trace_wrapper_


def wrap_emit_api_params(wrapped, instance, args, kwargs):
@@ -1059,14 +1177,167 @@ def wrap_serialize_to_request(wrapped, instance, args, kwargs):
("dynamodb", "delete_table"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "delete_table"),
("dynamodb", "query"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "query"),
("dynamodb", "scan"): dynamodb_datastore_trace("DynamoDB", extract("TableName"), "scan"),
("sqs", "send_message"): sqs_message_trace(
"Produce", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs
("kinesis", "add_tags_to_stream"): aws_function_trace(
"add_tags_to_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "create_stream"): aws_function_trace(
"create_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "decrease_stream_retention_period"): aws_function_trace(
"decrease_stream_retention_period",
extract_kinesis,
extract_agent_attrs=extract_kinesis_agent_attrs,
library="Kinesis",
),
("kinesis", "delete_resource_policy"): aws_function_trace(
"delete_resource_policy", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "delete_stream"): aws_function_trace(
"delete_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "deregister_stream_consumer"): aws_function_trace(
"deregister_stream_consumer",
extract_kinesis,
extract_agent_attrs=extract_kinesis_agent_attrs,
library="Kinesis",
),
("kinesis", "describe_limits"): aws_function_trace("describe_limits", library="Kinesis"),
("kinesis", "describe_stream"): aws_function_trace(
"describe_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "describe_stream_consumer"): aws_function_trace(
"describe_stream_consumer", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "describe_stream_summary"): aws_function_trace(
"describe_stream_summary", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "disable_enhanced_monitoring"): aws_function_trace(
"disable_enhanced_monitoring",
extract_kinesis,
extract_agent_attrs=extract_kinesis_agent_attrs,
library="Kinesis",
),
("kinesis", "enable_enhanced_monitoring"): aws_function_trace(
"enable_enhanced_monitoring",
extract_kinesis,
extract_agent_attrs=extract_kinesis_agent_attrs,
library="Kinesis",
),
("kinesis", "get_resource_policy"): aws_function_trace(
"get_resource_policy", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "get_shard_iterator"): aws_function_trace(
"get_shard_iterator", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "increase_stream_retention_period"): aws_function_trace(
"increase_stream_retention_period",
extract_kinesis,
extract_agent_attrs=extract_kinesis_agent_attrs,
library="Kinesis",
),
("kinesis", "list_shards"): aws_function_trace(
"list_shards", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "list_stream_consumers"): aws_function_trace(
"list_stream_consumers", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "list_streams"): aws_function_trace("list_streams", library="Kinesis"),
("kinesis", "list_tags_for_stream"): aws_function_trace(
"list_tags_for_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "merge_shards"): aws_function_trace(
"merge_shards", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "put_resource_policy"): aws_function_trace(
"put_resource_policy", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "register_stream_consumer"): aws_function_trace(
"register_stream_consumer", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "remove_tags_from_stream"): aws_function_trace(
"remove_tags_from_stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "split_shard"): aws_function_trace(
"split_shard", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "start_stream_encryption"): aws_function_trace(
"start_stream_encryption", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "stop_stream_encryption"): aws_function_trace(
"stop_stream_encryption", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "subscribe_to_shard"): aws_function_trace(
"subscribe_to_shard", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "update_shard_count"): aws_function_trace(
"update_shard_count", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "update_stream_mode"): aws_function_trace(
"update_stream_mode", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "put_record"): aws_message_trace(
"Produce", "Stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "put_records"): aws_message_trace(
"Produce", "Stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("kinesis", "get_records"): aws_message_trace(
"Consume", "Stream", extract_kinesis, extract_agent_attrs=extract_kinesis_agent_attrs, library="Kinesis"
),
("firehose", "create_delivery_stream"): aws_function_trace(
"create_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("firehose", "delete_delivery_stream"): aws_function_trace(
"delete_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("firehose", "describe_delivery_stream"): aws_function_trace(
"describe_delivery_stream",
extract_firehose,
extract_agent_attrs=extract_firehose_agent_attrs,
library="Firehose",
),
("firehose", "list_delivery_streams"): aws_function_trace("list_delivery_streams", library="Firehose"),
("firehose", "list_tags_for_delivery_stream"): aws_function_trace(
"list_tags_for_delivery_stream",
extract_firehose,
extract_agent_attrs=extract_firehose_agent_attrs,
library="Firehose",
),
("firehose", "put_record"): aws_function_trace(
"put_record", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("firehose", "put_record_batch"): aws_function_trace(
"put_record_batch", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("firehose", "start_delivery_stream_encryption"): aws_function_trace(
"start_delivery_stream_encryption",
extract_firehose,
extract_agent_attrs=extract_firehose_agent_attrs,
library="Firehose",
),
("firehose", "stop_delivery_stream_encryption"): aws_function_trace(
"stop_delivery_stream_encryption",
extract_firehose,
extract_agent_attrs=extract_firehose_agent_attrs,
library="Firehose",
),
("firehose", "tag_delivery_stream"): aws_function_trace(
"tag_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("firehose", "untag_delivery_stream"): aws_function_trace(
"untag_delivery_stream", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("firehose", "update_destination"): aws_function_trace(
"update_destination", extract_firehose, extract_agent_attrs=extract_firehose_agent_attrs, library="Firehose"
),
("sqs", "send_message"): aws_message_trace(
"Produce", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs, library="SQS"
),
("sqs", "send_message_batch"): sqs_message_trace(
"Produce", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs
("sqs", "send_message_batch"): aws_message_trace(
"Produce", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs, library="SQS"
),
("sqs", "receive_message"): sqs_message_trace(
"Consume", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs
("sqs", "receive_message"): aws_message_trace(
"Consume", "Queue", extract_sqs, extract_agent_attrs=extract_sqs_agent_attrs, library="SQS"
),
("bedrock-runtime", "invoke_model"): wrap_bedrock_runtime_invoke_model(response_streaming=False),
("bedrock-runtime", "invoke_model_with_response_stream"): wrap_bedrock_runtime_invoke_model(
Loading