Track commands spawned and subscriptions alive in beacon

This commit is contained in:
Héctor Ramón Jiménez 2024-05-13 13:21:10 +02:00
parent e770804435
commit b8adfc9ffe
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
8 changed files with 131 additions and 35 deletions

View file

@ -43,6 +43,9 @@ pub enum Event {
ThemeChanged(theme::Palette), ThemeChanged(theme::Palette),
SpanStarted(span::Stage), SpanStarted(span::Stage),
SpanFinished(span::Stage, Duration), SpanFinished(span::Stage, Duration),
MessageLogged(String),
CommandsSpawned(usize),
SubscriptionsTracked(usize),
} }
impl Client { impl Client {

View file

@ -30,6 +30,10 @@ pub enum Event {
at: SystemTime, at: SystemTime,
palette: theme::Palette, palette: theme::Palette,
}, },
SubscriptionsTracked {
at: SystemTime,
amount_alive: usize,
},
SpanFinished { SpanFinished {
at: SystemTime, at: SystemTime,
duration: Duration, duration: Duration,
@ -49,6 +53,7 @@ impl Event {
Self::Connected { at, .. } Self::Connected { at, .. }
| Self::Disconnected { at, .. } | Self::Disconnected { at, .. }
| Self::ThemeChanged { at, .. } | Self::ThemeChanged { at, .. }
| Self::SubscriptionsTracked { at, .. }
| Self::SpanFinished { at, .. } | Self::SpanFinished { at, .. }
| Self::QuitRequested { at } | Self::QuitRequested { at }
| Self::AlreadyRunning { at } => *at, | Self::AlreadyRunning { at } => *at,
@ -87,6 +92,9 @@ pub fn run() -> impl Stream<Item = Event> {
let _ = stream.set_nodelay(true); let _ = stream.set_nodelay(true);
let mut last_message = String::new();
let mut last_commands_spawned = 0;
loop { loop {
match receive(&mut stream, &mut buffer).await { match receive(&mut stream, &mut buffer).await {
Ok(message) => { Ok(message) => {
@ -114,6 +122,30 @@ pub fn run() -> impl Stream<Item = Event> {
}) })
.await; .await;
} }
client::Event::SubscriptionsTracked(
amount_alive,
) => {
let _ = output
.send(Event::SubscriptionsTracked {
at,
amount_alive,
})
.await;
}
client::Event::MessageLogged(message) => {
last_message = message;
}
client::Event::CommandsSpawned(
commands,
) => {
last_commands_spawned = commands;
}
client::Event::SpanStarted(
span::Stage::Update,
) => {
last_message.clear();
last_commands_spawned = 0;
}
client::Event::SpanStarted(_) => {} client::Event::SpanStarted(_) => {}
client::Event::SpanFinished( client::Event::SpanFinished(
stage, stage,
@ -121,7 +153,14 @@ pub fn run() -> impl Stream<Item = Event> {
) => { ) => {
let span = match stage { let span = match stage {
span::Stage::Boot => Span::Boot, span::Stage::Boot => Span::Boot,
span::Stage::Update => Span::Update, span::Stage::Update => {
Span::Update {
message: last_message
.clone(),
commands_spawned:
last_commands_spawned,
}
}
span::Stage::View(window) => { span::Stage::View(window) => {
Span::View { window } Span::View { window }
} }

View file

@ -5,20 +5,36 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Span { pub enum Span {
Boot, Boot,
Update, Update {
View { window: window::Id }, message: String,
Layout { window: window::Id }, commands_spawned: usize,
Interact { window: window::Id }, },
Draw { window: window::Id }, View {
Present { window: window::Id }, window: window::Id,
Custom { window: window::Id, name: String }, },
Layout {
window: window::Id,
},
Interact {
window: window::Id,
},
Draw {
window: window::Id,
},
Present {
window: window::Id,
},
Custom {
window: window::Id,
name: String,
},
} }
impl Span { impl Span {
pub fn stage(&self) -> Stage { pub fn stage(&self) -> Stage {
match self { match self {
Span::Boot => Stage::Boot, Span::Boot => Stage::Boot,
Span::Update => Stage::Update, Span::Update { .. } => Stage::Update,
Span::View { window } => Stage::View(*window), Span::View { window } => Stage::View(*window),
Span::Layout { window } => Stage::Layout(*window), Span::Layout { window } => Stage::Layout(*window),
Span::Interact { window } => Stage::Interact(*window), Span::Interact { window } => Stage::Interact(*window),

View file

@ -13,18 +13,24 @@ pub fn toggle_comet() {
internal::toggle_comet(); internal::toggle_comet();
} }
pub fn log_message(_message: &impl std::fmt::Debug) {}
pub fn theme_changed(f: impl FnOnce() -> Option<theme::Palette>) { pub fn theme_changed(f: impl FnOnce() -> Option<theme::Palette>) {
internal::theme_changed(f); internal::theme_changed(f);
} }
pub fn commands_spawned(amount: usize) {
internal::commands_spawned(amount)
}
pub fn subscriptions_tracked(amount: usize) {
internal::subscriptions_tracked(amount)
}
pub fn boot() -> Span { pub fn boot() -> Span {
internal::boot() internal::boot()
} }
pub fn update() -> Span { pub fn update(message: &impl std::fmt::Debug) -> Span {
internal::update() internal::update(message)
} }
pub fn view(window: window::Id) -> Span { pub fn view(window: window::Id) -> Span {
@ -107,12 +113,29 @@ mod internal {
} }
} }
pub fn commands_spawned(amount: usize) {
BEACON.log(client::Event::CommandsSpawned(amount));
}
pub fn subscriptions_tracked(amount: usize) {
BEACON.log(client::Event::SubscriptionsTracked(amount));
}
pub fn boot() -> Span { pub fn boot() -> Span {
span(span::Stage::Boot) span(span::Stage::Boot)
} }
pub fn update() -> Span { pub fn update(message: &impl std::fmt::Debug) -> Span {
span(span::Stage::Update) let span = span(span::Stage::Update);
let message = format!("{message:.30?}");
BEACON.log(client::Event::MessageLogged(if message.len() > 29 {
format!("{}...", &message[..29])
} else {
message
}));
span
} }
pub fn view(window: window::Id) -> Span { pub fn view(window: window::Id) -> Span {
@ -191,11 +214,15 @@ mod internal {
pub fn theme_changed(_f: impl FnOnce() -> Option<theme::Palette>) {} pub fn theme_changed(_f: impl FnOnce() -> Option<theme::Palette>) {}
pub fn commands_spawned(_amount: usize) {}
pub fn subscriptions_tracked(_amount: usize) {}
pub fn boot() -> Span { pub fn boot() -> Span {
Span Span
} }
pub fn update() -> Span { pub fn update(_message: &impl std::fmt::Debug) -> Span {
Span Span
} }

View file

@ -143,9 +143,7 @@ where
let commands = let commands =
Command::batch(messages.into_iter().map(|message| { Command::batch(messages.into_iter().map(|message| {
debug::log_message(&message); let update_span = debug::update(&message);
let update_span = debug::update();
let command = self.program.update(message); let command = self.program.update(message);
update_span.finish(); update_span.finish();

View file

@ -119,7 +119,9 @@ where
type Flags; type Flags;
/// Returns the unique name of the [`Application`]. /// Returns the unique name of the [`Application`].
fn name() -> &'static str; fn name() -> &'static str {
std::any::type_name::<Self>()
}
/// Initializes the [`Application`] with the flags provided to /// Initializes the [`Application`] with the flags provided to
/// [`run`] as part of the [`Settings`]. /// [`run`] as part of the [`Settings`].

View file

@ -557,7 +557,11 @@ async fn run_instance<A, E, C>(
&mut proxy, &mut proxy,
&window, &window,
); );
runtime.track(application.subscription().into_recipes());
let recipes = application.subscription().into_recipes();
debug::subscriptions_tracked(recipes.len());
runtime.track(recipes);
boot_span.finish(); boot_span.finish();
let mut user_interface = ManuallyDrop::new(build_user_interface( let mut user_interface = ManuallyDrop::new(build_user_interface(
@ -897,11 +901,8 @@ pub fn update<A: Application, C, E: Executor>(
A::Theme: DefaultStyle, A::Theme: DefaultStyle,
{ {
for message in messages.drain(..) { for message in messages.drain(..) {
debug::log_message(&message); let update_span = debug::update(&message);
let update_span = debug::update();
let command = runtime.enter(|| application.update(message)); let command = runtime.enter(|| application.update(message));
update_span.finish();
run_command( run_command(
application, application,
@ -917,12 +918,14 @@ pub fn update<A: Application, C, E: Executor>(
proxy, proxy,
window, window,
); );
update_span.finish();
} }
state.synchronize(application, window); state.synchronize(application, window);
let subscription = application.subscription(); let recipes = application.subscription().into_recipes();
runtime.track(subscription.into_recipes()); debug::subscriptions_tracked(recipes.len());
runtime.track(recipes);
} }
/// Runs the actions of a [`Command`]. /// Runs the actions of a [`Command`].
@ -949,7 +952,10 @@ pub fn run_command<A, C, E>(
use crate::runtime::system; use crate::runtime::system;
use crate::runtime::window; use crate::runtime::window;
for action in command.actions() { let actions = command.actions();
debug::commands_spawned(actions.len());
for action in actions {
match action { match action {
command::Action::Future(future) => { command::Action::Future(future) => {
runtime.spawn(future); runtime.spawn(future);

View file

@ -523,7 +523,10 @@ async fn run_instance<A, E, C>(
&mut ui_caches, &mut ui_caches,
); );
runtime.track(application.subscription().into_recipes()); let recipes = application.subscription().into_recipes();
debug::subscriptions_tracked(recipes.len());
runtime.track(recipes);
boot_span.finish(); boot_span.finish();
let mut messages = Vec::new(); let mut messages = Vec::new();
@ -987,9 +990,7 @@ fn update<A: Application, C, E: Executor>(
A::Theme: DefaultStyle, A::Theme: DefaultStyle,
{ {
for message in messages.drain(..) { for message in messages.drain(..) {
debug::log_message(&message); let update_span = debug::update(&message);
let update_span = debug::update();
let command = runtime.enter(|| application.update(message)); let command = runtime.enter(|| application.update(message));
update_span.finish(); update_span.finish();
@ -1006,8 +1007,9 @@ fn update<A: Application, C, E: Executor>(
); );
} }
let subscription = application.subscription(); let recipes = application.subscription().into_recipes();
runtime.track(subscription.into_recipes()); debug::subscriptions_tracked(recipes.len());
runtime.track(recipes);
} }
/// Runs the actions of a [`Command`]. /// Runs the actions of a [`Command`].
@ -1031,7 +1033,10 @@ fn run_command<A, C, E>(
use crate::runtime::system; use crate::runtime::system;
use crate::runtime::window; use crate::runtime::window;
for action in command.actions() { let actions = command.actions();
debug::commands_spawned(actions.len());
for action in actions {
match action { match action {
command::Action::Future(future) => { command::Action::Future(future) => {
runtime.spawn(Box::pin(future)); runtime.spawn(Box::pin(future));