Skip to content

Commit

Permalink
Add tracing support
Browse files Browse the repository at this point in the history
  • Loading branch information
matthunz committed Jan 8, 2024
1 parent 9f611ab commit 1f969ea
Show file tree
Hide file tree
Showing 15 changed files with 271 additions and 22 deletions.
98 changes: 98 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions Cargo.toml
Expand Up @@ -14,10 +14,22 @@ members = [
]

[features]
full = []
web = ["web-sys"]
full = ["web", "tracing"]

[dependencies]
web-sys = { version = "0.3.66", features = ["Document", "Event", "HtmlElement", "Window", "Text"] }
tracing = { version = "0.1.40", optional = true }

[dependencies.web-sys]
version = "0.3.66"
optional = true
features = [
"Document",
"Event",
"HtmlElement",
"Window",
"Text"
]

[package.metadata.docs.rs]
features = ["full"]
Expand Down
7 changes: 5 additions & 2 deletions README.md
Expand Up @@ -54,8 +54,11 @@ impl Model<Message> for App {
fn view(model: &App) -> impl View<Web, Message> {
(
format!("High five count: {}", model.count),
view::once(html::div(html::on_click(|| Message::Increment), "Up high!")),
view::once(html::div(
view::once(html::button(
html::on_click(|| Message::Increment),
"Up high!",
)),
view::once(html::button(
html::on_click(|| Message::Decrement),
"Down low!",
)),
Expand Down
18 changes: 18 additions & 0 deletions src/lib.rs
@@ -1,8 +1,20 @@
/// A high performance UI framework.
///
/// Viewbuilder is a moduler GUI library that can be used as an entire framework,
/// or with individual parts.
///
/// ## Features
/// - `full`: Enables all the features below.
/// - `tracing`: Enables structured logging and performance metrics with the `tracing` crate.
/// - `web`: Enables web support.

use std::sync::Arc;

pub mod view;
pub use self::view::View;

#[cfg(feature = "web")]
#[cfg_attr(docsrs, doc(cfg(feature = "web")))]
pub mod web;

pub struct Context<M> {
Expand All @@ -27,15 +39,21 @@ impl<M> Clone for Context<M> {
}
}

/// Control flow returned from [`Model::handle`].
pub enum ControlFlow {
/// This model is pending changes, do not rebuild the view.
Pending,

/// Rebuild the view with the updated model.
Rebuild,
}

/// Model for a view builder.
pub trait Model<M> {
fn handle(&mut self, msg: M) -> ControlFlow;
}

/// Runtime for a model and view builder.
pub struct Runtime<T, VB, E, M, S> {
model: T,
view_builder: VB,
Expand Down
8 changes: 8 additions & 0 deletions src/view/lazy.rs
Expand Up @@ -26,12 +26,20 @@ where
type Element = (u64, V::Element);

fn build(&mut self, cx: &mut crate::Context<M>, tree: &mut T) -> Self::Element {
let span = tracing::trace_span!("View::Build", view = "Lazy");
let _g = span.enter();

let element = self.view.build(cx, tree);
(self.hash, element)
}

fn rebuild(&mut self, cx: &mut crate::Context<M>, tree: &mut T, element: &mut Self::Element) {
let span = tracing::trace_span!("View::Rebuild", view = "Lazy");
let _g = span.enter();

if self.hash != element.0 {
tracing::trace!(name: "Hash change", new = self.hash, old = element.0);

element.0 = self.hash;
self.view.rebuild(cx, tree, &mut element.1);
}
Expand Down
6 changes: 6 additions & 0 deletions src/view/mod.rs
Expand Up @@ -66,10 +66,16 @@ macro_rules! impl_viewbuilder_for_tuple {
type Element = ($($t::Element),*);

fn build(&mut self, cx: &mut Context<M>, tree: &mut T) -> Self::Element {
let span = tracing::trace_span!("View::Build", view = stringify!(($($t),*)));
let _g = span.enter();

($(self.$idx.build(cx, tree)),*)
}

fn rebuild(&mut self, cx: &mut Context<M>, tree: &mut T, element: &mut Self::Element) {
let span = tracing::trace_span!("View::Rebuild", view = stringify!(($($t),*)));
let _g = span.enter();

$(self.$idx.rebuild(cx, tree, &mut element.$idx));*
}
}
Expand Down
8 changes: 7 additions & 1 deletion src/view/once.rs
Expand Up @@ -18,8 +18,14 @@ where
type Element = V::Element;

fn build(&mut self, cx: &mut Context<M>, tree: &mut T) -> Self::Element {
let span = tracing::trace_span!("View::Build", view = "Once");
let _g = span.enter();

self.view.build(cx, tree)
}

fn rebuild(&mut self, _cx: &mut Context<M>, _tree: &mut T, _element: &mut Self::Element) {}
fn rebuild(&mut self, _cx: &mut Context<M>, _tree: &mut T, _element: &mut Self::Element) {
let span = tracing::trace_span!("View::Rebuild", view = "Once");
let _g = span.enter();
}
}
9 changes: 9 additions & 0 deletions src/web/html.rs
@@ -1,6 +1,7 @@
use super::{HtmlAttributes, Web};
use crate::{Context, View};
use std::{fmt, marker::PhantomData, mem};
use tracing::{event, span, Level};
use web_sys::{
wasm_bindgen::{closure::Closure, JsCast},
Event,
Expand Down Expand Up @@ -61,6 +62,10 @@ where
type Element = (HtmlAttributes, A::Element);

fn build(&mut self, cx: &mut Context<M>, tree: &mut Web) -> Self::Element {
let span = span!(Level::TRACE, "HTML element", tag = self.tag.as_ref());
let _g = span.enter();
event!(Level::TRACE, "Build");

let element = tree.document.create_element(self.tag.as_ref()).unwrap();
tree.parent.append_child(&element).unwrap();

Expand All @@ -74,6 +79,10 @@ where
}

fn rebuild(&mut self, cx: &mut Context<M>, _tree: &mut Web, element: &mut Self::Element) {
let span = span!(Level::TRACE, "HTML element", tag = self.tag.as_ref());
let _g = span.enter();
event!(Level::TRACE, "Rebuild");

self.attrs.rebuild(cx, &mut element.0, &mut element.1)
}
}
Expand Down
17 changes: 16 additions & 1 deletion src/web/mod.rs
@@ -1,4 +1,4 @@
use crate::{Runtime, Context, ControlFlow, Model, View};
use crate::{Context, ControlFlow, Model, Runtime, View};
use std::{cell::RefCell, rc::Rc, sync::Arc};
use web_sys::{wasm_bindgen::JsCast, Document, Element, Text};

Expand Down Expand Up @@ -55,12 +55,19 @@ impl<M> View<Web, M> for &'static str {
type Element = (Self, Text);

fn build(&mut self, _cx: &mut Context<M>, tree: &mut Web) -> Self::Element {
let span = tracing::trace_span!("View::Build", view = "&'static str",);
let _g = span.enter();

let text = tree.document.create_text_node(self);
tree.parent.append_child(&text).unwrap();

(self, text)
}

fn rebuild(&mut self, _cx: &mut Context<M>, _tree: &mut Web, element: &mut Self::Element) {
let span = tracing::trace_span!("View::Rebuild", view = "&'static str",);
let _g = span.enter();

if *self != element.0 {
element.0 = self;
element.1.set_text_content(Some(self));
Expand All @@ -72,13 +79,21 @@ impl<M> View<Web, M> for String {
type Element = (Self, Text);

fn build(&mut self, _cx: &mut Context<M>, tree: &mut Web) -> Self::Element {
let span = tracing::trace_span!("View::Build", view = "String");
let _g = span.enter();

let text = tree.document.create_text_node(self);
tree.parent.append_child(&text).unwrap();
(self.clone(), text)
}

fn rebuild(&mut self, _cx: &mut Context<M>, _tree: &mut Web, element: &mut Self::Element) {
let span = tracing::trace_span!("View::Rebuild", view = "String");
let _g = span.enter();

if *self != element.0 {
tracing::event!(name: "Text change", tracing::Level::TRACE, new = &*self, old = element.0);

element.0 = self.clone();
element.1.set_text_content(Some(self));
}
Expand Down
7 changes: 4 additions & 3 deletions web_examples/counter/Cargo.toml
Expand Up @@ -3,7 +3,8 @@ name = "viewbuilder-counter-example"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
viewbuilder = { path = "../../" }
viewbuilder = { path = "../../", features = ["full"] }
console_error_panic_hook = "0.1.7"
tracing-wasm = { version = "0.2.1" }
tracing = "0.1.40"
4 changes: 2 additions & 2 deletions web_examples/counter/dist/index.html
@@ -1,6 +1,6 @@
<html><head>
<link rel="preload" href="/viewbuilder-counter-example-1826d9f52d63647e_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/viewbuilder-counter-example-1826d9f52d63647e.js"></head><body><script type="module">import init from '/viewbuilder-counter-example-1826d9f52d63647e.js';init('/viewbuilder-counter-example-1826d9f52d63647e_bg.wasm');</script><script>(function () {
<link rel="preload" href="/viewbuilder-counter-example-325a295824e217cb_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/viewbuilder-counter-example-325a295824e217cb.js"></head><body><script type="module">import init from '/viewbuilder-counter-example-325a295824e217cb.js';init('/viewbuilder-counter-example-325a295824e217cb_bg.wasm');</script><script>(function () {
var protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
var url = protocol + '//' + window.location.host + '/_trunk/ws';
var poll_interval = 5000;
Expand Down
Binary file not shown.

0 comments on commit 1f969ea

Please sign in to comment.