autoconnect_web/
dockerflow.rs1use std::thread;
3
4use actix_web::{
5 web::{self, Data, Json},
6 HttpResponse, ResponseError,
7};
8use serde_json::json;
9
10use autoconnect_settings::AppState;
11#[allow(unused_imports)]
14use autopush_common::metric_name::MetricName;
15#[allow(unused_imports)]
16use autopush_common::metrics::StatsdClientExt;
17
18use crate::error::ApiError;
19
20pub fn config(config: &mut web::ServiceConfig) {
22 config
23 .service(web::resource("/status").route(web::get().to(status_route)))
24 .service(web::resource("/health").route(web::get().to(health_route)))
25 .service(web::resource("/v1/err/crit").route(web::get().to(log_check)))
26 .service(web::resource("/__error__").route(web::get().to(log_check)))
28 .service(web::resource("/__heartbeat__").route(web::get().to(health_route)))
30 .service(web::resource("/__lbheartbeat__").route(web::get().to(lb_heartbeat_route)))
31 .service(web::resource("/__version__").route(web::get().to(version_route)));
32}
33
34pub async fn health_route(state: Data<AppState>) -> Json<serde_json::Value> {
36 #[allow(unused_mut)]
37 let mut health = json!({
38 "status": if state
39 .db
40 .health_check()
41 .await
42 .map_err(|e| {
43 error!("Autoconnect Health Error: {:?}", e);
44 e
45 })
46 .is_ok() { "OK" } else {"ERROR"},
47 "version": env!("CARGO_PKG_VERSION"),
48 "connections": state.clients.count().await
49 });
50
51 #[cfg(feature = "reliable_report")]
52 {
53 health["reliability"] = json!(state.reliability.health_check().await.unwrap_or_else(|e| {
54 state
55 .metrics
56 .incr_with_tags(MetricName::ErrorRedisUnavailable)
57 .with_tag("application", "autoconnect")
58 .send();
59 error!("🔍🟥 Reliability reporting down: {:?}", e);
60 "ERROR"
61 }));
62 }
63
64 Json(health)
65}
66
67pub async fn status_route(state: Data<AppState>) -> Json<serde_json::Value> {
69 let mut status: std::collections::HashMap<&str, String> = std::collections::HashMap::new();
70 status.insert("version", env!("CARGO_PKG_VERSION").to_owned());
71 let check = state.db.health_check().await;
72 if check.is_ok() {
73 status.insert("status", "OK".to_owned());
74 } else {
75 status.insert("status", "ERROR".to_owned());
76 }
77 if let Some(err) = check.err().map(|v| v.to_string()) {
78 status.insert("error", err);
79 };
80
81 Json(json!(status))
82}
83
84pub async fn lb_heartbeat_route() -> HttpResponse {
86 HttpResponse::Ok().finish()
88}
89
90pub async fn version_route() -> HttpResponse {
92 HttpResponse::Ok()
95 .content_type("application/json")
96 .body(include_str!("../../../version.json"))
97}
98
99pub async fn log_check() -> Result<HttpResponse, ApiError> {
101 let err = ApiError::LogCheck;
102 error!(
103 "Test Critical Message";
104 "status_code" => err.status_code().as_u16(),
105 "errno" => err.errno(),
106 );
107
108 thread::spawn(|| {
109 panic!("LogCheck");
110 });
111
112 Err(err)
113}