Microsoft Azure Cost Management Client Library for Python providing comprehensive access to cost analysis, billing data, budgets, alerts, exports, and recommendations.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Query available cost dimensions for building filters and groupings in cost analysis. Access comprehensive metadata about available cost categories, resource types, billing dimensions, and hierarchy information to construct precise cost queries and reports.
Query and discover available dimensions for cost analysis, filtering, and grouping operations within specified scopes.
def list(
scope: str,
filter: str = None,
expand: str = None,
skiptoken: str = None,
top: int = None
) -> DimensionsListResult:
"""
List dimensions available for the specified scope.
Args:
scope (str): The scope to query dimensions for
filter (str): OData filter expression for filtering dimensions
expand (str): Expand options for additional dimension properties
skiptoken (str): Skiptoken for pagination
top (int): Maximum number of dimensions to return
Returns:
DimensionsListResult: Collection of available dimensions with metadata
"""
def by_external_cloud_provider_type(
external_cloud_provider_type: str,
external_cloud_provider_id: str,
filter: str = None,
expand: str = None,
skiptoken: str = None,
top: int = None
) -> DimensionsListResult:
"""
List dimensions for external cloud providers like AWS.
Args:
external_cloud_provider_type (str): Provider type (e.g., "aws")
external_cloud_provider_id (str): Provider account identifier
filter (str): OData filter expression
expand (str): Expand options for additional properties
skiptoken (str): Skiptoken for pagination
top (int): Maximum number of dimensions to return
Returns:
DimensionsListResult: Collection of external provider dimensions
"""# Get all available dimensions for subscription
scope = "/subscriptions/{subscription-id}"
dimensions = client.dimensions.list(scope=scope)
print(f"Available dimensions ({len(dimensions.value)}):")
for dimension in dimensions.value:
print(f" Name: {dimension.name}")
print(f" Display Name: {dimension.display_name}")
print(f" Category: {dimension.category}")
print(f" Description: {dimension.description}")
print(f" Filter Enabled: {dimension.filter_enabled}")
print(f" Grouping Enabled: {dimension.grouping_enabled}")
print(" ---")# Get only resource-related dimensions
resource_filter = "category eq 'Resource'"
resource_dimensions = client.dimensions.list(
scope=scope,
filter=resource_filter
)
print("Resource Dimensions:")
for dimension in resource_dimensions.value:
print(f" {dimension.name}: {dimension.display_name}")
if dimension.data:
print(f" Sample values: {dimension.data[:5]}") # Show first 5 values
# Get billing-related dimensions
billing_filter = "category eq 'Billing'"
billing_dimensions = client.dimensions.list(
scope=scope,
filter=billing_filter
)
print("\nBilling Dimensions:")
for dimension in billing_dimensions.value:
print(f" {dimension.name}: {dimension.display_name}")# Get dimensions with expanded data (actual values)
expanded_dimensions = client.dimensions.list(
scope=scope,
expand="data",
top=10 # Limit for performance
)
print("Dimensions with sample values:")
for dimension in expanded_dimensions.value:
print(f"\n{dimension.display_name} ({dimension.name}):")
print(f" Category: {dimension.category}")
print(f" Can Filter: {dimension.filter_enabled}")
print(f" Can Group: {dimension.grouping_enabled}")
if hasattr(dimension, 'data') and dimension.data:
print(f" Sample values ({len(dimension.data)} total):")
for value in dimension.data[:10]: # Show first 10 values
print(f" - {value}")
if len(dimension.data) > 10:
print(f" ... and {len(dimension.data) - 10} more")
else:
print(" Values: Use in query to see available values")from azure.mgmt.costmanagement.models import (
QueryDefinition,
QueryDataset,
QueryFilter,
QueryComparisonExpression,
QueryOperatorType,
TimeframeType,
GranularityType
)
# Get resource group dimension values to build filter
rg_dimensions = client.dimensions.list(
scope=scope,
filter="name eq 'ResourceGroup'",
expand="data"
)
if rg_dimensions.value:
rg_dimension = rg_dimensions.value[0]
# Use first few resource groups for filtering
if rg_dimension.data and len(rg_dimension.data) > 0:
selected_rgs = rg_dimension.data[:3] # Select first 3 resource groups
# Build query with dynamic filter
query_filter = QueryFilter(
and_=[
QueryComparisonExpression(
name="ResourceGroup",
operator=QueryOperatorType.IN,
values=selected_rgs
)
]
)
# Create query using discovered dimensions
query_def = QueryDefinition(
type="Usage",
timeframe=TimeframeType.THE_LAST_MONTH,
dataset=QueryDataset(
granularity=GranularityType.DAILY,
filter=query_filter
)
)
# Execute query
result = client.query.usage(scope, query_def)
print(f"Query returned {len(result.rows)} rows for RGs: {', '.join(selected_rgs)}")# Categorize dimensions by capabilities
filterable_dims = []
groupable_dims = []
both_dims = []
all_dimensions = client.dimensions.list(scope=scope)
for dimension in all_dimensions.value:
if dimension.filter_enabled and dimension.grouping_enabled:
both_dims.append(dimension)
elif dimension.filter_enabled:
filterable_dims.append(dimension)
elif dimension.grouping_enabled:
groupable_dims.append(dimension)
print(f"Dimension Capabilities Analysis:")
print(f" Filter + Group capable: {len(both_dims)} dimensions")
print(f" Filter only: {len(filterable_dims)} dimensions")
print(f" Group only: {len(groupable_dims)} dimensions")
print(f"\nRecommended dimensions for analysis (Filter + Group):")
for dim in both_dims[:10]: # Show top 10
print(f" - {dim.display_name} ({dim.name})")# Get AWS dimensions
try:
aws_dimensions = client.dimensions.by_external_cloud_provider_type(
external_cloud_provider_type="aws",
external_cloud_provider_id="123456789012"
)
print("AWS Dimensions:")
for dimension in aws_dimensions.value:
print(f" {dimension.name}: {dimension.display_name}")
print(f" Category: {dimension.category}")
print(f" Filterable: {dimension.filter_enabled}")
print(f" Groupable: {dimension.grouping_enabled}")
except Exception as e:
print(f"Error retrieving AWS dimensions: {e}")# Create a comprehensive catalog of dimensions
def build_dimension_catalog(scope):
"""Build a comprehensive catalog of available dimensions"""
catalog = {
"resource": [],
"billing": [],
"service": [],
"location": [],
"other": []
}
dimensions = client.dimensions.list(scope=scope, expand="data")
for dimension in dimensions.value:
dim_info = {
"name": dimension.name,
"display_name": dimension.display_name,
"category": dimension.category,
"filterable": dimension.filter_enabled,
"groupable": dimension.grouping_enabled,
"description": getattr(dimension, 'description', 'No description'),
"sample_values": dimension.data[:5] if hasattr(dimension, 'data') and dimension.data else []
}
# Categorize by common patterns
name_lower = dimension.name.lower()
if 'resource' in name_lower:
catalog["resource"].append(dim_info)
elif 'billing' in name_lower or 'invoice' in name_lower:
catalog["billing"].append(dim_info)
elif 'service' in name_lower or 'meter' in name_lower:
catalog["service"].append(dim_info)
elif 'location' in name_lower or 'region' in name_lower:
catalog["location"].append(dim_info)
else:
catalog["other"].append(dim_info)
return catalog
# Build and display catalog
dimension_catalog = build_dimension_catalog(scope)
for category, dims in dimension_catalog.items():
if dims:
print(f"\n{category.upper()} DIMENSIONS ({len(dims)}):")
for dim in dims:
print(f" {dim['display_name']}")
print(f" Name: {dim['name']}")
print(f" Capabilities: {'Filter' if dim['filterable'] else ''} {'Group' if dim['groupable'] else ''}")
if dim['sample_values']:
print(f" Samples: {', '.join(dim['sample_values'])}")# Build a dynamic cost report using discovered dimensions
def create_dynamic_report(scope, groupby_dimension="ResourceGroup"):
"""Create a cost report using a specified dimension for grouping"""
# Verify dimension exists and supports grouping
dimensions = client.dimensions.list(
scope=scope,
filter=f"name eq '{groupby_dimension}'"
)
if not dimensions.value:
print(f"Dimension '{groupby_dimension}' not found")
return None
dimension = dimensions.value[0]
if not dimension.grouping_enabled:
print(f"Dimension '{groupby_dimension}' does not support grouping")
return None
# Create query using the dimension
from azure.mgmt.costmanagement.models import QueryGrouping, QueryAggregation
query_def = QueryDefinition(
type="ActualCost",
timeframe=TimeframeType.THE_LAST_MONTH,
dataset=QueryDataset(
granularity=GranularityType.MONTHLY,
aggregation={
"totalCost": QueryAggregation(name="Cost", function="Sum")
},
grouping=[
QueryGrouping(type="Dimension", name=groupby_dimension)
]
)
)
result = client.query.usage(scope, query_def)
print(f"Cost Report by {dimension.display_name}:")
for row in result.rows:
group_value = row[0]
cost = row[1]
print(f" {group_value}: ${cost:.2f}")
return result
# Create reports using different dimensions
create_dynamic_report(scope, "ResourceGroup")
create_dynamic_report(scope, "ServiceName")
create_dynamic_report(scope, "Location")class Dimension:
id: str
name: str
type: str
category: str
display_name: str
description: str
filter_enabled: bool
grouping_enabled: bool
sort_enabled: bool
data: List[str]
total: int
next_link: str
class DimensionsListResult:
value: List[Dimension]
next_link: strThe Azure Cost Management API provides dimensions across several categories:
This module provides comprehensive dimension discovery capabilities for building sophisticated cost analysis queries with precise filtering, grouping, and categorization across all Azure billing and resource metadata.
Install with Tessl CLI
npx tessl i tessl/pypi-azure-mgmt-costmanagement