1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
//! This crate provides an interface to the [Prometheus HTTP API](https://prometheus.io/docs/prometheus/latest/querying/api/) and leverage Rust's type system in the process where applicable.
//!
//! The [Client] uses as [reqwest::Client] as HTTP client internally as you will see in the usage section. Thus its features and limitations also apply to this library.
//!
//! # Usage
//!
//! The following code contains just a few examples. See [Client] for the complete set of query functions.
//!
//!
//! ## Initialize a client
//!
//! The [Client] can be constructed in various ways depending on your need to add customizations.
//!
//! ```rust
//! use prometheus_http_query::Client;
//! use std::str::FromStr;
//!
//! // In the most general case the default implementation is used to create the client.
//! // Requests will be sent to "http://127.0.0.1:9090 (the default listen address and port of the Prometheus server).
//! let client = Client::default();
//!
//! // Provide an alternative URL if you need to. The URL will be checked for correctness.
//! use std::convert::TryFrom;
//! let client = Client::try_from("https://prometheus.example.com").unwrap();
//!
//! // The greatest flexibility is offered by initializing a reqwest::Client first with
//! // all needed customizations and passing it along.
//! let client = {
//! let c = reqwest::Client::builder().no_proxy().build().unwrap();
//! Client::from(c, "https://prometheus.example.com").unwrap();
//! };
//! ```
//!
//! ## Execute PromQL queries
//!
//! ```rust
//! use prometheus_http_query::{Client, Error, Selector};
//!
//! #[tokio::main(flavor = "current_thread")]
//! async fn main() -> Result<(), Error> {
//! let client = Client::default();
//!
//! let q = "topk by (code) (5, prometheus_http_requests_total)";
//! let response = client.query(q, None, None).await?;
//! assert!(response.as_instant().is_some());
//!
//! let q = r#"sum(prometheus_http_requests_total{code="200"})"#;
//! let response = client.query(q, None, None).await?;
//! let result = response.as_instant();
//!
//! if matches!(result, Some(x) if x.first().is_some()) {
//! let first = result.unwrap().first().unwrap();
//! println!("Received a total of {} HTTP requests", first.sample().value());
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ## Metadata queries
//!
//! Retrieve a list of time series that match a certain label set by providing one or more series [Selector]s.
//!
//! ```rust
//! use prometheus_http_query::{Client, Error, Selector};
//!
//! #[tokio::main(flavor = "current_thread")]
//! async fn main() -> Result<(), Error> {
//! let client = Client::default();
//!
//! let s1 = Selector::new()
//! .eq("handler", "/api/v1/query");
//!
//! let s2 = Selector::new()
//! .eq("job", "node")
//! .regex_eq("mode", ".+");
//!
//! let response = client.series(&[s1, s2], None, None).await;
//!
//! assert!(response.is_ok());
//!
//! Ok(())
//! }
//! ```
//!
//! ## Rules & Alerts
//!
//! Retrieve recording/alerting rules and active alerts.
//!
//! ```rust
//! use prometheus_http_query::{Client, Error, RuleType};
//!
//! #[tokio::main(flavor = "current_thread")]
//! async fn main() -> Result<(), Error> {
//! let client = Client::default();
//!
//! let response = client.rules(None).await;
//!
//! assert!(response.is_ok());
//!
//! // Only request alerting rules instead:
//! let response = client.rules(Some(RuleType::Alert)).await;
//!
//! assert!(response.is_ok());
//!
//! // Request active alerts:
//! let response = client.alerts().await;
//!
//! assert!(response.is_ok());
//!
//! Ok(())
//! }
//! ```
//!
//! ## Convenience functions for one-off requests
//!
//! ```rust
//! use prometheus_http_query::{Error, query, runtime_information};
//!
//! #[tokio::main(flavor = "current_thread")]
//! async fn main() -> Result<(), Error> {
//! let q = "topk by (code) (5, prometheus_http_requests_total)";
//! let response = query("http://localhost:9090", q, None, None).await?;
//!
//! assert!(response.as_instant().is_some());
//!
//! let response = runtime_information("http://localhost:9090").await;
//!
//! assert!(response.is_ok());
//!
//! Ok(())
//! }
//! ```
//!
//! # Compatibility
//!
//! See the `README` for details on this matter.
//!
//! # Supported operations
//!
//! - [x] Execute instant and range queries and properly parse the results (vector/matrix/scalar)
//! - [x] Execute series metadata queries
//! - [x] Execute label metadata queries (names/values)
//! - [x] Retrieve target discovery status
//! - [x] Retrieve alerting + recording rules
//! - [x] Retrieve active alerts
//! - [x] Retrieve configured flags & values
//! - [x] Query target metadata
//! - [x] Query metric metadata
//! - [x] Query alertmanager service discovery status
//! - [x] Prometheus server flags
//! - [x] Prometheus server build information
//! - [x] Prometheus server runtime information
//! - [ ] Prometheus server config
//!
//! # Notes
//!
//! ## On parsing an error handling
//!
//! If the JSON response from the Prometheus HTTP API indicates an error (field `status` == `"error"`),
//! then the contents of both fields `errorType` and `error` are captured and then returned by the client
//! as a variant of the [Error] enum, just as any HTTP errors (non-200) that may indicate a problem
//! with the provided query string. Thus any syntax problems etc. that cannot be caught at compile time
//! or before executing the query will at least be propagated as returned by the HTTP API.
//!
//! # Limitations
//!
//! * Some [Client] methods may not work with older versions of the Prometheus server
//! * The [String](https://prometheus.io/docs/prometheus/latest/querying/api/#strings) result type is not supported
//! * Warnings contained in a API response will be ignored
mod client;
mod direct;
mod error;
pub mod response;
mod selector;
mod util;
pub use self::client::Client;
pub use self::direct::*;
pub use self::error::Error;
pub use self::selector::Selector;
pub use self::util::RuleType;
pub use self::util::TargetState;