use alloy_deploy_profile::api as deploy_profile_api;
use alloy_service_core::api as service_core_api;
use alloy_telemetry::api as telemetry_api;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceReport {
pub service_scope: &'static str,
pub deploy_scope: &'static str,
pub telemetry_scope: &'static str,
pub service_name: &'static str,
pub runtime_mode: &'static str,
pub support_band: &'static str,
pub profile_id: &'static str,
pub schema_id: &'static str,
pub listen_address: String,
pub liveness_path: &'static str,
pub readiness_path: &'static str,
pub admin_status_path: &'static str,
pub health_component: String,
pub health_readiness: &'static str,
pub health_liveness: &'static str,
pub lifecycle_verbs: Vec<&'static str>,
pub required_env: Vec<&'static str>,
pub required_evidence_artifacts: Vec<&'static str>,
pub admin_routes: Vec<ServiceAdminRoute>,
pub graceful_shutdown: ServiceShutdownReport,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceAdminRoute {
pub path: &'static str,
pub purpose: &'static str,
pub operator_only: bool,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ServiceShutdownReport {
pub signal: &'static str,
pub timeout_seconds: u64,
pub drain_in_flight_requests: bool,
}
impl ServiceReport {
pub fn to_json_pretty(&self) -> String {
let lifecycle_verbs = self
.lifecycle_verbs
.iter()
.map(|verb| format!("\"{}\"", verb))
.collect::<Vec<_>>()
.join(", ");
let required_env = self
.required_env
.iter()
.map(|key| format!("\"{}\"", key))
.collect::<Vec<_>>()
.join(", ");
let required_evidence_artifacts = self
.required_evidence_artifacts
.iter()
.map(|artifact| format!("\"{}\"", artifact))
.collect::<Vec<_>>()
.join(", ");
let admin_routes = self
.admin_routes
.iter()
.map(|route| {
format!(
concat!(
" {{\n",
" \"path\": \"{}\",\n",
" \"purpose\": \"{}\",\n",
" \"operator_only\": {}\n",
" }}"
),
route.path, route.purpose, route.operator_only
)
})
.collect::<Vec<_>>()
.join(",\n");
format!(
concat!(
"{{\n",
" \"service_scope\": \"{}\",\n",
" \"deploy_scope\": \"{}\",\n",
" \"telemetry_scope\": \"{}\",\n",
" \"service_name\": \"{}\",\n",
" \"runtime_mode\": \"{}\",\n",
" \"support_band\": \"{}\",\n",
" \"profile_id\": \"{}\",\n",
" \"schema_id\": \"{}\",\n",
" \"listen_address\": \"{}\",\n",
" \"paths\": {{\n",
" \"liveness\": \"{}\",\n",
" \"readiness\": \"{}\",\n",
" \"admin_status\": \"{}\"\n",
" }},\n",
" \"health\": {{\n",
" \"component\": \"{}\",\n",
" \"readiness\": \"{}\",\n",
" \"liveness\": \"{}\"\n",
" }},\n",
" \"lifecycle_verbs\": [{}],\n",
" \"required_env\": [{}],\n",
" \"required_evidence_artifacts\": [{}],\n",
" \"admin_routes\": [\n{}\n",
" ],\n",
" \"graceful_shutdown\": {{\n",
" \"signal\": \"{}\",\n",
" \"timeout_seconds\": {},\n",
" \"drain_in_flight_requests\": {}\n",
" }}\n",
"}}\n"
),
self.service_scope,
self.deploy_scope,
self.telemetry_scope,
self.service_name,
self.runtime_mode,
self.support_band,
self.profile_id,
self.schema_id,
self.listen_address,
self.liveness_path,
self.readiness_path,
self.admin_status_path,
self.health_component,
self.health_readiness,
self.health_liveness,
lifecycle_verbs,
required_env,
required_evidence_artifacts,
admin_routes,
self.graceful_shutdown.signal,
self.graceful_shutdown.timeout_seconds,
self.graceful_shutdown.drain_in_flight_requests,
)
}
}
pub fn service_report(
listen_address: Option<&str>,
checked_at_epoch_seconds: u64,
) -> ServiceReport {
let descriptor = service_core_api::ServiceDescriptor::new(
"iridium-service-candidate",
service_core_api::RuntimeMode::ServiceTarget,
service_core_api::ServicePaths::new("/livez", "/readyz", "/admin/status"),
);
let config = service_core_api::ConfigSchema::new(
"iridium.service.v0_1",
"v0.1",
&["listen_address", "data_dir", "telemetry_endpoint"],
&[("listen_address", "127.0.0.1:7001"), ("data_dir", "./data")],
&["storage.data_dir", "telemetry.endpoint", "tls.mode"],
);
let bootstrap = service_core_api::ServiceBootstrap::new(
descriptor,
config,
listen_address.unwrap_or("127.0.0.1:7001"),
30,
);
let profile = deploy_profile_api::service_candidate_profile();
let health = telemetry_api::HealthSnapshot {
component: "iridium-service-candidate",
readiness: telemetry_api::HealthState::Ready,
liveness: telemetry_api::HealthState::Live,
degradation_reason: None,
checked_at_epoch_seconds,
};
let admin_routes = [
service_core_api::AdminRoute::new("/admin/status", "service status", true),
service_core_api::AdminRoute::new("/admin/lifecycle", "lifecycle control", true),
];
let shutdown = service_core_api::GracefulShutdown::new("SIGTERM", 30, true);
ServiceReport {
service_scope: service_core_api::scope(),
deploy_scope: deploy_profile_api::scope(),
telemetry_scope: telemetry_api::scope(),
service_name: descriptor.name,
runtime_mode: match descriptor.mode {
service_core_api::RuntimeMode::EmbeddedEvaluator => "embedded-evaluator",
service_core_api::RuntimeMode::ServiceTarget => "service-target",
},
support_band: profile.support_band.as_str(),
profile_id: profile.profile_id,
schema_id: config.schema_id,
listen_address: bootstrap.listen_address.to_string(),
liveness_path: descriptor.paths.liveness,
readiness_path: descriptor.paths.readiness,
admin_status_path: descriptor.paths.admin_status,
health_component: health.component.to_string(),
health_readiness: match health.readiness {
telemetry_api::HealthState::Ready => "ready",
telemetry_api::HealthState::Live => "live",
telemetry_api::HealthState::NotReady => "not-ready",
},
health_liveness: match health.liveness {
telemetry_api::HealthState::Ready => "ready",
telemetry_api::HealthState::Live => "live",
telemetry_api::HealthState::NotReady => "not-ready",
},
lifecycle_verbs: service_core_api::default_lifecycle_verbs()
.iter()
.map(|verb| verb.as_str())
.collect(),
required_env: profile.required_env.to_vec(),
required_evidence_artifacts: profile.required_evidence_artifacts.to_vec(),
admin_routes: admin_routes
.iter()
.map(|route| ServiceAdminRoute {
path: route.path,
purpose: route.purpose,
operator_only: route.operator_only,
})
.collect(),
graceful_shutdown: ServiceShutdownReport {
signal: shutdown.signal,
timeout_seconds: shutdown.timeout_seconds,
drain_in_flight_requests: shutdown.drain_in_flight_requests,
},
}
}