diff --git a/CHANGELOG.md b/CHANGELOG.md index a147dbc..451e1b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -- +- Update `http` to `1.0`. This fixes compatibility with `axum 0.7` (#167) -## [1.0.0] - 2023-12-01 +## [1.0.0](https://github.com/autometrics-dev/autometrics-rs/releases/tag/v1.0.0) - 2023-12-01 ### Breaking changes diff --git a/autometrics-macros/src/lib.rs b/autometrics-macros/src/lib.rs index 198bf35..42b0c4f 100644 --- a/autometrics-macros/src/lib.rs +++ b/autometrics-macros/src/lib.rs @@ -45,7 +45,8 @@ pub fn autometrics( /// - `async_trait` attributes that have to be re-added after our instrumentation magic has been added /// - `input` but without the `async_trait` attributes fn check_async_trait(input: proc_macro::TokenStream) -> (String, proc_macro::TokenStream) { - let regex = Regex::new(r#"#\[[^\]]*async_trait\]"#).expect("The regex is hardcoded and thus guaranteed to be successfully parseable"); + let regex = Regex::new(r#"#\[[^\]]*async_trait\]"#) + .expect("The regex is hardcoded and thus guaranteed to be successfully parseable"); let original = input.to_string(); diff --git a/autometrics/Cargo.toml b/autometrics/Cargo.toml index 8e38701..8464c31 100644 --- a/autometrics/Cargo.toml +++ b/autometrics/Cargo.toml @@ -96,7 +96,7 @@ opentelemetry = { version = "0.21", default-features = false, optional = true } metrics = { version = "0.21", default-features = false, optional = true } # Used for prometheus-exporter feature -http = { version = "0.2", optional = true } +http = { version = "1.0.0", optional = true } metrics-exporter-prometheus = { version = "0.12", default-features = false, optional = true } opentelemetry-prometheus = { version = "0.14", optional = true } opentelemetry_sdk = { version = "0.21", default-features = false, features = [ @@ -119,9 +119,9 @@ tracing-opentelemetry-0-22 = { package = "tracing-opentelemetry", version = "0.2 [dev-dependencies] async-trait = "0.1.74" -axum = { version = "0.6", features = ["tokio"] } +axum = { version = "0.7.2", features = ["tokio"] } criterion = "0.5" -http = "0.2" +http = "1.0.0" opentelemetry = "0.21" opentelemetry-stdout = { version = "0.2", features = ["trace"] } prometheus-client = "0.22" diff --git a/autometrics/README.md b/autometrics/README.md index 8c4e0d1..cf2f0eb 100644 --- a/autometrics/README.md +++ b/autometrics/README.md @@ -33,29 +33,35 @@ See [autometrics.dev](https://docs.autometrics.dev/) for more details on the ide Autometrics isn't tied to any web framework, but this shows how you can use the library in an [Axum](https://github.com/tokio-rs/axum) server. -```rust +```rust,ignore +use std::error::Error; use autometrics::{autometrics, prometheus_exporter}; -use axum::{routing::*, Router, Server}; +use axum::{routing::*, Router}; +use std::net::Ipv4Addr; +use tokio::net::TcpListener; // Instrument your functions with metrics #[autometrics] pub async fn create_user() -> Result<(), ()> { - Ok(()) + Ok(()) } // Export the metrics to Prometheus #[tokio::main] -pub async fn main() { - prometheus_exporter::init(); - - let app = Router::new() - .route("/users", post(create_user)) - .route( - "/metrics", - get(|| async { prometheus_exporter::encode_http_response() }), - ); - Server::bind(&([127, 0, 0, 1], 0).into()) - .serve(app.into_make_service()); +pub async fn main() -> Result<(), Box> { + prometheus_exporter::init(); + + let app = Router::new() + .route("/users", post(create_user)) + .route( + "/metrics", + get(|| async { prometheus_exporter::encode_http_response() }), + ); + + + let listener = TcpListener::bind((Ipv4Addr::from([127, 0, 0, 1]), 0)).await?; + axum::serve(listener, app).await?; + Ok(()) } ``` diff --git a/autometrics/src/README.md b/autometrics/src/README.md index eb48708..96fbeb7 100644 --- a/autometrics/src/README.md +++ b/autometrics/src/README.md @@ -33,9 +33,12 @@ See [autometrics.dev](https://docs.autometrics.dev/) for more details on the ide Autometrics isn't tied to any web framework, but this shows how you can use the library in an [Axum](https://github.com/tokio-rs/axum) server. -```rust +```rust,ignore use autometrics::{autometrics, prometheus_exporter}; -use axum::{routing::*, Router, Server}; +use axum::{routing::*, Router}; +use std::error::Error; +use std::net::Ipv4Addr; +use tokio::net::TcpListener; // Instrument your functions with metrics #[autometrics] @@ -45,17 +48,19 @@ pub async fn create_user() -> Result<(), ()> { // Export the metrics to Prometheus #[tokio::main] -pub async fn main() { - prometheus_exporter::init(); - - let app = Router::new() - .route("/users", post(create_user)) - .route( - "/metrics", - get(|| async { prometheus_exporter::encode_http_response() }), - ); - Server::bind(&([127, 0, 0, 1], 0).into()) - .serve(app.into_make_service()); +pub async fn main() -> Result<(), Box> { + prometheus_exporter::init(); + + let app = Router::new() + .route("/users", post(create_user)) + .route( + "/metrics", + get(|| async { prometheus_exporter::encode_http_response() }), + ); + + let listener = TcpListener::bind((Ipv4Addr::from([127, 0, 0, 1]), 0)).await?; + axum::serve(listener, app).await?; + Ok(()) } ``` diff --git a/examples/axum/Cargo.toml b/examples/axum/Cargo.toml index e3e0435..c9c83e0 100644 --- a/examples/axum/Cargo.toml +++ b/examples/axum/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] autometrics = { path = "../../autometrics", features = ["prometheus-exporter"] } autometrics-example-util = { path = "../util" } -axum = { version = "0.6", features = ["json"] } +axum = { version = "0.7.2", features = ["json"] } rand = "0.8" reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1", features = ["full"] } diff --git a/examples/axum/src/main.rs b/examples/axum/src/main.rs index 5a544f0..788ba16 100644 --- a/examples/axum/src/main.rs +++ b/examples/axum/src/main.rs @@ -2,7 +2,10 @@ use autometrics::{autometrics, prometheus_exporter}; use autometrics_example_util::{run_prometheus, sleep_random_duration}; use axum::{http::StatusCode, response::IntoResponse, routing::get, Router}; use rand::{random, thread_rng, Rng}; -use std::{net::SocketAddr, time::Duration}; +use std::error::Error; +use std::net::Ipv4Addr; +use std::time::Duration; +use tokio::net::TcpListener; // Starting simple, hover over the function name to see the Autometrics graph links in the Rust Docs! /// This is a simple endpoint that never errors @@ -43,7 +46,7 @@ where } #[tokio::main] -pub async fn main() { +pub async fn main() -> Result<(), Box> { // Run Prometheus and generate random traffic for the app // (You would not actually do this in production, but it makes it easier to see the example in action) let _prometheus = run_prometheus(false); @@ -58,8 +61,8 @@ pub async fn main() { get(|| async { prometheus_exporter::encode_http_response() }), ); - let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); - let server = axum::Server::bind(&addr); + let listener = TcpListener::bind((Ipv4Addr::from([127, 0, 0, 1]), 3000)).await?; + let addr = listener.local_addr()?; println!( "The example API server is now running on: {addr} @@ -70,10 +73,8 @@ Then, hover over one of the HTTP handler functions (in your editor) to bring up Click on one of the Autometrics links to see the graph for that handler's metrics in Prometheus." ); - server - .serve(app.into_make_service()) - .await - .expect("Error starting example API server"); + axum::serve(listener, app).await?; + Ok(()) } /// Make some random API calls to generate data that we can see in the graphs diff --git a/examples/exemplars-tracing-opentelemetry/Cargo.toml b/examples/exemplars-tracing-opentelemetry/Cargo.toml index 8ae1aab..22e7a60 100644 --- a/examples/exemplars-tracing-opentelemetry/Cargo.toml +++ b/examples/exemplars-tracing-opentelemetry/Cargo.toml @@ -11,7 +11,7 @@ autometrics = { path = "../../autometrics", features = [ "exemplars-tracing-opentelemetry-0_22", ] } autometrics-example-util = { path = "../util" } -axum = { version = "0.6", features = ["json"] } +axum = { version = "0.7.2", features = ["json"] } opentelemetry = "0.20" opentelemetry-stdout = { version = "0.1", features = ["trace"] } reqwest = { version = "0.11", features = ["json"] } diff --git a/examples/exemplars-tracing-opentelemetry/src/main.rs b/examples/exemplars-tracing-opentelemetry/src/main.rs index 5963df0..367d6ce 100644 --- a/examples/exemplars-tracing-opentelemetry/src/main.rs +++ b/examples/exemplars-tracing-opentelemetry/src/main.rs @@ -1,10 +1,13 @@ use autometrics::{autometrics, prometheus_exporter}; use autometrics_example_util::run_prometheus; -use axum::{routing::get, Router, Server}; +use axum::{routing::get, Router, ServiceExt}; use opentelemetry::sdk::trace::TracerProvider; use opentelemetry::trace::TracerProvider as _; use opentelemetry_stdout::SpanExporter; +use std::error::Error; +use std::net::Ipv4Addr; use std::{io, net::SocketAddr, time::Duration}; +use tokio::net::TcpListener; use tracing::{instrument, trace}; use tracing_opentelemetry::OpenTelemetryLayer; use tracing_subscriber::{layer::SubscriberExt, prelude::*, Registry}; @@ -28,7 +31,7 @@ fn inner_function() { } #[tokio::main] -async fn main() { +async fn main() -> Result<(), Box> { // Run Prometheus with flag --enable-feature=exemplars-storage let _prometheus = run_prometheus(true); tokio::spawn(generate_random_traffic()); @@ -54,17 +57,18 @@ async fn main() { get(|| async { prometheus_exporter::encode_http_response() }), ); - let server = Server::bind(&([127, 0, 0, 1], 3000).into()); - println!("\nVisit the following URL to see one of the charts along with the exemplars:"); println!("http://localhost:9090/graph?g0.expr=%23%20Rate%20of%20calls%20to%20the%20%60outer_function%60%20function%20per%20second%2C%20averaged%20over%205%20minute%20windows%0A%0Asum%20by%20(function%2C%20module%2C%20commit%2C%20version)%20(rate(%7B__name__%3D~%22function_calls(_count)%3F(_total)%3F%22%2Cfunction%3D%22outer_function%22%7D%5B5m%5D)%20*%20on%20(instance%2C%20job)%20group_left(version%2C%20commit)%20last_over_time(build_info%5B1s%5D))&g0.tab=0&g0.stacked=0&g0.show_exemplars=1&g0.range_input=1h"); - server - .serve(app.into_make_service_with_connect_info::()) - .await - .expect("Error starting example API server"); + let listener = TcpListener::bind((Ipv4Addr::from([127, 0, 0, 1]), 3000)).await?; + axum::serve( + listener, + app.into_make_service_with_connect_info::(), + ) + .await?; opentelemetry::global::shutdown_tracer_provider(); + Ok(()) } pub async fn generate_random_traffic() { diff --git a/examples/exemplars-tracing/Cargo.toml b/examples/exemplars-tracing/Cargo.toml index 6d8dd7b..ece1221 100644 --- a/examples/exemplars-tracing/Cargo.toml +++ b/examples/exemplars-tracing/Cargo.toml @@ -11,7 +11,7 @@ autometrics = { path = "../../autometrics", features = [ "exemplars-tracing" ] } autometrics-example-util = { path = "../util" } -axum = { version = "0.6", features = ["json"] } +axum = { version = "0.7.2", features = ["json"] } reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1", features = ["full"] } tracing = "0.1" diff --git a/examples/exemplars-tracing/src/main.rs b/examples/exemplars-tracing/src/main.rs index 3043356..3093f3b 100644 --- a/examples/exemplars-tracing/src/main.rs +++ b/examples/exemplars-tracing/src/main.rs @@ -3,7 +3,10 @@ use autometrics::{ }; use autometrics_example_util::run_prometheus; use axum::{http::header::CONTENT_TYPE, response::Response, routing::get, Router}; +use std::error::Error; +use std::net::Ipv4Addr; use std::{net::SocketAddr, time::Duration}; +use tokio::net::TcpListener; use tracing::{instrument, trace}; use tracing_subscriber::{prelude::*, EnvFilter}; use uuid::Uuid; @@ -27,7 +30,7 @@ fn inner_function(param: &str) { } #[tokio::main] -async fn main() { +async fn main() -> Result<(), Box> { // Run Prometheus with flag --enable-feature=exemplars-storage let _prometheus = run_prometheus(true); tokio::spawn(generate_random_traffic()); @@ -46,16 +49,12 @@ async fn main() { get(|| async { prometheus_exporter::encode_http_response() }), ); - let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); - let server = axum::Server::bind(&addr); - println!("\nVisit the following URL to see one of the charts along with the exemplars:"); println!("http://localhost:9090/graph?g0.expr=%23%20Rate%20of%20calls%20to%20the%20%60outer_function%60%20function%20per%20second%2C%20averaged%20over%205%20minute%20windows%0A%0Asum%20by%20(function%2C%20module%2C%20commit%2C%20version)%20(rate(%7B__name__%3D~%22function_calls(_count)%3F(_total)%3F%22%2Cfunction%3D%22outer_function%22%7D%5B5m%5D)%20*%20on%20(instance%2C%20job)%20group_left(version%2C%20commit)%20last_over_time(build_info%5B1s%5D))&g0.tab=0&g0.stacked=0&g0.show_exemplars=1&g0.range_input=1h"); - server - .serve(app.into_make_service()) - .await - .expect("Error starting example API server"); + let listener = TcpListener::bind((Ipv4Addr::from([127, 0, 0, 1]), 3000)).await?; + axum::serve(listener, app).await?; + Ok(()) } pub async fn generate_random_traffic() { diff --git a/examples/full-api/Cargo.toml b/examples/full-api/Cargo.toml index b343f28..52df5b2 100644 --- a/examples/full-api/Cargo.toml +++ b/examples/full-api/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] autometrics = { path = "../../autometrics", features = ["prometheus-exporter"] } autometrics-example-util = { path = "../util" } -axum = { version = "0.6", features = ["json"] } +axum = { version = "0.7.2", features = ["json"] } rand = "0.8" reqwest = { version = "0.11", features = ["json"] } serde = { version = "1", features = ["derive"] } diff --git a/examples/full-api/src/main.rs b/examples/full-api/src/main.rs index f0f7de1..aea2be1 100644 --- a/examples/full-api/src/main.rs +++ b/examples/full-api/src/main.rs @@ -4,7 +4,9 @@ use autometrics::prometheus_exporter; use autometrics_example_util::run_prometheus; use axum::routing::{get, post}; use axum::Router; -use std::net::SocketAddr; +use std::error::Error; +use std::net::{Ipv4Addr, SocketAddr}; +use tokio::net::TcpListener; mod database; mod error; @@ -13,7 +15,7 @@ mod util; /// Run the API server as well as Prometheus and a traffic generator #[tokio::main] -async fn main() { +async fn main() -> Result<(), Box> { // Run Prometheus and generate random traffic for the app // (You would not actually do this in production, but it makes it easier to see the example in action) let _prometheus = run_prometheus(false); @@ -33,8 +35,8 @@ async fn main() { ) .with_state(Database::new()); - let addr = SocketAddr::from(([127, 0, 0, 1], 3000)); - let server = axum::Server::bind(&addr); + let listener = TcpListener::bind((Ipv4Addr::from([127, 0, 0, 1]), 3000)).await?; + let addr = listener.local_addr()?; println!( "The example API server is now running on: {addr} @@ -45,8 +47,6 @@ Then, hover over one of the HTTP handler functions (in your editor) to bring up Click on one of the Autometrics links to see the graph for that handler's metrics in Prometheus." ); - server - .serve(app.into_make_service()) - .await - .expect("Error starting example API server"); + axum::serve(listener, app).await?; + Ok(()) }