use super::{
display::{Operational, write_list},
effect::PluginRuntimeTraceEffect,
proposal::PluginRuntimeTraceProposalReceipt,
workspace::{
PluginRuntimeTraceWorkspaceIoCompletion, PluginRuntimeTraceWorkspaceObserveTaskOutcome,
},
};
use crate::ecs::events::edit::PluginBufferEditProposalReceipt;
#[cfg(feature = "plugin-runtime")]
use crate::plugin::WasmtimeWorkspaceObserveTaskScheduleDiscardReport;
use crate::plugin::{
DrainedPluginEffectReport, PluginEffectDiscardReport, PluginHostImportDiscardReport,
PluginHostOwnerDiscardReport, PluginIdentity, PluginOperationalEvent,
PluginOperationalEventKind, PluginWorkspaceIoCancellationReport,
PluginWorkspaceIoDiscardReport, PluginWorkspaceIoReport,
PluginWorkspaceObserveTaskCancellationReport, PluginWorkspaceObserveTaskCompletion,
PluginWorkspaceObserveTaskCompletionShape, PluginWorkspaceObserveTaskDiscardReport,
};
use std::fmt::{Display, Formatter};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PluginRuntimeTraceEvent {
identity: Option<PluginIdentity>,
kind: PluginRuntimeTraceEventKind,
}
impl PluginRuntimeTraceEvent {
#[must_use]
pub fn drained_effects(report: &DrainedPluginEffectReport) -> Self {
Self::scoped(
report.identity_proof().clone(),
PluginRuntimeTraceEventKind::EffectsDrained {
effects: report
.buffer_edits()
.iter()
.map(PluginRuntimeTraceEffect::from)
.chain(
report
.status_messages()
.iter()
.map(PluginRuntimeTraceEffect::from),
)
.collect(),
},
)
}
#[must_use]
pub fn update_discarded(report: &PluginHostImportDiscardReport) -> Self {
Self::discarded_update_work(
report.effects().identity_proof().clone(),
report.effects().discarded_effects(),
report.workspace_io().discarded_requests(),
report.workspace_observe_tasks().discarded_tasks(),
)
}
#[must_use]
pub fn owner_work_discarded(report: &PluginHostOwnerDiscardReport) -> Self {
Self::discarded_update_work(
report.identity_proof().clone(),
report.effects().discarded_effects(),
report.workspace_io().discarded_requests(),
0,
)
}
#[must_use]
pub fn effects_discarded(report: &PluginEffectDiscardReport) -> Self {
Self::discarded_update_work(
report.identity_proof().clone(),
report.discarded_effects(),
0,
0,
)
}
#[must_use]
pub fn workspace_io_discarded(report: &PluginWorkspaceIoDiscardReport) -> Self {
Self::discarded_update_work(
report.identity_proof().clone(),
0,
report.discarded_requests(),
0,
)
}
#[must_use]
pub fn workspace_observe_tasks_discarded(
report: &PluginWorkspaceObserveTaskDiscardReport,
) -> Self {
Self::discarded_update_work(
report.identity_proof().clone(),
0,
0,
report.discarded_tasks(),
)
}
#[cfg(feature = "plugin-runtime")]
#[must_use]
pub fn workspace_observe_task_schedule_discarded(
report: &WasmtimeWorkspaceObserveTaskScheduleDiscardReport,
) -> Self {
Self::discarded_update_work(
report.identity_proof().clone(),
report.owner_work().effects().discarded_effects(),
report.owner_work().workspace_io().discarded_requests(),
report.workspace_observe_tasks().discarded_tasks(),
)
}
#[must_use]
pub fn workspace_io_completed(report: &PluginWorkspaceIoReport) -> Self {
Self::scoped(
report.identity_proof().clone(),
PluginRuntimeTraceEventKind::WorkspaceIoCompleted {
completions: report
.completions()
.iter()
.map(PluginRuntimeTraceWorkspaceIoCompletion::from)
.collect(),
},
)
}
#[must_use]
pub fn workspace_io_canceled(report: &PluginWorkspaceIoCancellationReport) -> Self {
Self::scoped(
report.identity_proof().clone(),
PluginRuntimeTraceEventKind::WorkspaceIoCanceled {
canceled_batches: report.canceled_batches(),
canceled_requests: report.canceled_requests(),
},
)
}
#[must_use]
pub fn workspace_observe_task_completed(
completion: &PluginWorkspaceObserveTaskCompletion,
) -> Self {
let shape = completion.shape();
Self::scoped(
shape.identity_proof().clone(),
PluginRuntimeTraceEventKind::WorkspaceObserveTaskCompleted { completion: shape },
)
}
#[must_use]
pub fn workspace_observe_tasks_canceled(
report: &PluginWorkspaceObserveTaskCancellationReport,
) -> Self {
Self::scoped(
report.identity_proof().clone(),
PluginRuntimeTraceEventKind::WorkspaceObserveTasksCanceled {
canceled_pending: report.canceled_pending(),
discarded_retained: report.discarded_retained(),
},
)
}
#[must_use]
pub fn operational(event: &PluginOperationalEvent) -> Self {
Self {
identity: event.identity_proof().cloned(),
kind: PluginRuntimeTraceEventKind::Operational { kind: event.kind() },
}
}
#[must_use]
pub fn proposal_receipt(receipt: &PluginBufferEditProposalReceipt) -> Self {
Self::scoped(
receipt.source_identity_proof().clone(),
PluginRuntimeTraceEventKind::ProposalReceipt {
receipt: PluginRuntimeTraceProposalReceipt::from(receipt),
},
)
}
#[must_use]
pub fn identity(&self) -> Option<&str> {
self.identity_proof().map(PluginIdentity::as_str)
}
#[must_use]
pub const fn identity_proof(&self) -> Option<&PluginIdentity> {
self.identity.as_ref()
}
#[must_use]
pub const fn kind(&self) -> &PluginRuntimeTraceEventKind {
&self.kind
}
#[must_use]
pub const fn class(&self) -> PluginRuntimeTraceEventClass {
self.kind.class()
}
const fn scoped(identity: PluginIdentity, kind: PluginRuntimeTraceEventKind) -> Self {
Self {
identity: Some(identity),
kind,
}
}
const fn discarded_update_work(
identity: PluginIdentity,
discarded_effects: usize,
discarded_workspace_requests: usize,
discarded_workspace_observe_tasks: usize,
) -> Self {
Self::scoped(
identity,
PluginRuntimeTraceEventKind::UpdateDiscarded {
discarded_effects,
discarded_workspace_requests,
discarded_workspace_observe_tasks,
},
)
}
}
impl Display for PluginRuntimeTraceEvent {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
match self.identity() {
Some(identity) => write!(formatter, "plugin {identity:?} trace {}", self.kind),
None => write!(formatter, "plugin trace {}", self.kind),
}
}
}
impl From<&DrainedPluginEffectReport> for PluginRuntimeTraceEvent {
fn from(report: &DrainedPluginEffectReport) -> Self {
Self::drained_effects(report)
}
}
impl From<&PluginHostImportDiscardReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginHostImportDiscardReport) -> Self {
Self::update_discarded(report)
}
}
impl From<&PluginHostOwnerDiscardReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginHostOwnerDiscardReport) -> Self {
Self::owner_work_discarded(report)
}
}
impl From<&PluginEffectDiscardReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginEffectDiscardReport) -> Self {
Self::effects_discarded(report)
}
}
impl From<&PluginWorkspaceIoDiscardReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginWorkspaceIoDiscardReport) -> Self {
Self::workspace_io_discarded(report)
}
}
impl From<&PluginWorkspaceObserveTaskDiscardReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginWorkspaceObserveTaskDiscardReport) -> Self {
Self::workspace_observe_tasks_discarded(report)
}
}
#[cfg(feature = "plugin-runtime")]
impl From<&WasmtimeWorkspaceObserveTaskScheduleDiscardReport> for PluginRuntimeTraceEvent {
fn from(report: &WasmtimeWorkspaceObserveTaskScheduleDiscardReport) -> Self {
Self::workspace_observe_task_schedule_discarded(report)
}
}
impl From<&PluginWorkspaceIoReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginWorkspaceIoReport) -> Self {
Self::workspace_io_completed(report)
}
}
impl From<&PluginWorkspaceIoCancellationReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginWorkspaceIoCancellationReport) -> Self {
Self::workspace_io_canceled(report)
}
}
impl From<&PluginWorkspaceObserveTaskCompletion> for PluginRuntimeTraceEvent {
fn from(completion: &PluginWorkspaceObserveTaskCompletion) -> Self {
Self::workspace_observe_task_completed(completion)
}
}
impl From<&PluginWorkspaceObserveTaskCancellationReport> for PluginRuntimeTraceEvent {
fn from(report: &PluginWorkspaceObserveTaskCancellationReport) -> Self {
Self::workspace_observe_tasks_canceled(report)
}
}
impl From<&PluginOperationalEvent> for PluginRuntimeTraceEvent {
fn from(event: &PluginOperationalEvent) -> Self {
Self::operational(event)
}
}
impl From<&PluginBufferEditProposalReceipt> for PluginRuntimeTraceEvent {
fn from(receipt: &PluginBufferEditProposalReceipt) -> Self {
Self::proposal_receipt(receipt)
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PluginRuntimeTraceEventClass {
EffectsDrained,
UpdateDiscarded,
WorkspaceIoCompleted,
WorkspaceIoCanceled,
WorkspaceObserveTaskCompleted,
WorkspaceObserveTasksCanceled,
Operational,
ProposalReceipt,
}
impl PluginRuntimeTraceEventClass {
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::EffectsDrained => "effects-drained",
Self::UpdateDiscarded => "update-discarded",
Self::WorkspaceIoCompleted => "workspace-io-completed",
Self::WorkspaceIoCanceled => "workspace-io-canceled",
Self::WorkspaceObserveTaskCompleted => "workspace-observe-task-completed",
Self::WorkspaceObserveTasksCanceled => "workspace-observe-tasks-canceled",
Self::Operational => "operational",
Self::ProposalReceipt => "proposal-receipt",
}
}
}
impl Display for PluginRuntimeTraceEventClass {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
formatter.write_str(self.as_str())
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum PluginRuntimeTraceEventKind {
EffectsDrained {
effects: Vec<PluginRuntimeTraceEffect>,
},
UpdateDiscarded {
discarded_effects: usize,
discarded_workspace_requests: usize,
discarded_workspace_observe_tasks: usize,
},
WorkspaceIoCompleted {
completions: Vec<PluginRuntimeTraceWorkspaceIoCompletion>,
},
WorkspaceIoCanceled {
canceled_batches: usize,
canceled_requests: usize,
},
WorkspaceObserveTaskCompleted {
completion: PluginWorkspaceObserveTaskCompletionShape,
},
WorkspaceObserveTasksCanceled {
canceled_pending: usize,
discarded_retained: usize,
},
Operational {
kind: PluginOperationalEventKind,
},
ProposalReceipt {
receipt: PluginRuntimeTraceProposalReceipt,
},
}
impl PluginRuntimeTraceEventKind {
#[must_use]
pub const fn class(&self) -> PluginRuntimeTraceEventClass {
match self {
Self::EffectsDrained { .. } => PluginRuntimeTraceEventClass::EffectsDrained,
Self::UpdateDiscarded { .. } => PluginRuntimeTraceEventClass::UpdateDiscarded,
Self::WorkspaceIoCompleted { .. } => PluginRuntimeTraceEventClass::WorkspaceIoCompleted,
Self::WorkspaceIoCanceled { .. } => PluginRuntimeTraceEventClass::WorkspaceIoCanceled,
Self::WorkspaceObserveTaskCompleted { .. } => {
PluginRuntimeTraceEventClass::WorkspaceObserveTaskCompleted
}
Self::WorkspaceObserveTasksCanceled { .. } => {
PluginRuntimeTraceEventClass::WorkspaceObserveTasksCanceled
}
Self::Operational { .. } => PluginRuntimeTraceEventClass::Operational,
Self::ProposalReceipt { .. } => PluginRuntimeTraceEventClass::ProposalReceipt,
}
}
}
impl Display for PluginRuntimeTraceEventKind {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::EffectsDrained { effects } => {
write!(formatter, "effects-drained effects=[")?;
write_list(formatter, effects)?;
formatter.write_str("]")
}
Self::UpdateDiscarded {
discarded_effects,
discarded_workspace_requests,
discarded_workspace_observe_tasks,
} => write!(
formatter,
"update-discarded effects={discarded_effects} workspace_io={discarded_workspace_requests} workspace_observe_tasks={discarded_workspace_observe_tasks}"
),
Self::WorkspaceIoCompleted { completions } => {
write!(formatter, "workspace-io-completed completions=[")?;
write_list(formatter, completions)?;
formatter.write_str("]")
}
Self::WorkspaceIoCanceled {
canceled_batches,
canceled_requests,
} => write!(
formatter,
"workspace-io-canceled batches={canceled_batches} requests={canceled_requests}"
),
Self::WorkspaceObserveTaskCompleted { completion } => {
let task_id = completion.task_id();
let outcome =
PluginRuntimeTraceWorkspaceObserveTaskOutcome::from(completion.outcome_shape());
write!(
formatter,
"workspace-observe-task-completed task_id={task_id} outcome={outcome}"
)
}
Self::WorkspaceObserveTasksCanceled {
canceled_pending,
discarded_retained,
} => write!(
formatter,
"workspace-observe-tasks-canceled pending={canceled_pending} retained={discarded_retained}"
),
Self::Operational { kind } => write!(formatter, "operational {}", Operational(kind)),
Self::ProposalReceipt { receipt } => write!(formatter, "proposal-receipt {receipt}"),
}
}
}