13个版本
0.2.5 | 2024年5月11日 |
---|---|
0.2.4 | 2023年9月8日 |
0.2.3 | 2023年6月22日 |
0.2.2 | 2023年3月20日 |
0.1.4 | 2020年7月16日 |
#310 在 编码
51,820 每月下载量
用于 2 crates
78KB
2K SLoC
Serde Prometheus
一个用于Prometheus文本展示格式的serde实现。
lib.rs
:
一个用于Prometheus文本展示格式的serde实现。
目前这个库只支持将指标序列化为Prometheus格式,但以后可能会扩展到反序列化。
serde_prometheus
将与大多数度量库的struct结构无缝工作,但是可能需要对它们进行一些处理才能达到Prometheus期望的格式。
格式中暴露的度量名称是从包含它的struct或map中的值的名称派生出来的。
基本用法
#[derive(Serialize)]
struct HitCount(u64);
#[derive(Serialize)]
struct MetricRegistry {
my_struct: MyStructMetrics
}
#[derive(Serialize)]
struct MyStructMetrics {
hit_count: HitCount
}
let metrics = MetricRegistry {
my_struct: MyStructMetrics {
hit_count: HitCount(30)
}
};
assert_eq!(
serde_prometheus::to_string(&metrics, None, HashMap::new())?,
"hit_count{path = \"my_struct\"} 30\n"
);
全局标签
可以使用HashMap
(或任何可以解析为IntoIterator<Borrow<(&str, &str)>>
)将全局标签添加到serde_prometheus
导出的所有指标中,例如通过传递到serde_prometheus::to_string
#
#
#
let mut labels = HashMap::new();
labels.insert("my_key", "my_value");
let serialised = serde_prometheus::to_string(&metrics, None, &[("my_key", "my_value")])?;
assert_eq!(serialised, "hit_count{my_key = \"my_value\", path = \"my_struct\"} 30\n");
全局前缀
还可以添加全局前缀到所有指标
#
#
#
assert_eq!(
serde_prometheus::to_string(&metrics, Some("my_prefix"), HashMap::new())?,
"my_prefix_hit_count{path = \"my_struct\"} 30\n"
);
元数据和键操作
serde_prometheus
通过使用Serde的newtype实现来添加元数据到序列化字段,而不会破坏与serde_json
等的向后兼容性。
keymodifiers|key=value,key2=value2
也可以在标签中使用修饰符,例如这样使用==
|key3==modifiers
对于每个标签值,都会重置path
堆栈,然而在写入path
标签本身时,应用了键修饰符后,它会保留。
可以使用的修饰符有
修饰符 | 描述 |
---|---|
< | 从path 堆栈中弹出一个值并将其附加到名称上 |
! | 从path 堆栈中弹出的最后一个值并将其丢弃 |
- | 将堆栈光标向后移动一个位置,当从堆栈中弹出一个值时,位置会重置回堆栈顶部 |
. | serde_prometheus 0.1 的默认行为是将收集到的堆栈附加到path 中的下一个值(就像在修饰符中添加了一个额外的< ),要防止这种情况,请使用此修饰符。在标签中此操作无效果。 |
这些修饰符可以组合使用,并且从左到右读取,例如
#
#
#
struct HitCount(u64);
impl Serialize for HitCount {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
// metric name: include our key (hit_count), ignore the second (my_method), and include the third (my_struct)
// metric meta: for the method_name, ignore our key (hit_count), include the second (my_method)
serializer.serialize_newtype_struct("<!<|my_key=my_value,method_name==!<", &self.0)
}
}
let metrics = MetricRegistry {
my_struct: MyStructMetrics {
my_method: MyMethodMetrics {
hit_count: HitCount(30)
}
}
};
let serialised = serde_prometheus::to_string(&metrics, None, HashMap::new())?;
assert_eq!(
serialised,
// would be `hit_count{path = "my_struct/my_method"}` without the Serialize impl
"my_struct_hit_count{my_key = \"my_value\", method_name = \"my_method\"} 30\n"
);
内部覆盖
serialize_newtype_struct
支持一个额外的部分,允许覆盖内部操作,如下所示
keymodifiers|key=value,key2=value2|:internal=abc
内部覆盖始终以:
开头,以使其明显不是标签,以下是可以使用的内部覆盖列表
覆盖 | 描述 |
---|---|
:namespace | 用新的值覆盖该结构及其下任何叶子的全局命名空间 |
标签连接
默认情况下,通过serialize_newtype_struct
调用添加的新标签,将覆盖堆栈上更高位置的先前设置的标签。可以通过在标签名称中附加[::]
来覆盖“更深”的值,这将使用::
连接先前设置的标签和新的标签。::
可以是Prometheus标签值中的任何有效值,但不能是=
。
fn add_my_cool_key<S: serde::Serializer, T: serde::Serialize>(
value: &T,
serializer: S,
) -> Result<S::Ok, S::Error> {
serializer.serialize_newtype_struct("!|my_cool_key[::]==<", value)
}
#[derive(Serialize)]
struct MetricRegistry {
#[serde(serialize_with = "add_my_cool_key")]
my_struct: MyStructMetrics
}
#[derive(Serialize)]
struct MyStructMetrics {
#[serde(serialize_with = "add_my_cool_key")]
my_method: MyMethodMetrics
}
#[derive(Serialize)]
struct MyMethodMetrics {
hit_count: HitCount
}
#
let metrics = MetricRegistry {
my_struct: MyStructMetrics {
my_method: MyMethodMetrics {
hit_count: HitCount(30)
}
}
};
let serialised = serde_prometheus::to_string(&metrics, None, HashMap::new())?;
assert_eq!(
serialised,
"hit_count{my_cool_key = \"my_struct::my_method\"} 30\n"
);
依赖
~2.1–3MB
~62K SLoC