use serde::{Deserialize, Serialize};
use crate::error::WyrdError;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, schemars::JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Resource {
pub service_name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub service_namespace: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub service_version: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub service_instance_id: Option<String>,
#[serde(default)]
pub attributes: serde_json::Map<String, serde_json::Value>,
}
impl Resource {
pub fn validate(&self) -> Result<(), WyrdError> {
if self.service_name.is_empty() {
return Err(WyrdError::Validation {
message:
"resource.service_name must be non-empty (OTel semconv: required attribute)"
.to_string(),
details: serde_json::Value::Null,
});
}
if self.service_name.len() > 256 {
return Err(WyrdError::Validation {
message: format!(
"resource.service_name length must be <= 256, got {}",
self.service_name.len()
),
details: serde_json::Value::Null,
});
}
for (field, value) in [
("service_namespace", &self.service_namespace),
("service_version", &self.service_version),
("service_instance_id", &self.service_instance_id),
] {
if let Some(v) = value
&& v.len() > 256
{
return Err(WyrdError::Validation {
message: format!("resource.{field} length must be <= 256, got {}", v.len()),
details: serde_json::Value::Null,
});
}
}
if self.attributes.len() > 256 {
return Err(WyrdError::Validation {
message: format!(
"resource.attributes count must be <= 256, got {}",
self.attributes.len()
),
details: serde_json::Value::Null,
});
}
Ok(())
}
}