diff --git a/Cargo.lock b/Cargo.lock
index 1bb820ac4b..90bbc81a68 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5331,6 +5331,8 @@ dependencies = [
name = "shuttle-common"
version = "0.7.2"
dependencies = [
+ "async-trait",
+ "axum",
"chrono",
"comfy-table",
"crossterm",
diff --git a/common/Cargo.toml b/common/Cargo.toml
index e76c61a6dd..6bcb979588 100644
--- a/common/Cargo.toml
+++ b/common/Cargo.toml
@@ -7,6 +7,8 @@ description = "Common library for the shuttle platform (https://www.shuttle.rs/)
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+async-trait = { version = "0.1.52", optional = true }
+axum = { version = "0.5.8", optional = true }
chrono = { version = "0.4.22", features = ["serde"] }
comfy-table = { version = "6.1.0", optional = true }
crossterm = { version = "0.25.0", optional = true }
@@ -22,5 +24,6 @@ uuid = { version = "1.1.1", features = ["v4", "serde"] }
[features]
default = ["models"]
-models = ["display", "serde_json", "http"]
+backend = ["async-trait", "axum"]
display = ["comfy-table", "crossterm"]
+models = ["display", "serde_json", "http"]
diff --git a/deployer/src/handlers/metrics.rs b/common/src/backends/metrics.rs
similarity index 77%
rename from deployer/src/handlers/metrics.rs
rename to common/src/backends/metrics.rs
index 3b5988ff9b..433205b90e 100644
--- a/deployer/src/handlers/metrics.rs
+++ b/common/src/backends/metrics.rs
@@ -5,6 +5,8 @@ use axum::extract::{FromRequest, Path, RequestParts};
use tracing::Span;
/// Used to record a bunch of metrics info
+/// The tracing layer on the server should record a `request.params.` field for each parameter
+/// that should be recorded
pub struct Metrics;
#[async_trait]
@@ -15,10 +17,10 @@ where
type Rejection = Infallible;
async fn from_request(req: &mut RequestParts) -> Result {
- // We expect some path parameters
+ // Get path parameters if they exist
let Path(path): Path> = match req.extract().await {
Ok(path) => path,
- Err(_) => todo!(),
+ Err(_) => return Ok(Metrics),
};
let span = Span::current();
diff --git a/common/src/backends/mod.rs b/common/src/backends/mod.rs
new file mode 100644
index 0000000000..e144883287
--- /dev/null
+++ b/common/src/backends/mod.rs
@@ -0,0 +1 @@
+pub mod metrics;
diff --git a/common/src/lib.rs b/common/src/lib.rs
index bd7e50afc3..5f7be0326d 100644
--- a/common/src/lib.rs
+++ b/common/src/lib.rs
@@ -1,3 +1,5 @@
+#[cfg(feature = "backend")]
+pub mod backends;
pub mod database;
pub mod deployment;
pub mod log;
diff --git a/deployer/src/handlers/mod.rs b/deployer/src/handlers/mod.rs
index 9d16575d75..1d072488ac 100644
--- a/deployer/src/handlers/mod.rs
+++ b/deployer/src/handlers/mod.rs
@@ -13,6 +13,7 @@ use fqdn::FQDN;
use futures::StreamExt;
use opentelemetry::global;
use opentelemetry_http::HeaderExtractor;
+use shuttle_common::backends::metrics::Metrics;
use shuttle_common::models::secret;
use shuttle_common::project::ProjectName;
use shuttle_common::LogItem;
@@ -30,7 +31,6 @@ use std::time::Duration;
pub use {self::error::Error, self::error::Result};
-mod metrics;
mod project;
pub fn make_router(
@@ -72,7 +72,7 @@ pub fn make_router(
.layer(RequireAuthorizationLayer::bearer(&admin_secret))
// This route should be below the auth bearer since it does not need authentication
.route("/projects/:project_name/status", get(get_status))
- .route_layer(from_extractor::())
+ .route_layer(from_extractor::())
.layer(
TraceLayer::new_for_http()
.make_span_with(|request: &Request| {
diff --git a/gateway/Cargo.toml b/gateway/Cargo.toml
index e45fca8a63..dd16b65a47 100644
--- a/gateway/Cargo.toml
+++ b/gateway/Cargo.toml
@@ -36,6 +36,7 @@ uuid = { version = "1.2.1", features = [ "v4" ] }
[dependencies.shuttle-common]
version = "0.7.2"
path = "../common"
+features = ["backend"]
[dev-dependencies]
anyhow = "1"
diff --git a/gateway/src/api/latest.rs b/gateway/src/api/latest.rs
index cf5bfe3501..70113b06de 100644
--- a/gateway/src/api/latest.rs
+++ b/gateway/src/api/latest.rs
@@ -10,6 +10,7 @@ use axum::routing::{any, get, post};
use axum::{Json as AxumJson, Router};
use http::StatusCode;
use serde::{Deserialize, Serialize};
+use shuttle_common::backends::metrics::Metrics;
use shuttle_common::models::error::ErrorKind;
use shuttle_common::models::{project, user};
use tokio::sync::mpsc::Sender;
@@ -191,7 +192,7 @@ pub fn make_api(service: Arc, sender: Sender) -> Rout
.route("/admin/revive", post(revive_projects))
.layer(Extension(service))
.layer(Extension(sender))
- .route_layer(from_extractor::())
+ .route_layer(from_extractor::())
.layer(
TraceLayer::new_for_http()
.make_span_with(|request: &Request| {
diff --git a/gateway/src/api/metrics.rs b/gateway/src/api/metrics.rs
deleted file mode 100644
index 3b5988ff9b..0000000000
--- a/gateway/src/api/metrics.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-use std::{collections::HashMap, convert::Infallible};
-
-use async_trait::async_trait;
-use axum::extract::{FromRequest, Path, RequestParts};
-use tracing::Span;
-
-/// Used to record a bunch of metrics info
-pub struct Metrics;
-
-#[async_trait]
-impl FromRequest for Metrics
-where
- B: Send,
-{
- type Rejection = Infallible;
-
- async fn from_request(req: &mut RequestParts) -> Result {
- // We expect some path parameters
- let Path(path): Path> = match req.extract().await {
- Ok(path) => path,
- Err(_) => todo!(),
- };
-
- let span = Span::current();
-
- for (param, value) in path {
- span.record(format!("request.params.{param}").as_str(), value);
- }
- Ok(Metrics)
- }
-}
diff --git a/gateway/src/api/mod.rs b/gateway/src/api/mod.rs
index 3d9f08f8df..02afbd488f 100644
--- a/gateway/src/api/mod.rs
+++ b/gateway/src/api/mod.rs
@@ -1,4 +1,3 @@
pub mod latest;
-mod metrics;
pub use latest::make_api;