From 3f4d3e6d036145caee7d629aebea738c8833f127 Mon Sep 17 00:00:00 2001 From: Jocelyn Boullier Date: Tue, 16 Apr 2024 21:22:39 +0200 Subject: [PATCH 1/4] feat(common): add new line for the logger --- common/src/lib.rs | 2 ++ common/src/log.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/common/src/lib.rs b/common/src/lib.rs index 1cfd71381..a4b429266 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -14,6 +14,8 @@ pub mod limits; pub mod log; #[cfg(feature = "service")] pub use log::LogItem; +#[cfg(feature = "service")] +pub use log::LogItemBeta; #[cfg(feature = "models")] pub mod models; pub mod resource; diff --git a/common/src/log.rs b/common/src/log.rs index 98ffa6f7a..15ed841c6 100644 --- a/common/src/log.rs +++ b/common/src/log.rs @@ -47,6 +47,48 @@ pub struct LogItem { pub line: String, } +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct LogItemBeta { + pub id: String, + + /// Time log was captured + pub timestamp: DateTime, + + /// Stdout/stderr + pub source: String, + + /// The log line + pub line: String, +} + +impl LogItemBeta { + pub fn new(id: String, timestamp: DateTime, source: String, line: String) -> Self { + Self { + id, + timestamp, + source, + line, + } + } +} + +#[cfg(feature = "display")] +impl std::fmt::Display for LogItemBeta { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let datetime: chrono::DateTime = DateTime::from(self.timestamp); + + write!( + f, + "{} [{}] {}", + datetime + .to_rfc3339_opts(chrono::SecondsFormat::Millis, false) + .dim(), + self.source, + self.line, + ) + } +} + const LOGLINE_MAX_CHARS: usize = 2048; const TRUNC_MSG: &str = "... (truncated)"; From 4ebb804a346114aacfa5fee1cad392fd8d8e6c00 Mon Sep 17 00:00:00 2001 From: Jocelyn Boullier Date: Wed, 17 Apr 2024 14:15:07 +0200 Subject: [PATCH 2/4] feat(cargo): add support for logs of new platform --- cargo-shuttle/src/lib.rs | 47 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index 94d1cd6d2..512448d3e 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -136,7 +136,6 @@ impl Shuttle { | Command::Stop | Command::Clean | Command::Status - | Command::Logs { .. } ) { unimplemented!("This command is not yet implemented on the beta platform"); } @@ -218,7 +217,13 @@ impl Shuttle { Command::Run(run_args) => self.local_run(run_args).await, Command::Deploy(deploy_args) => self.deploy(deploy_args).await, Command::Status => self.status().await, - Command::Logs(logs_args) => self.logs(logs_args).await, + Command::Logs(logs_args) => { + if self.beta { + self.logs_beta(logs_args).await + } else { + self.logs(logs_args).await + } + } Command::Deployment(DeploymentCommand::List { page, limit, raw }) => { if self.beta { unimplemented!(); @@ -838,6 +843,44 @@ impl Shuttle { Ok(CommandOutcome::Ok) } + async fn logs_beta(&self, args: LogsArgs) -> Result { + let client = self.client.as_ref().unwrap(); + let mut stream = client + // TODO: use something else than a fake Uuid + .get_logs_ws(self.ctx.project_name(), &Uuid::new_v4()) + .await + .map_err(|err| { + suggestions::logs::get_logs_failure(err, "Connecting to the logs stream failed") + })?; + + while let Some(Ok(msg)) = stream.next().await { + if let tokio_tungstenite::tungstenite::Message::Text(line) = msg { + match serde_json::from_str::(&line) { + Ok(log) => { + if args.raw { + println!("{}", log.line); + } else { + println!("[{}] ({}) {}", log.timestamp, log.source, log.line); + } + } + Err(err) => { + debug!(error = %err, "failed to parse message into log item"); + + let message = if let Ok(err) = serde_json::from_str::(&line) { + err.to_string() + } else { + "failed to parse logs, is your cargo-shuttle outdated?".to_string() + }; + + bail!(message); + } + } + } + } + + Ok(CommandOutcome::Ok) + } + async fn logs(&self, args: LogsArgs) -> Result { let client = self.client.as_ref().unwrap(); let id = if let Some(id) = args.id { From 5efddddc3891e5dbd133ccf7a4f96f6ab145f47d Mon Sep 17 00:00:00 2001 From: Jocelyn Boullier Date: Wed, 17 Apr 2024 15:45:27 +0200 Subject: [PATCH 3/4] fix(cargo): remove useless error handling --- cargo-shuttle/src/lib.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cargo-shuttle/src/lib.rs b/cargo-shuttle/src/lib.rs index 512448d3e..c25a89f24 100644 --- a/cargo-shuttle/src/lib.rs +++ b/cargo-shuttle/src/lib.rs @@ -864,15 +864,9 @@ impl Shuttle { } } Err(err) => { - debug!(error = %err, "failed to parse message into log item"); - - let message = if let Ok(err) = serde_json::from_str::(&line) { - err.to_string() - } else { - "failed to parse logs, is your cargo-shuttle outdated?".to_string() - }; - - bail!(message); + // TODO better handle logs, by returning a different type than the log line + // if an error happened. + bail!(err); } } } From 9ffc75f272de11c577ce2c3b20a218d04325051f Mon Sep 17 00:00:00 2001 From: Jocelyn Boullier Date: Wed, 17 Apr 2024 15:47:38 +0200 Subject: [PATCH 4/4] fix(cargo): remove id from LogItemBeta --- common/src/log.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/common/src/log.rs b/common/src/log.rs index 15ed841c6..89b68c935 100644 --- a/common/src/log.rs +++ b/common/src/log.rs @@ -49,8 +49,6 @@ pub struct LogItem { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct LogItemBeta { - pub id: String, - /// Time log was captured pub timestamp: DateTime, @@ -62,9 +60,8 @@ pub struct LogItemBeta { } impl LogItemBeta { - pub fn new(id: String, timestamp: DateTime, source: String, line: String) -> Self { + pub fn new(timestamp: DateTime, source: String, line: String) -> Self { Self { - id, timestamp, source, line,