brokkr-agent::diagnostics
Rust
Diagnostics handler for on-demand diagnostic collection.
This module provides functionality to collect detailed diagnostic information about Kubernetes resources, including pod statuses, events, and log tails.
Structs
Section titled “Structs”struct DiagnosticRequest
Section titled “struct DiagnosticRequest”pub
Derives: Debug, Clone, Serialize, Deserialize
Diagnostic request received from the broker.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
id |
Uuid |
Unique identifier for the diagnostic request. |
agent_id |
Uuid |
The agent that should handle this request. |
deployment_object_id |
Uuid |
The deployment object to gather diagnostics for. |
status |
String |
Status: pending, claimed, completed, failed, expired. |
requested_by |
Option<String> |
Who requested the diagnostics. |
created_at |
DateTime<Utc> |
When the request was created. |
claimed_at |
Option<DateTime<Utc>> |
When the agent claimed the request. |
completed_at |
Option<DateTime<Utc>> |
When the request was completed. |
expires_at |
DateTime<Utc> |
When the request expires. |
struct SubmitDiagnosticResult
Section titled “struct SubmitDiagnosticResult”pub
Derives: Debug, Clone, Serialize, Deserialize
Result to submit back to the broker.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
pod_statuses |
String |
JSON-encoded pod statuses. |
events |
String |
JSON-encoded Kubernetes events. |
log_tails |
Option<String> |
JSON-encoded log tails (optional). |
collected_at |
DateTime<Utc> |
When the diagnostics were collected. |
struct PodStatus
Section titled “struct PodStatus”pub
Derives: Debug, Clone, Serialize, Deserialize
Pod status information for diagnostics.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
name |
String |
Pod name. |
namespace |
String |
Pod namespace. |
phase |
String |
Pod phase (Pending, Running, Succeeded, Failed, Unknown). |
conditions |
Vec<PodCondition> |
Pod conditions. |
containers |
Vec<ContainerStatus> |
Container statuses. |
struct PodCondition
Section titled “struct PodCondition”pub
Derives: Debug, Clone, Serialize, Deserialize
Pod condition information.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
condition_type |
String |
Condition type. |
status |
String |
Condition status (True, False, Unknown). |
reason |
Option<String> |
Reason for the condition. |
message |
Option<String> |
Human-readable message. |
struct ContainerStatus
Section titled “struct ContainerStatus”pub
Derives: Debug, Clone, Serialize, Deserialize
Container status information.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
name |
String |
Container name. |
ready |
bool |
Whether the container is ready. |
restart_count |
i32 |
Number of restarts. |
state |
String |
Current state of the container. |
state_reason |
Option<String> |
Reason for current state. |
state_message |
Option<String> |
Message for current state. |
struct EventInfo
Section titled “struct EventInfo”pub
Derives: Debug, Clone, Serialize, Deserialize
Kubernetes event information.
Fields
Section titled “Fields”| Name | Type | Description |
|---|---|---|
event_type |
Option<String> |
Event type (Normal, Warning). |
reason |
Option<String> |
Event reason. |
message |
Option<String> |
Event message. |
involved_object |
String |
Name of the object the event refers to, or "unknown" when the source event carries no name. |
involved_object_kind |
Option<String> |
Kind of the object the event refers to (Pod, ReplicaSet, …). None when the source event omits it. Without this a bare name is ambiguous — several kinds in a namespace routinely share one. |
first_timestamp |
Option<DateTime<Utc>> |
First timestamp. |
last_timestamp |
Option<DateTime<Utc>> |
Last timestamp. |
count |
Option<i32> |
Event count. |
struct DiagnosticsHandler
Section titled “struct DiagnosticsHandler”pub
Diagnostics handler for collecting Kubernetes diagnostics.
Methods
Section titled “Methods”pub
fn new(client: Client) -> SelfCreates a new DiagnosticsHandler.
Source
pub fn new(client: Client) -> Self { Self { client } }collect_diagnostics
Section titled “collect_diagnostics”pub async
async fn collect_diagnostics( &self, namespace: &str, deployment_object_id: Uuid,) -> Result<SubmitDiagnosticResult, Box<dyn std::error::Error + Send + Sync>>Collects diagnostics for one deployment object within a single namespace.
Parameters:
| Name | Type | Description |
|---|---|---|
namespace |
&str |
The Kubernetes namespace |
deployment_object_id |
Uuid |
The deployment object to attribute pods to |
Returns:
A SubmitDiagnosticResult containing collected diagnostics
Source
pub async fn collect_diagnostics( &self, namespace: &str, deployment_object_id: Uuid, ) -> Result<SubmitDiagnosticResult, Box<dyn std::error::Error + Send + Sync>> { self.collect_diagnostics_in(&[namespace.to_string()], deployment_object_id) .await }collect_diagnostics_in
Section titled “collect_diagnostics_in”pub async
async fn collect_diagnostics_in( &self, namespaces: &[String], deployment_object_id: Uuid,) -> Result<SubmitDiagnosticResult, Box<dyn std::error::Error + Send + Sync>>Collects diagnostics across multiple namespaces and merges the results.
Namespaces are derived from the deployment object’s manifests so
diagnostics work for workloads outside default (BROKKR-T-0190).
Pods are attributed to deployment_object_id with the shared
PodAttributor strategy rather than a label selector: Brokkr stamps
brokkr.io/deployment-object-id as an annotation on the top-level
applied object and never injects it into pod templates, so selecting
pods by that label matched nothing for controller-managed workloads
(BROKKR-T-0299).
Parameters:
| Name | Type | Description |
|---|---|---|
namespaces |
&[String] |
The Kubernetes namespaces to search |
deployment_object_id |
Uuid |
The deployment object to attribute pods to |
Returns:
A SubmitDiagnosticResult containing the merged diagnostics
Source
pub async fn collect_diagnostics_in( &self, namespaces: &[String], deployment_object_id: Uuid, ) -> Result<SubmitDiagnosticResult, Box<dyn std::error::Error + Send + Sync>> { info!( "Collecting diagnostics for namespaces={:?}, deployment_object={}", namespaces, deployment_object_id );
let mut pod_statuses = Vec::new(); let mut events = Vec::new(); let mut log_tails: HashMap<String, String> = HashMap::new();
// One attributor for the whole request so API discovery and // owner-chain lookups are shared across namespaces. let mut attributor = PodAttributor::new(self.client.clone());
for namespace in namespaces { let pods = self .resolve_pods(&mut attributor, namespace, deployment_object_id) .await?; pod_statuses.extend(pods.iter().map(pod_status_of)); events.extend(self.collect_events(namespace).await?); log_tails.extend(self.collect_log_tails(namespace, &pods).await); }
Ok(SubmitDiagnosticResult { pod_statuses: serde_json::to_string(&pod_statuses)?, events: serde_json::to_string(&events)?, // With no namespace to search, `{}` would claim "looked, found no // containers"; `null` correctly says logs were never collected. log_tails: if namespaces.is_empty() { None } else { Some(serde_json::to_string(&log_tails)?) }, collected_at: Utc::now(), }) }