Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tracing (port from #8289) #8607

Merged
merged 33 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a501364
feat(tracing): add IPC tracing
lucasfernog-crabnebula Sep 14, 2023
bb51e21
span for deserialization
lucasfernog-crabnebula Sep 14, 2023
fa6ddb1
trace spans for IPC command handlers
lucasfernog-crabnebula Sep 14, 2023
7f35866
fix spans usage
lucasfernog-crabnebula Sep 16, 2023
38cb9a9
app tracing [skip ci]
lucasfernog-crabnebula Sep 17, 2023
cceba2f
window tracing
lucasfernog-crabnebula Sep 17, 2023
df4ab38
fix run never resolving all spans
lucasfernog-crabnebula Sep 17, 2023
932218a
fix draw not entered
lucasfernog-crabnebula Sep 17, 2023
8e1fc85
change level
lucasfernog-crabnebula Sep 17, 2023
76da8a4
feat(core): Manager::emit_filter and optimize serialization (#7512)
lucasfernog-crabnebula Sep 18, 2023
30358be
event spans
lucasfernog-crabnebula Sep 18, 2023
74df6cc
lint & fix tests
lucasfernog-crabnebula Sep 18, 2023
f4fd461
change eval to run sync
lucasfernog-crabnebula Sep 19, 2023
5a156b7
fix instrument
lucasfernog-crabnebula Sep 19, 2023
5d71410
update wry
lucasfernog-crabnebula Sep 19, 2023
9747abc
change separator
lucasfernog-crabnebula Sep 19, 2023
87b642d
Update core/tauri/src/plugin.rs
lucasfernog-crabnebula Sep 20, 2023
f472303
Update core/tauri/src/window.rs
lucasfernog-crabnebula Sep 20, 2023
c48ac3d
Update core/tauri/src/window.rs
lucasfernog-crabnebula Sep 20, 2023
02fb8b4
Update core/tauri/src/window.rs
lucasfernog-crabnebula Sep 20, 2023
d0afef0
Update core/tauri/src/window.rs
lucasfernog-crabnebula Sep 20, 2023
53ed93b
instrument separators
lucasfernog-crabnebula Sep 20, 2023
ae8ed67
remove on_event trace
lucasfernog-crabnebula Oct 25, 2023
33af069
skip all arguments on App::build tracing
lucasfernog-crabnebula Nov 13, 2023
85429ae
Merge remote-tracking branch 'upstream/dev' into feat/core-tracing
lucasfernog-crabnebula Dec 19, 2023
8aaa3ef
ipc spans adjustments
lucasfernog-crabnebula Dec 20, 2023
551aab8
merge from dev
lucasfernog-crabnebula Dec 20, 2023
1264693
delete change file
lucasfernog-crabnebula Dec 20, 2023
4e90f60
improve how request and response are added as values (serialize)
lucasfernog-crabnebula Dec 21, 2023
f7d2faa
do not run evalScript sync on android :( freezes the app
lucasfernog-crabnebula Dec 21, 2023
2a717bf
wry 0.35.2
lucasfernog-crabnebula Jan 2, 2024
ff58f81
add change file
lucasfernog-crabnebula Jan 15, 2024
5620489
Merge branch 'dev' into feat/core-tracing
lucasfernog-crabnebula Jan 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changes/tracing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"tauri": patch:enhance
"tauri-runtime-wry": patch:enhance
"tauri-macros": patch:enhance
---

Added tracing for window startup, plugins, `Window::eval`, events, IPC, updater and custom protocol request handlers behind the `tracing` feature flag.
4 changes: 2 additions & 2 deletions core/tauri-runtime-wry/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ edition = { workspace = true }
rust-version = { workspace = true }

[dependencies]
wry = { version = "0.35", default-features = false, features = [ "file-drop", "protocol", "os-webview" ] }
wry = { version = "0.35.2", default-features = false, features = [ "file-drop", "protocol", "os-webview" ] }
tao = { version = "0.24", default-features = false, features = [ "rwh_05" ] }
tauri-runtime = { version = "1.0.0-alpha.7", path = "../tauri-runtime" }
tauri-utils = { version = "2.0.0-alpha.12", path = "../tauri-utils" }
Expand Down Expand Up @@ -48,4 +48,4 @@ macos-private-api = [
]
objc-exception = [ "wry/objc-exception" ]
linux-protocol-body = [ "wry/linux-body", "webkit2gtk/v2_40" ]
tracing = [ "dep:tracing" ]
tracing = [ "dep:tracing", "wry/tracing" ]
12 changes: 6 additions & 6 deletions core/tauri-runtime-wry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,9 +1070,9 @@ pub enum WindowMessage {

#[derive(Debug, Clone)]
pub enum WebviewMessage {
#[cfg(not(feature = "tracing"))]
#[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
EvaluateScript(String),
#[cfg(feature = "tracing")]
#[cfg(all(feature = "tracing", not(target_os = "android")))]
EvaluateScript(String, Sender<()>, tracing::Span),
#[allow(dead_code)]
WebviewEvent(WebviewEvent),
Expand Down Expand Up @@ -1583,7 +1583,7 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
)
}

#[cfg(feature = "tracing")]
#[cfg(all(feature = "tracing", not(target_os = "android")))]
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
// use a channel so the EvaluateScript task uses the current span as parent
let (tx, rx) = channel();
Expand All @@ -1597,7 +1597,7 @@ impl<T: UserEvent> Dispatch<T> for WryDispatcher<T> {
)
}

#[cfg(not(feature = "tracing"))]
#[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
fn eval_script<S: Into<String>>(&self, script: S) -> Result<()> {
send_user_message(
&self.context,
Expand Down Expand Up @@ -2429,7 +2429,7 @@ fn handle_user_message<T: UserEvent>(
}
}
Message::Webview(id, webview_message) => match webview_message {
#[cfg(feature = "tracing")]
#[cfg(all(feature = "tracing", not(target_os = "android")))]
WebviewMessage::EvaluateScript(script, tx, span) => {
let _span = span.entered();
if let Some(WindowHandle::Webview { inner: webview, .. }) =
Expand All @@ -2441,7 +2441,7 @@ fn handle_user_message<T: UserEvent>(
}
tx.send(()).unwrap();
}
#[cfg(not(feature = "tracing"))]
#[cfg(not(all(feature = "tracing", not(target_os = "android"))))]
WebviewMessage::EvaluateScript(script) => {
if let Some(WindowHandle::Webview { inner: webview, .. }) =
windows.borrow().get(&id).and_then(|w| w.inner.as_ref())
Expand Down
5 changes: 5 additions & 0 deletions core/tauri/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,10 @@ shared_app_impl!(App<R>);
shared_app_impl!(AppHandle<R>);

impl<R: Runtime> App<R> {
#[cfg_attr(
feature = "tracing",
tracing::instrument(name = "app::core_plugins::register")
)]
fn register_core_plugins(&self) -> crate::Result<()> {
self.handle.plugin(crate::path::plugin::init())?;
self.handle.plugin(crate::event::plugin::init())?;
Expand Down Expand Up @@ -1663,6 +1667,7 @@ unsafe impl<R: Runtime> HasRawDisplayHandle for App<R> {
}
}

#[cfg_attr(feature = "tracing", tracing::instrument(name = "app::setup"))]
fn setup<R: Runtime>(app: &mut App<R>) -> crate::Result<()> {
let pending_windows = app.pending_windows.take();
if let Some(pending_windows) = pending_windows {
Expand Down
13 changes: 13 additions & 0 deletions core/tauri/src/ipc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,19 @@ pub enum InvokeResponse {
Err(InvokeError),
}

impl Serialize for InvokeResponse {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
Self::Ok(InvokeBody::Json(j)) => j.serialize(serializer),
Self::Ok(InvokeBody::Raw(b)) => b.serialize(serializer),
Self::Err(e) => e.0.serialize(serializer),
}
}
}

impl<T: IpcResponse, E: Into<InvokeError>> From<Result<T, E>> for InvokeResponse {
#[inline]
fn from(result: Result<T, E>) -> Self {
Expand Down
113 changes: 98 additions & 15 deletions core/tauri/src/ipc/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@

use std::{borrow::Cow, sync::Arc};

use http::{
header::{ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE},
HeaderValue, Method, StatusCode,
};

use crate::{
manager::AppManager,
window::{InvokeRequest, UriSchemeProtocolHandler},
Runtime,
};
use http::{
header::{ACCESS_CONTROL_ALLOW_HEADERS, ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE},
HeaderValue, Method, StatusCode,
};

use super::{CallbackFn, InvokeBody, InvokeResponse};

Expand All @@ -29,6 +28,14 @@ pub fn message_handler<R: Runtime>(

pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeProtocolHandler {
Box::new(move |request, responder| {
#[cfg(feature = "tracing")]
let span = tracing::trace_span!(
"ipc::request",
kind = "custom-protocol",
request = tracing::field::Empty
)
.entered();

let manager = manager.clone();
let label = label.clone();

Expand All @@ -44,9 +51,35 @@ pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeP
if let Some(window) = manager.get_window(&label) {
match parse_invoke_request(&manager, request) {
Ok(request) => {
#[cfg(feature = "tracing")]
span.record(
"request",
match &request.body {
InvokeBody::Json(j) => serde_json::to_string(j).unwrap(),
InvokeBody::Raw(b) => serde_json::to_string(b).unwrap(),
},
);
#[cfg(feature = "tracing")]
let request_span = tracing::trace_span!("ipc::request::handle", cmd = request.cmd);

window.on_message(
request,
Box::new(move |_window, _cmd, response, _callback, _error| {
#[cfg(feature = "tracing")]
let _respond_span = tracing::trace_span!(
parent: &request_span,
"ipc::request::respond"
)
.entered();

#[cfg(feature = "tracing")]
let response_span = tracing::trace_span!(
"ipc::request::response",
response = serde_json::to_string(&response).unwrap(),
mime_type = tracing::field::Empty
)
.entered();

let (mut response, mime_type) = match response {
InvokeResponse::Ok(InvokeBody::Json(v)) => (
http::Response::new(serde_json::to_vec(&v).unwrap().into()),
Expand All @@ -64,6 +97,9 @@ pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeP
}
};

#[cfg(feature = "tracing")]
response_span.record("mime_type", mime_type.essence_str());

response.headers_mut().insert(
CONTENT_TYPE,
HeaderValue::from_str(mime_type.essence_str()).unwrap(),
Expand Down Expand Up @@ -129,6 +165,10 @@ pub fn get<R: Runtime>(manager: Arc<AppManager<R>>, label: String) -> UriSchemeP
#[cfg(any(target_os = "macos", target_os = "ios", not(ipc_custom_protocol)))]
fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, label: &str) {
if let Some(window) = manager.get_window(label) {
#[cfg(feature = "tracing")]
let _span =
tracing::trace_span!("ipc::request", kind = "post-message", request = message).entered();

use serde::{Deserialize, Deserializer};

pub(crate) struct HeaderMap(http::HeaderMap);
Expand Down Expand Up @@ -185,6 +225,9 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
}

if let crate::Pattern::Isolation { crypto_keys, .. } = &*manager.pattern {
#[cfg(feature = "tracing")]
let _span = tracing::trace_span!("ipc::request::decrypt_isolation_payload").entered();

invoke_message.replace(
serde_json::from_str::<IsolationMessage<'_>>(&message)
.map_err(Into::into)
Expand All @@ -201,18 +244,25 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
}
}

match invoke_message
.unwrap_or_else(|| serde_json::from_str::<Message>(&message).map_err(Into::into))
{
match invoke_message.unwrap_or_else(|| {
#[cfg(feature = "tracing")]
let _span = tracing::trace_span!("ipc::request::deserialize").entered();
serde_json::from_str::<Message>(&message).map_err(Into::into)
}) {
Ok(message) => {
let request = InvokeRequest {
cmd: message.cmd,
callback: message.callback,
error: message.error,
body: message.payload.into(),
headers: message.options.map(|o| o.headers.0).unwrap_or_default(),
};

#[cfg(feature = "tracing")]
let request_span = tracing::trace_span!("ipc::request::handle", cmd = request.cmd);

window.on_message(
InvokeRequest {
cmd: message.cmd,
callback: message.callback,
error: message.error,
body: message.payload.into(),
headers: message.options.map(|o| o.headers.0).unwrap_or_default(),
},
request,
Box::new(move |window, cmd, response, callback, error| {
use crate::ipc::{
format_callback::{
Expand All @@ -222,6 +272,13 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
};
use serde_json::Value as JsonValue;

#[cfg(feature = "tracing")]
let _respond_span = tracing::trace_span!(
parent: &request_span,
"ipc::request::respond"
)
.entered();

// the channel data command is the only command that uses a custom protocol on Linux
if window.manager.window.invoke_responder.is_none()
&& cmd != crate::ipc::channel::FETCH_CHANNEL_DATA_COMMAND
Expand All @@ -240,6 +297,19 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
let _ = window.eval(&eval_js);
}

#[cfg(feature = "tracing")]
let _response_span = tracing::trace_span!(
"ipc::request::response",
response = serde_json::to_string(&response).unwrap(),
mime_type = match &response {
InvokeResponse::Ok(InvokeBody::Json(_)) => mime::APPLICATION_JSON,
InvokeResponse::Ok(InvokeBody::Raw(_)) => mime::APPLICATION_OCTET_STREAM,
InvokeResponse::Err(_) => mime::TEXT_PLAIN,
}
.essence_str()
)
.entered();

match &response {
InvokeResponse::Ok(InvokeBody::Json(v)) => {
if !(cfg!(target_os = "macos") || cfg!(target_os = "ios"))
Expand Down Expand Up @@ -277,6 +347,9 @@ fn handle_ipc_message<R: Runtime>(message: String, manager: &AppManager<R>, labe
);
}
Err(e) => {
#[cfg(feature = "tracing")]
tracing::trace!("ipc.request.error {}", e);

let _ = window.eval(&format!(
r#"console.error({})"#,
serde_json::Value::String(e.to_string())
Expand All @@ -301,6 +374,9 @@ fn parse_invoke_request<R: Runtime>(
// the body is not set if ipc_custom_protocol is not enabled so we'll just ignore it
#[cfg(all(feature = "isolation", ipc_custom_protocol))]
if let crate::Pattern::Isolation { crypto_keys, .. } = &*manager.pattern {
#[cfg(feature = "tracing")]
let _span = tracing::trace_span!("ipc::request::decrypt_isolation_payload").entered();

body = crate::utils::pattern::isolation::RawIsolationPayload::try_from(&body)
.and_then(|raw| crypto_keys.decrypt(raw))
.map_err(|e| e.to_string())?;
Expand Down Expand Up @@ -334,6 +410,10 @@ fn parse_invoke_request<R: Runtime>(
.map(|mime| mime.parse())
.unwrap_or(Ok(mime::APPLICATION_OCTET_STREAM))
.map_err(|_| "unknown content type")?;

#[cfg(feature = "tracing")]
let span = tracing::trace_span!("ipc::request::deserialize").entered();

let body = if content_type == mime::APPLICATION_OCTET_STREAM {
body.into()
} else if content_type == mime::APPLICATION_JSON {
Expand All @@ -349,6 +429,9 @@ fn parse_invoke_request<R: Runtime>(
return Err(format!("content type {content_type} is not implemented"));
};

#[cfg(feature = "tracing")]
drop(span);

let payload = InvokeRequest {
cmd,
callback,
Expand Down
6 changes: 6 additions & 0 deletions core/tauri/src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,9 @@ impl<R: Runtime> AppManager<R> {
{
assert_event_name_is_valid(event);

#[cfg(feature = "tracing")]
let _span = tracing::debug_span!("emit::run").entered();

let emit_args = EmitArgs::from(event, source_window_label, payload)?;

self
Expand All @@ -506,6 +509,9 @@ impl<R: Runtime> AppManager<R> {
) -> crate::Result<()> {
assert_event_name_is_valid(event);

#[cfg(feature = "tracing")]
let _span = tracing::debug_span!("emit::run").entered();

let emit_args = EmitArgs::from(event, source_window_label, payload)?;

self
Expand Down
3 changes: 3 additions & 0 deletions core/tauri/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,9 @@ impl<R: Runtime> PluginStore<R> {

pub(crate) fn on_navigation(&mut self, window: &Window<R>, url: &Url) -> bool {
for plugin in self.store.iter_mut() {
#[cfg(feature = "tracing")]
let _span =
tracing::trace_span!("plugin::hooks::on_navigation", name = plugin.name()).entered();
if !plugin.on_navigation(window, url) {
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions core/tauri/src/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2410,6 +2410,8 @@ impl<R: Runtime> Window<R> {
load_channels(&payload, &message.window);

let resolver_ = resolver.clone();
#[cfg(feature = "span")]
let _span = tracing::debug_span!("ipc::request::mobile_plugin").entered();
if let Err(e) = crate::plugin::mobile::run_command(
plugin,
&app_handle,
Expand Down
Loading