use crate::OwnedTags;
use crate::aggregator::Encoder;
use duration_str::deserialize_duration;
use metricus::PreAllocatedMetric;
use serde::{Deserialize, Serialize};
use serde_with::serde_as;
use std::collections::HashMap;
use std::net::{SocketAddr, ToSocketAddrs};
use std::path::Path;
use std::str::FromStr;
use std::time::Duration;
use std::vec;
#[serde_as]
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct MetricsConfig {
#[serde(deserialize_with = "deserialize_duration")]
#[serde(default = "get_default_flush_interval")]
pub flush_interval: Duration,
#[serde_as(as = "HashMap<_, _>")]
#[serde(default)]
pub default_tags: OwnedTags,
#[serde(default = "get_default_event_channel_size")]
pub event_channel_size: usize,
#[serde(default)]
pub exporter: ExporterSource,
#[serde(default)]
pub pre_allocated_metrics: Vec<PreAllocatedMetric>,
#[serde(default)]
pub aggregator_affinity_cpu_id: Option<usize>,
#[serde(default)]
pub aggregator_affinity_cpu_index: Option<usize>,
}
impl MetricsConfig {
pub fn from_file(path: impl AsRef<Path>) -> std::io::Result<MetricsConfig> {
serde_yaml::from_reader(std::fs::File::open(path)?).map_err(std::io::Error::other)
}
pub fn with_default_tags(self, default_tags: OwnedTags) -> MetricsConfig {
MetricsConfig {
default_tags: [self.default_tags, default_tags].concat(),
..self
}
}
pub fn with_pre_allocated_metrics<F>(self, pre_allocated_metrics: F) -> MetricsConfig
where
F: FnOnce() -> Vec<PreAllocatedMetric>,
{
MetricsConfig {
pre_allocated_metrics: [self.pre_allocated_metrics, pre_allocated_metrics()].concat(),
..self
}
}
}
impl FromStr for MetricsConfig {
type Err = std::io::Error;
fn from_str(config: &str) -> Result<Self, Self::Err> {
serde_yaml::from_str(config).map_err(std::io::Error::other)
}
}
const fn get_default_event_channel_size() -> usize {
1024 * 1024
}
const fn get_default_flush_interval() -> Duration {
Duration::from_secs(10)
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "snake_case")]
pub enum Format {
LineProtocol,
Json,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
#[serde(rename_all = "snake_case")]
#[serde(tag = "type", content = "config")]
pub enum ExporterSource {
#[default]
NoOp,
Udp(UdpConfig),
File(FileConfig),
UnixStream(UnixSocketConfig),
UnixDatagram(UnixSocketConfig),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UdpConfig {
pub host: String,
pub port: u16,
pub encoder: Encoder,
}
impl ToSocketAddrs for UdpConfig {
type Iter = vec::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
format!("{}:{}", self.host, self.port).to_socket_addrs()
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FileConfig {
pub path: String,
pub encoder: Encoder,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct UnixSocketConfig {
pub path: String,
pub encoder: Encoder,
}