Skip to content

Commit

Permalink
Add app insights telemetry.
Browse files Browse the repository at this point in the history
  • Loading branch information
twitchax committed Sep 1, 2023
1 parent 08e43f3 commit b1b7a15
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 170 deletions.
61 changes: 53 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 3 additions & 6 deletions rtz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ tz-osm = ["rtz-core/tz-osm", "rtz-build/tz-osm", "chrono-tz", "chrono"]
admin-osm = ["rtz-core/admin-osm", "rtz-build/admin-osm"]

cli = ["clap"]
web = ["full", "tokio", "config", "log", "simple_logger", "schemars", "chrono", "axum", "hyper", "tower", "tower-http", "utoipa", "utoipa-swagger-ui", "utoipa-redoc", "utoipa-rapidoc", "tracing", "opentelemetry", "opentelemetry-application-insights", "tracing-opentelemetry", "tracing-subscriber"]
web = ["full", "tokio", "config", "log", "simple_logger", "schemars", "chrono", "axum", "hyper", "tower", "tower-http", "utoipa", "utoipa-swagger-ui", "utoipa-redoc", "utoipa-rapidoc", "axum-insights", "tracing"]
wasm = ["wasm-bindgen", "wasm-bindgen-futures", "wee_alloc", "js-sys"]

[dependencies]
Expand Down Expand Up @@ -68,7 +68,7 @@ chrono-tz ={ version = "0.8.3", features = ["serde"], optional = true }
chrono = { version = "0.4.19", features = ["serde"], optional = true }

# web
tokio = { version = "1.29.1", features = ["rt", "macros", "signal"], optional = true }
tokio = { version = "1.29.1", features = ["rt", "macros", "signal", "parking_lot"], optional = true }
config = { version = "0.13.3", optional = true }
log = { version = "0.4.8", features = ["release_max_level_info"], optional = true }
simple_logger = { version = "4.2.0", optional = true }
Expand All @@ -83,11 +83,8 @@ utoipa-redoc = { version = "0.1.0", features = ["axum"], optional = true }
utoipa-rapidoc = { version = "0.1.0", features = ["axum"], optional = true }

# telemetry
axum-insights = { version = "0.2.0", optional = true }
tracing = { version = "0.1.37", optional = true }
opentelemetry = { version = "0.20", features = ["rt-tokio"], optional = true }
opentelemetry-application-insights = { version = "0.27.0", features = ["reqwest-client"], optional = true }
tracing-opentelemetry = { version = "0.20.0", optional = true}
tracing-subscriber = { version = "0.3.17", optional = true }

# wasm
wasm-bindgen = { version = "0.2.84", optional = true }
Expand Down
23 changes: 11 additions & 12 deletions rtz/src/web/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub(crate) mod config;
pub(crate) mod response_types;
pub(crate) mod server;
pub(crate) mod types;
pub(crate) mod telemetry;
pub(crate) mod utilities;

// Imports.
Expand Down Expand Up @@ -52,13 +51,13 @@ pub fn server_start(config_path: String, bind_address: Option<String>, port: Opt
mod tests {
use super::*;
use axum::Router;
use hyper::{Request, Body, StatusCode};
use hyper::{Body, Request, StatusCode};
use pretty_assertions::assert_eq;
use tower::{ServiceExt, Service};
use tower::{Service, ServiceExt};

fn get_client() -> Router {
let config = Config::new("", None, None, Some(false)).unwrap();

server::create_axum_app(&config)
}

Expand Down Expand Up @@ -148,14 +147,14 @@ mod bench {

use super::*;
use axum::Router;
use hyper::{Request, Body, StatusCode};
use hyper::{Body, Request, StatusCode};
use pretty_assertions::assert_eq;
use test::Bencher;
use tower::{ServiceExt, Service};
use tower::{Service, ServiceExt};

fn get_client() -> Router {
let config = Config::new("", None, None, Some(false)).unwrap();

server::create_axum_app(&config)
}

Expand Down Expand Up @@ -193,7 +192,7 @@ mod bench {
futures::executor::block_on(async {
let request = Request::get(format!("/api/ned/tz/{}/{}", x, y)).body(Body::empty()).unwrap();
let response = client.call(request).await.unwrap();

assert_eq!(response.status(), StatusCode::OK);
});
});
Expand All @@ -213,7 +212,7 @@ mod bench {
for y in ys.clone() {
let request = Request::get(format!("/api/osm/tz/{}/{}", x, y)).body(Body::empty()).unwrap();
let response = client.call(request).await.unwrap();

assert_eq!(response.status(), StatusCode::OK);
}
}
Expand All @@ -233,7 +232,7 @@ mod bench {
futures::executor::block_on(async {
let request = Request::get(format!("/api/osm/tz/{}/{}", x, y)).body(Body::empty()).unwrap();
let response = client.call(request).await.unwrap();

assert_eq!(response.status(), StatusCode::OK);
});
});
Expand All @@ -253,7 +252,7 @@ mod bench {
for y in ys.clone() {
let request = Request::get(format!("/api/osm/admin/{}/{}", x, y)).body(Body::empty()).unwrap();
let response = client.call(request).await.unwrap();

assert_eq!(response.status(), StatusCode::OK);
}
}
Expand All @@ -274,7 +273,7 @@ mod bench {
futures::executor::block_on(async {
let request = Request::get(format!("/api/osm/admin/{}/{}", x, y)).body(Body::empty()).unwrap();
let response = client.call(request).await.unwrap();

assert_eq!(response.status(), StatusCode::OK);
});
});
Expand Down
5 changes: 4 additions & 1 deletion rtz/src/web/response_types.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! Them for supporting the response types of the APIs, and their versions.

use axum::{response::{IntoResponse, Response}, http::HeaderValue};
use axum::{
http::HeaderValue,
response::{IntoResponse, Response},
};
use hyper::StatusCode;
use serde::Serialize;

Expand Down
64 changes: 54 additions & 10 deletions rtz/src/web/server.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
use std::sync::Arc;
use std::{
collections::HashMap,
sync::{Arc, OnceLock},
};

use axum::{extract::Path, routing::get, Json, Router, middleware::from_fn};
use axum::{extract::Path, routing::get, Json, Router};
use axum_insights::AppInsights;
use hyper::Method;
use rtz_core::{
base::types::{Float, Void},
geo::{
admin::osm::OsmAdmin,
tz::{ned::NedTimezone, osm::OsmTimezone},
},
};
use tracing::{instrument, Instrument};
use tower_http::cors::{Any, CorsLayer};
use tracing::instrument;
use utoipa::OpenApi;
use utoipa_rapidoc::RapiDoc;
use utoipa_redoc::{Redoc, Servable};
Expand All @@ -22,19 +28,22 @@ use crate::{
use super::{
config::Config,
response_types::LookupResponse,
types::{get_last_modified_time, AppState, IfModifiedSince, WebResult}, utilities::shutdown_signal, telemetry::{telemetry_fn, self},
types::{get_last_modified_time, AppState, IfModifiedSince, WebResult, WebError},
utilities::shutdown_signal,
};

// Statics.

static FLY_REGION: OnceLock<String> = OnceLock::new();
static FLY_ALLOC_ID: OnceLock<String> = OnceLock::new();
static FLY_PUBLIC_IP: OnceLock<String> = OnceLock::new();

/// Starts the web server.
pub async fn start(config: &Config) -> Void {
let app = create_axum_app(config);

telemetry::init(config.analytics_api_key.as_deref());

let bind_address = format!("{}:{}", config.bind_address, config.port);
axum::Server::bind(&bind_address
.parse()
.unwrap())
axum::Server::bind(&bind_address.parse().unwrap())
.serve(app.into_make_service())
.with_graceful_shutdown(shutdown_signal())
.await
Expand All @@ -46,7 +55,41 @@ pub async fn start(config: &Config) -> Void {
pub fn create_axum_app(config: &Config) -> Router {
let state = AppState { config: Arc::new(config.clone()) };

let telemetry_layer = from_fn(telemetry_fn);
let cors_layer = CorsLayer::new().allow_methods([Method::GET]).allow_origin(Any);

let name = std::env::var("FLY_REGION").unwrap_or_else(|_| "server".to_string());
let _ = FLY_REGION.set(name.clone());
let _ = FLY_ALLOC_ID.set(std::env::var("FLY_ALLOC_ID").unwrap_or_else(|_| "unknown".to_string()));
let _ = FLY_PUBLIC_IP.set(std::env::var("FLY_PUBLIC_IP").unwrap_or_else(|_| "unknown".to_string()));

let telemetry_layer = AppInsights::default()
.with_connection_string(config.analytics_api_key.clone())
.with_service_config("rtz", name)
.with_catch_panic(true)
.with_field_mapper(|p| {
let fly_alloc_id = FLY_ALLOC_ID.get().unwrap().to_owned();
let fly_public_ip = FLY_PUBLIC_IP.get().unwrap().to_owned();
let fly_region = FLY_REGION.get().unwrap().to_owned();
let fly_accept_region = p.headers.get("Fly-Region").map(|v| v.to_str().unwrap_or("unknown").to_owned()).unwrap_or("unknown".to_owned());

HashMap::from([
("fly.alloc_id".to_string(), fly_alloc_id),
("fly.public_ip".to_string(), fly_public_ip),
("fly.server_region".to_string(), fly_region),
("fly.accept_region".to_string(), fly_accept_region),
])
})
.with_panic_mapper(|e| {
(500, WebError {
status: 500,
message: format!("A panic occurred: {:?}", e),
backtrace: None,
})
})
.with_error_type::<WebError>()
.build_and_set_global_default()
.unwrap()
.layer();

let api_router = Router::new()
.route("/ned/tz/:lng/:lat", get(timezone_ned))
Expand All @@ -61,6 +104,7 @@ pub fn create_axum_app(config: &Config) -> Router {
.merge(Redoc::with_url("/redoc", ApiDoc::openapi()))
.merge(RapiDoc::new("/api-docs/openapi.json").path("/rapidoc"))
.nest("/api", api_router)
.layer(cors_layer)
.layer(telemetry_layer)
.with_state(state);

Expand Down
Loading

0 comments on commit b1b7a15

Please sign in to comment.