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
2 changes: 2 additions & 0 deletions src/containerapp/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Release History
===============
upcoming
++++++
* 'az containerapp function invocations': Update application insights query
* 'az containerapp function keys': Update minimum replica check

1.3.0b1
++++++
Expand Down
23 changes: 23 additions & 0 deletions src/containerapp/azext_containerapp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,17 @@ def create_acrpull_role_assignment_if_needed(cmd, registry_server, registry_iden
time.sleep(5)


def get_min_replicas_from_revision(cmd, resource_group_name, container_app_name, revision_name):
revision_def = ContainerAppClient.show_revision(
cmd=cmd,
resource_group_name=resource_group_name,
container_app_name=container_app_name,
name=revision_name
)
min_replicas = safe_get(revision_def, "properties", "template", "scale", "minReplicas", default=None)
return min_replicas


def get_random_replica(cmd, resource_group_name, container_app_name, revision_name):
logger.debug(f"Getting random replica for container app: name='{container_app_name}', resource_group='{resource_group_name}', revision='{revision_name}'")

Expand All @@ -851,6 +862,18 @@ def get_random_replica(cmd, resource_group_name, container_app_name, revision_na

if not replicas:
logger.debug(f"No replicas found for revision '{revision_name}' - unable to proceed")
logger.debug(f"checking min replica count for revision='{revision_name}'")

min_replicas = get_min_replicas_from_revision(
cmd,
resource_group_name,
container_app_name,
revision_name
)
if min_replicas is None or min_replicas == 0:
logger.debug(f"The revision '{revision_name}' has minReplicas set to 0.")
raise CLIError(f"The revision '{revision_name}' has minReplicas set to 0. Ensure that there is at least one replica. To update minimum replica: Run 'az containerapp update --name {container_app_name} --resource-group {resource_group_name} --min-replica 1'")

raise CLIError(f"No replicas found for revision '{revision_name}' of container app '{container_app_name}'.")

# Filter replicas by running state
Expand Down
6 changes: 3 additions & 3 deletions src/containerapp/azext_containerapp/_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ def validate_revision_and_get_name(cmd, resource_group_name, container_app_name,
if not provided_revision_name:
logger.debug("No revision name provided for multiple revision mode container app")
raise ValidationError("Revision name is required when active revision mode is not 'single'.")
return provided_revision_name
return provided_revision_name, active_revision_mode
if not provided_revision_name:
logger.debug("No revision name provided - attempting to determine latest revision")
revision_name = safe_get(containerapp_def, "properties", "latestRevisionName")
Expand All @@ -331,9 +331,9 @@ def validate_revision_and_get_name(cmd, resource_group_name, container_app_name,
if not revision_name or revision_name is None:
logger.debug("Could not determine any revision name from container app properties")
raise ValidationError("Could not determine the latest revision name. Please provide --revision.")
return revision_name
return revision_name, active_revision_mode
logger.debug("Using provided revision name: '%s'", provided_revision_name)
return provided_revision_name
return provided_revision_name, active_revision_mode


def validate_functionapp_kind(cmd, resource_group_name, container_app_name):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def validate_common_arguments(self):
)

# Validate revision and get the appropriate revision name
revision_name = validate_revision_and_get_name(
revision_name, _ = validate_revision_and_get_name(
cmd=self.cmd,
resource_group_name=resource_group_name,
container_app_name=name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def validate_common_arguments(self):
)

# Validate revision and get the appropriate revision name
revision_name = validate_revision_and_get_name(
revision_name, _ = validate_revision_and_get_name(
cmd=self.cmd,
resource_group_name=resource_group_name,
container_app_name=name,
Expand Down Expand Up @@ -170,6 +170,10 @@ class ContainerAppFunctionInvocationsDecorator(ContainerAppFunctionsDecorator):

APP_INSIGHTS_API_VERSION = "2018-04-20"

def __init__(self, cmd, client, raw_parameters, models):
super().__init__(cmd, client, raw_parameters, models)
self.active_revision_mode = None

def validate_arguments(self):
"""Validate arguments required for function invocation operations"""
validate_basic_arguments(
Expand All @@ -185,14 +189,17 @@ def validate_arguments(self):
)

revision_name = self.get_argument_revision_name()
revision_name = validate_revision_and_get_name(
revision_name, active_revision_mode = validate_revision_and_get_name(
cmd=self.cmd,
resource_group_name=self.get_argument_resource_group_name(),
container_app_name=self.get_argument_container_app_name(),
provided_revision_name=revision_name
)

# Update the revision name with the validated value
self.set_argument_revision_name(revision_name)
# Store active revision mode for use in query building
self.active_revision_mode = active_revision_mode
self.validate_function_name_requirement()

def _get_app_insights_id(self, resource_group_name, container_app_name, revision_name):
Expand Down Expand Up @@ -267,12 +274,14 @@ def get_summary(self):
# Fetch the app insights resource app id
app_id = self._get_app_insights_id(resource_group_name, container_app_name, revision_name)

# Use application insights query to get function invocations summary
# Set revision_name to empty string for single mode, keep it for multiple mode
revision_name = "" if self.active_revision_mode.lower() == "single" else revision_name

invocation_summary_query = (
f"requests | extend functionNameFromCustomDimension = tostring(customDimensions['faas.name']) "
f"| where timestamp >= ago({timespan}) "
f"| where cloud_RoleName =~ '{container_app_name}' "
f"| where cloud_RoleInstance contains '{revision_name}' "
f"| where isempty(\"{revision_name}\") or cloud_RoleInstance contains '{revision_name}' "
f"| where operation_Name =~ '{function_name}' or functionNameFromCustomDimension =~ '{function_name}' "
f"| summarize SuccessCount = coalesce(countif(success == true), 0), ErrorCount = coalesce(countif(success == false), 0)"
)
Expand All @@ -299,14 +308,16 @@ def get_traces(self):
# Fetch the app insights resource app id
app_id = self._get_app_insights_id(resource_group_name, container_app_name, revision_name)

# Use application insights query to get function invocations traces
# Set revision_name to empty string for single mode, keep it for multiple mode
revision_name = "" if self.active_revision_mode.lower() == "single" else revision_name

invocation_traces_query = (
f"requests | extend functionNameFromCustomDimension = tostring(customDimensions['faas.name']) "
f"| project timestamp, id, operation_Name, success, resultCode, duration, operation_Id, functionNameFromCustomDimension, "
f"cloud_RoleName, cloud_RoleInstance, invocationId=coalesce(tostring(customDimensions['InvocationId']), tostring(customDimensions['faas.invocation_id'])) "
f"| where timestamp > ago({timespan}) "
f"| where cloud_RoleName =~ '{container_app_name}' "
f"| where cloud_RoleInstance contains '{revision_name}' "
f"| where isempty(\"{revision_name}\") or cloud_RoleInstance contains '{revision_name}' "
f"| where operation_Name =~ '{function_name}' or functionNameFromCustomDimension =~ '{function_name}' "
f"| order by timestamp desc | take {limit} "
f"| project timestamp, success, resultCode, durationInMilliSeconds=duration, invocationId, operationId=operation_Id, operationName=operation_Name, functionNameFromCustomDimension "
Expand Down
Loading