我正在开发一个Python 3脚本,旨在使用Boto3库从AWS CloudFront获取S3空间利用率统计信息。
我从AWS CLI开始,发现我可以通过这样的命令获得我所追求的内容:
aws cloudwatch get-metric-statistics --metric-name BucketSizeBytes --namespace AWS/S3 --start-time 2017-03-06T00:00:00Z --end-time 2017-03-07T00:00:00Z --statistics Average --unit Bytes --region us-west-2 --dimensions Name=BucketName,Value=foo-bar Name=StorageType,Value=StandardStorage --period 86400 --output json
这将返回我期望的数据。现在我想在Python 3 / Boto3中做同样的事情。我的代码就是:
from datetime import datetime, timedelta
import boto3
seconds_in_one_day = 86400 # used for granularity
cloudwatch = boto3.client('cloudwatch')
response = cloudwatch.get_metric_statistics(
Namespace='AWS/S3',
Dimensions=[
{
'Name': 'BucketName',
'Value': 'foo-bar'
},
{
'Name': 'StorageType',
'Value': 'StandardStorage'
}
],
MetricName='BucketSizeBytes',
StartTime=datetime.now() - timedelta(days=7),
EndTime=datetime.now(),
Period=seconds_in_one_day,
Statistics=[
'Average'
],
Unit='Bytes'
)
print(response)
当我运行它时,我得到一个有效的响应但没有数据点(它是一个空数组)。它们似乎是相同的,除了Python方法似乎没有区域,命令行需要它。
我尝试了另外一件事:我的代码是计算最后日期的日期与硬编码的命令行。我确实试着编写日期,只是为了看看我是否会得到数据,结果是一样的。
所以我的问题是:
我在Boto / Python中使用的方法是否等同于命令行?假设它们是,我可能会失踪什么?
我没有看到你的代码有任何明显的错误,所以这个地区看起来像是一个主要的嫌疑人。
您可以在创建客户端时使用以下命令设置:
cloudwatch = boto3.client('cloudwatch', region_name='us-west-2')
如果未设置,boto将首先尝试从AWS_DEFAULT_REGION
env变量获取区域,然后尝试~/.aws/config
配置文件。尝试检查那些以查看默认区域集。
我能够解决这个问题。您需要在boto3调用中指定Dimensions参数。
我有一个可行的解决办法,以防其他人需要这个,但我仍然希望找到一个非kludgy答案,如果存在。它可能不会。我决定只生成命令行并使用python运行它并检索json结果 - 相同的结果。
s3 = boto3.resource('s3')
s3_client = boto3.client('s3')
command = "aws cloudwatch get-metric-statistics --metric-name BucketSizeBytes --namespace AWS/S3 --start-time {} --end-time {} --statistics Average --unit Bytes --region {} --dimensions Name=BucketName,Value={} Name=StorageType,Value=StandardStorage --period 86400 --output json"
for bucket in s3.buckets.all():
region = s3_client.get_bucket_location(Bucket=bucket.name)
region_name = region['LocationConstraint']
start_date = datetime.now() - timedelta(days=7)
start_date_str = str(start_date.date()) + 'T00:00:00Z'
end_date = datetime.now()
end_date_str = str(end_date.date()) + 'T00:00:00Z'
cmd = command.format(start_date_str, end_date_str, region_name, bucket.name)
res = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
bucket_stats = json.loads(res.decode('ascii'))
if len(bucket_stats['Datapoints']) > 0:
print(bucket_stats['Datapoints'])