This repository has been archived by the owner on Feb 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from PostHog/ellie/setup-producer-api
Setup basic API
- Loading branch information
Showing
9 changed files
with
844 additions
and
30 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
use envconfig::Envconfig; | ||
|
||
#[derive(Envconfig)] | ||
pub struct Config { | ||
#[envconfig(from = "BIND_HOST", default = "0.0.0.0")] | ||
pub host: String, | ||
|
||
#[envconfig(from = "BIND_PORT", default = "8000")] | ||
pub port: u16, | ||
} | ||
|
||
impl Config { | ||
pub fn bind(&self) -> String { | ||
format!("{}:{}", self.host, self.port) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub async fn get() -> &'static str { | ||
"rusty hook" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use axum::{routing, Router}; | ||
|
||
mod index; | ||
|
||
pub fn router() -> Router { | ||
let recorder_handle = crate::metrics::setup_metrics_recorder(); | ||
|
||
Router::new() | ||
.route("/", routing::get(index::get)) | ||
.route( | ||
"/metrics", | ||
routing::get(move || std::future::ready(recorder_handle.render())), | ||
) | ||
.layer(axum::middleware::from_fn(crate::metrics::track_metrics)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,32 @@ | ||
fn main() { | ||
println!("Hello, world!"); | ||
use axum::Router; | ||
|
||
use config::Config; | ||
use envconfig::Envconfig; | ||
|
||
use eyre::Result; | ||
|
||
mod config; | ||
mod handlers; | ||
mod metrics; | ||
|
||
async fn listen(app: Router, bind: String) -> Result<()> { | ||
let listener = tokio::net::TcpListener::bind(bind).await?; | ||
|
||
axum::serve(listener, app).await?; | ||
|
||
Ok(()) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
tracing_subscriber::fmt::init(); | ||
|
||
let app = handlers::router(); | ||
|
||
let config = Config::init_from_env().expect("failed to load configuration from env"); | ||
|
||
match listen(app, config.bind()).await { | ||
Ok(_) => {} | ||
Err(e) => tracing::error!("failed to start hook-producer http server, {}", e), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use std::time::Instant; | ||
|
||
use axum::{ | ||
body::Body, extract::MatchedPath, http::Request, middleware::Next, response::IntoResponse, | ||
}; | ||
use metrics_exporter_prometheus::{Matcher, PrometheusBuilder, PrometheusHandle}; | ||
|
||
pub fn setup_metrics_recorder() -> PrometheusHandle { | ||
const EXPONENTIAL_SECONDS: &[f64] = &[ | ||
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0, | ||
]; | ||
|
||
PrometheusBuilder::new() | ||
.set_buckets_for_metric( | ||
Matcher::Full("http_requests_duration_seconds".to_string()), | ||
EXPONENTIAL_SECONDS, | ||
) | ||
.unwrap() | ||
.install_recorder() | ||
.unwrap() | ||
} | ||
|
||
/// Middleware to record some common HTTP metrics | ||
/// Someday tower-http might provide a metrics middleware: https://github.com/tower-rs/tower-http/issues/57 | ||
pub async fn track_metrics(req: Request<Body>, next: Next) -> impl IntoResponse { | ||
let start = Instant::now(); | ||
|
||
let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() { | ||
matched_path.as_str().to_owned() | ||
} else { | ||
req.uri().path().to_owned() | ||
}; | ||
|
||
let method = req.method().clone(); | ||
|
||
// Run the rest of the request handling first, so we can measure it and get response | ||
// codes. | ||
let response = next.run(req).await; | ||
|
||
let latency = start.elapsed().as_secs_f64(); | ||
let status = response.status().as_u16().to_string(); | ||
|
||
let labels = [ | ||
("method", method.to_string()), | ||
("path", path), | ||
("status", status), | ||
]; | ||
|
||
metrics::increment_counter!("http_requests_total", &labels); | ||
metrics::histogram!("http_requests_duration_seconds", latency, &labels); | ||
|
||
response | ||
} |