Skip to content

Commit 7ab8d11

Browse files
jonaro00chesedo
andauthored
feat(deployer): StateChangeLayer, DeploymentLogLayer, new log item structure (#1171)
* refactor(deployer): new log structure * WIP revert state tracking * mostly finish DeploymentIdLayer and StateChangeLayer * fix: comments Co-authored-by: Pieter <pieter@chesedo.me> * format log lines. LogItem::new. * deployment_id in spans, LogRecorder for Batcher * Convertions, log retrieval. * derive default * add matching for deployment log end states * fmt errors correctly --------- Co-authored-by: Pieter <pieter@chesedo.me>
1 parent bd5c9ff commit 7ab8d11

File tree

24 files changed

+670
-865
lines changed

24 files changed

+670
-865
lines changed

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,8 @@ up: $(DOCKER_COMPOSE_FILES)
204204
$(SHUTTLE_DETACH)
205205

206206
down: $(DOCKER_COMPOSE_FILES)
207-
$(DOCKER_COMPOSE_ENV) $(DOCKER_COMPOSE) $(addprefix -f ,$(DOCKER_COMPOSE_FILES)) -p $(STACK) down
207+
$(DOCKER_COMPOSE_ENV) \
208+
$(DOCKER_COMPOSE) \
209+
$(addprefix -f ,$(DOCKER_COMPOSE_FILES)) \
210+
-p $(STACK) \
211+
down

auth/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::io;
22

33
use clap::Parser;
4-
use shuttle_common::backends::tracing::setup_tracing;
4+
use shuttle_common::{backends::tracing::setup_tracing, log::Backend};
55
use sqlx::migrate::Migrator;
66
use tracing::{info, trace};
77

@@ -15,7 +15,7 @@ async fn main() -> io::Result<()> {
1515

1616
trace!(args = ?args, "parsed args");
1717

18-
setup_tracing(tracing_subscriber::registry(), "auth");
18+
setup_tracing(tracing_subscriber::registry(), Backend::Auth);
1919

2020
let db_path = args.state.join("authentication.sqlite");
2121

cargo-shuttle/src/lib.rs

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::process::exit;
1515
use std::str::FromStr;
1616

1717
use logger_server::LocalLogger;
18+
use shuttle_common::deployment::{DEPLOYER_END_MESSAGES_BAD, DEPLOYER_END_MESSAGES_GOOD};
1819
use shuttle_common::models::deployment::CREATE_SERVICE_BODY_LIMIT;
1920
use shuttle_common::{
2021
claims::{ClaimService, InjectPropagation},
@@ -1140,8 +1141,11 @@ impl Shuttle {
11401141
deployment_req.data = self.make_archive()?;
11411142
if deployment_req.data.len() > CREATE_SERVICE_BODY_LIMIT {
11421143
bail!(
1143-
"The project is too large - we have a {}MB project limit.",
1144-
CREATE_SERVICE_BODY_LIMIT / 1_000_000
1144+
r#"The project is too large - we have a {} MB project limit. \
1145+
Your project archive is {} MB. \
1146+
Run with `RUST_LOG="cargo_shuttle=debug"` to see which files are being packed."#,
1147+
CREATE_SERVICE_BODY_LIMIT / 1_000_000,
1148+
deployment_req.data.len() / 1_000_000,
11451149
);
11461150
}
11471151

@@ -1160,33 +1164,31 @@ impl Shuttle {
11601164
let log_item: shuttle_common::LogItem =
11611165
serde_json::from_str(&line).expect("to parse log line");
11621166

1163-
match log_item.state.clone() {
1164-
shuttle_common::deployment::State::Queued
1165-
| shuttle_common::deployment::State::Building
1166-
| shuttle_common::deployment::State::Built
1167-
| shuttle_common::deployment::State::Loading => {
1168-
println!("{log_item}");
1169-
}
1170-
shuttle_common::deployment::State::Crashed => {
1171-
println!();
1172-
println!("{}", "Deployment crashed".red());
1173-
println!();
1174-
println!("Run the following for more details");
1175-
println!();
1176-
print!("cargo shuttle logs {}", &deployment.id);
1177-
println!();
1178-
1179-
return Ok(CommandOutcome::DeploymentFailure);
1180-
}
1181-
// Break on remaining end states: Running, Stopped, Completed or Unknown.
1182-
end_state => {
1183-
debug!(state = %end_state, "received end state, breaking deployment stream");
1184-
break;
1185-
}
1186-
};
1167+
println!("{log_item}");
1168+
1169+
if DEPLOYER_END_MESSAGES_BAD
1170+
.iter()
1171+
.any(|m| log_item.line.contains(m))
1172+
{
1173+
println!();
1174+
println!("{}", "Deployment crashed".red());
1175+
println!();
1176+
println!("Run the following for more details");
1177+
println!();
1178+
println!("cargo shuttle logs {}", &deployment.id);
1179+
1180+
return Ok(CommandOutcome::DeploymentFailure);
1181+
}
1182+
if DEPLOYER_END_MESSAGES_GOOD
1183+
.iter()
1184+
.any(|m| log_item.line.contains(m))
1185+
{
1186+
debug!("received end message, breaking deployment stream");
1187+
break;
1188+
}
11871189
}
11881190
} else {
1189-
println!("Reconnecting websockets logging");
1191+
eprintln!("--- Reconnecting websockets logging ---");
11901192
// A wait time short enough for not much state to have changed, long enough that
11911193
// the terminal isn't completely spammed
11921194
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
@@ -1198,26 +1200,15 @@ impl Shuttle {
11981200

11991201
// Temporary fix.
12001202
// TODO: Make get_service_summary endpoint wait for a bit and see if it entered Running/Crashed state.
1203+
// Note: Will otherwise be possible when health checks are supported
12011204
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
12021205

12031206
let deployment = client
12041207
.get_deployment_details(self.ctx.project_name(), &deployment.id)
12051208
.await?;
12061209

12071210
// A deployment will only exist if there is currently one in the running state
1208-
if deployment.state == shuttle_common::deployment::State::Running {
1209-
let service = client.get_service(self.ctx.project_name()).await?;
1210-
1211-
let resources = client
1212-
.get_service_resources(self.ctx.project_name())
1213-
.await?;
1214-
1215-
let resources = get_resources_table(&resources, self.ctx.project_name().as_str());
1216-
1217-
println!("{resources}{service}");
1218-
1219-
Ok(CommandOutcome::Ok)
1220-
} else {
1211+
if deployment.state != shuttle_common::deployment::State::Running {
12211212
println!("{}", "Deployment has not entered the running state".red());
12221213
println!();
12231214

@@ -1251,8 +1242,18 @@ impl Shuttle {
12511242
println!("cargo shuttle logs {}", &deployment.id);
12521243
println!();
12531244

1254-
Ok(CommandOutcome::DeploymentFailure)
1245+
return Ok(CommandOutcome::DeploymentFailure);
12551246
}
1247+
1248+
let service = client.get_service(self.ctx.project_name()).await?;
1249+
let resources = client
1250+
.get_service_resources(self.ctx.project_name())
1251+
.await?;
1252+
let resources = get_resources_table(&resources, self.ctx.project_name().as_str());
1253+
1254+
println!("{resources}{service}");
1255+
1256+
Ok(CommandOutcome::Ok)
12561257
}
12571258

12581259
async fn project_create(&self, client: &Client, idle_minutes: u64) -> Result<()> {

common/src/backends/tracing.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ use tracing::{debug_span, instrument::Instrumented, Instrument, Span, Subscriber
2020
use tracing_opentelemetry::OpenTelemetrySpanExt;
2121
use tracing_subscriber::{fmt, prelude::*, registry::LookupSpan, EnvFilter};
2222

23+
use crate::log::Backend;
24+
2325
const OTLP_ADDRESS: &str = "http://otel-collector:4317";
2426

25-
pub fn setup_tracing<S>(subscriber: S, service_name: &str)
27+
pub fn setup_tracing<S>(subscriber: S, backend: Backend)
2628
where
2729
S: Subscriber + for<'a> LookupSpan<'a> + Send + Sync,
2830
{
@@ -46,7 +48,7 @@ where
4648
.with_trace_config(
4749
trace::config().with_resource(Resource::new(vec![KeyValue::new(
4850
"service.name",
49-
service_name.to_string(),
51+
backend.to_string(),
5052
)])),
5153
)
5254
.install_batch(Tokio)
@@ -196,15 +198,17 @@ pub fn serde_json_map_to_key_value_list(
196198
/// Convert an [AnyValue] to a [serde_json::Value]
197199
pub fn from_any_value_to_serde_json_value(any_value: AnyValue) -> serde_json::Value {
198200
let Some(value) = any_value.value else {
199-
return serde_json::Value::Null
201+
return serde_json::Value::Null;
200202
};
201203

202204
match value {
203205
any_value::Value::StringValue(s) => serde_json::Value::String(s),
204206
any_value::Value::BoolValue(b) => serde_json::Value::Bool(b),
205207
any_value::Value::IntValue(i) => serde_json::Value::Number(i.into()),
206208
any_value::Value::DoubleValue(f) => {
207-
let Some(number) = serde_json::Number::from_f64(f) else {return serde_json::Value::Null};
209+
let Some(number) = serde_json::Number::from_f64(f) else {
210+
return serde_json::Value::Null;
211+
};
208212
serde_json::Value::Number(number)
209213
}
210214
any_value::Value::ArrayValue(a) => {

common/src/deployment.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ pub enum Environment {
2828
Production,
2929
}
3030

31+
pub const DEPLOYER_END_MSG_STARTUP_ERR: &str = "Service startup encountered an error";
32+
pub const DEPLOYER_END_MSG_CRASHED: &str = "Service encountered an error and crashed";
33+
pub const DEPLOYER_END_MSG_STOPPED: &str = "Service was stopped by the user";
34+
pub const DEPLOYER_END_MSG_COMPLETED: &str = "Service finished running all on its own";
35+
36+
pub const DEPLOYER_END_MESSAGES_BAD: &[&str] =
37+
&[DEPLOYER_END_MSG_STARTUP_ERR, DEPLOYER_END_MSG_CRASHED];
38+
pub const DEPLOYER_END_MESSAGES_GOOD: &[&str] =
39+
&[DEPLOYER_END_MSG_STOPPED, DEPLOYER_END_MSG_COMPLETED];
40+
3141
#[cfg(test)]
3242
mod tests {
3343
use std::str::FromStr;

common/src/lib.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ pub mod database;
66
#[cfg(feature = "service")]
77
pub mod deployment;
88
#[cfg(feature = "service")]
9+
use uuid::Uuid;
10+
#[cfg(feature = "service")]
11+
pub type DeploymentId = Uuid;
12+
#[cfg(feature = "service")]
913
pub mod log;
14+
#[cfg(feature = "service")]
15+
pub use log::LogItem;
1016
#[cfg(feature = "models")]
1117
pub mod models;
1218
#[cfg(feature = "service")]
@@ -22,17 +28,11 @@ pub mod wasm;
2228
use std::collections::BTreeMap;
2329
use std::fmt::Debug;
2430
use std::fmt::Display;
25-
#[cfg(feature = "openapi")]
26-
use utoipa::openapi::{Object, ObjectBuilder};
2731

2832
use anyhow::bail;
29-
#[cfg(feature = "service")]
30-
pub use log::Item as LogItem;
31-
#[cfg(feature = "service")]
32-
pub use log::STATE_MESSAGE;
3333
use serde::{Deserialize, Serialize};
34-
#[cfg(feature = "service")]
35-
use uuid::Uuid;
34+
#[cfg(feature = "openapi")]
35+
use utoipa::openapi::{Object, ObjectBuilder};
3636

3737
#[cfg(debug_assertions)]
3838
pub const API_URL_DEFAULT: &str = "http://localhost:8001";
@@ -42,8 +42,6 @@ pub const API_URL_DEFAULT: &str = "https://api.shuttle.rs";
4242

4343
pub type ApiUrl = String;
4444
pub type Host = String;
45-
#[cfg(feature = "service")]
46-
pub type DeploymentId = Uuid;
4745

4846
#[derive(Clone, Serialize, Deserialize)]
4947
#[cfg_attr(feature = "persist", derive(sqlx::Type, PartialEq, Hash, Eq))]

0 commit comments

Comments
 (0)