添加 DataFrame/DataPoint 对象¶
CloudKitty 拥有一个内部数据格式,称为“DataFrame”。它几乎无处不在:API 返回数据帧,存储驱动程序期望存储数据帧,收集的数据以数据帧的形式检索……但数据帧总是作为字典传递,这使得它们的处理变得繁琐。 这项提案旨在添加 DataFrame 和 DataPoint 类定义,这将允许更轻松地转换/操作数据帧。
https://storyboard.openstack.org/#!/story/2005890
问题描述¶
“dataframe” 格式在多个地方都有说明,但实际上并没有真正的实现:而是传递符合格式规范的字典。这可能容易出错:这些对象的完整性无法保证(即使无意中,函数也可能修改它们),并且一些特定细节可能因代码库的不同部分而异(例如,可以使用 float 代替 decimal.Decimal)。
此外,dataframe 格式在 v1 和 v2 存储接口中并不完全相同。v1 具有一个 desc 键,其中包含数据点的所有元数据属性,而 v2 提供两个键,metadata 和 groupby,具体取决于属性的类型。 这导致代码中多个地方需要进行 v1 和 v2 格式之间的转换。 示例摘自 CloudKittyFormatTransformer
def format_item(self, groupby, metadata, unit, qty=1.0):
data = {}
data['groupby'] = groupby
data['metadata'] = metadata
# For backward compatibility.
data['desc'] = data['groupby'].copy()
data['desc'].update(data['metadata'])
data['vol'] = {'unit': unit, 'qty': qty}
return data
提议的变更¶
建议的解决方案是引入两个新类:DataPoint 和 DataFrame。
DataPoint¶
DataPoint 替换了由以下格式的字典表示的单个数据点
{
"vol": {
"unit": "GiB",
"qty": 1.2,
},
"rating": {
"price": 0.04,
},
"groupby": {
"group_one": "one",
"group_two": "two",
},
"metadata": {
"attr_one": "one",
"attr_two": "two",
},
}
以下属性将在 DataPoint 对象中可访问
qty:decimal.Decimalprice:decimal.Decimalgroupby:werkzeug.datastructures.ImmutableMultiDictmetadata:werkzeug.datastructures.ImmutableMultiDictdesc:werkzeug.datastructures.ImmutableMultiDict
注意
desc 将是 metadata 和 groupby 的组合
为了确保数据一致性,DataPoint 对象将继承 collections.namedtuple。 groupby 和 metadata 属性将存储为 werkzeug.datastructures.ImmutableDict。
除了基本属性外,DataPoint 类还将具有一个 desc 属性(作为属性实现),它将返回一个 ImmutableDict(metadata 和 groupby 的合并)。
DataPoint 实例将公开以下方法
set_price: 设置DataPoint的价格。返回一个新实例。as_dict: 返回对象的(可选可变的)字典表示形式。为了与 API 向后兼容,可以获得以传统格式表示的结果(desc将替换metadata和groupby)。json: 返回对象的 json 表示形式。为了与 API 向后兼容,可以获得以传统格式表示的结果(desc将替换metadata和groupby)。from_dict: 从其字典表示形式创建DataPoint。
DataFrame¶
DataFrame 替换了由以下格式的字典表示的数据帧
{
"period": {
"begin": datetime.datetime,
"end": datetime.datetime,
},
"usage": {
"metric_one": [], # list of datapoints
[...]
}
}
一个 DataFrame 是对 DataPoint 对象集合的包装。 DataFrame 实例将具有两个只读属性:start 和 end(存储为 datetime.datetime 对象)。
DataFrame 实例将公开以下方法
as_dict: 返回对象的(可选可变的)字典表示形式。为了与 API 向后兼容,可以获得以传统格式表示的结果。json: 返回对象的 json 表示形式。为了与 API 向后兼容,可以获得以传统格式表示的结果。from_dict: 从其字典表示形式创建DataFrame。add_points: 将DataPoint对象列表添加到给定指标的数据帧中。iterpoints: 生成器函数,迭代DataFrame中的所有点。产生 (metric_name,DataPoint) 元组。
注意
鉴于两个类的 from_dict 方法主要将在 API 级别使用,将添加与类匹配的 voluptuous 模式,并在调用 from_dict 时执行模式验证。
备选方案¶
代码库可以保持不变,让开发人员处理繁琐的数据帧操作。
数据模型影响¶
内部操作的数据结构得到加固。
REST API 影响¶
无。但是,这将简化未来允许将数据帧推送到 cloudkitty 的端点。
安全影响¶
无。
通知影响¶
无。
其他最终用户影响¶
无。
性能影响¶
实例化 DataPoints 可能比实例化字典稍慢。但是,namedtuple 是一个高性能容器,如果我们使用 namedtuple 子类,将跳过当前执行的几个字典格式化步骤,因此可能根本没有开销。
其他部署者影响¶
无。
开发人员影响¶
使用具有清晰且严格接口的对象应该使使用数据帧更容易且更不易出错。
不需要额外的依赖项。
实现¶
负责人¶
主要负责人
peschk_l
工作项¶
创建将允许检查数据点/数据帧格式的验证工具。
提交带有测试的新类。
依赖项¶
无。
测试¶
这将使用单元测试进行测试。预计 100% 的测试覆盖率。
文档影响¶
无。
参考资料¶
无。