use serde::Deserialize;
use std::fmt;
use crate::limits::Limits;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(thiserror::Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[error("Invalid time order")]
InvalidTimeOrder,
#[error("Empty update")]
EmptyUpdate,
#[error("Empty datasets")]
EmptyDatasets,
#[error("Empty type")]
EmptyType,
#[error("Missing token")]
MissingToken,
#[error("Missing Org ID for Personal Access Token")]
MissingOrgId,
#[error("Invalid token (make sure there are no invalid characters)")]
InvalidToken,
#[error("Invalid Org ID (make sure there are no invalid characters)")]
InvalidOrgId,
#[error("Failed to setup HTTP client: {0}")]
HttpClientSetup(reqwest::Error),
#[error("Failed to deserialize response: {0}")]
Deserialize(reqwest::Error),
#[error("Http error: {0}")]
Http(reqwest::Error),
#[error(transparent)]
Axiom(Axiom),
#[error("Query ID contains invisible characters (this is a server error)")]
InvalidQueryId,
#[error(transparent)]
InvalidParams(#[from] serde_qs::Error),
#[error(transparent)]
Serialize(#[from] serde_json::Error),
#[error("Failed to encode payload: {0}")]
Encoding(std::io::Error),
#[error("Duration is out of range (can't be larger than i64::MAX milliseconds)")]
DurationOutOfRange,
#[cfg(feature = "tokio")]
#[error("Failed to join thread: {0}")]
JoinError(tokio::task::JoinError),
#[error("Rate limit exceeded for the {scope} scope: {limits}")]
RateLimitExceeded {
scope: String,
limits: Limits,
},
#[error("Query limit exceeded: {0}")]
QueryLimitExceeded(Limits),
#[error("Ingest limit exceeded: {0}")]
IngestLimitExceeded(Limits),
#[error("Invalid URL: {0}")]
InvalidUrl(url::ParseError),
#[error("Error in ingest stream: {0}")]
IngestStreamError(Box<dyn std::error::Error + Send + Sync>),
#[error("Invalid content type: {0}")]
InvalidContentType(String),
#[error("Invalid content encoding: {0}")]
InvalidContentEncoding(String),
}
impl From<backoff::Error<reqwest::Error>> for Error {
fn from(err: backoff::Error<reqwest::Error>) -> Self {
match err {
backoff::Error::Permanent(err)
| backoff::Error::Transient {
err,
retry_after: _,
} => Error::Http(err),
}
}
}
#[derive(Deserialize, Debug)]
pub struct Axiom {
#[serde(skip)]
pub status: u16,
#[serde(skip)]
pub method: http::Method,
#[serde(skip)]
pub path: String,
pub message: Option<String>,
}
impl Axiom {
pub(crate) fn new(
status: u16,
method: http::Method,
path: String,
message: Option<String>,
) -> Self {
Self {
status,
method,
path,
message,
}
}
}
impl std::error::Error for Axiom {}
impl fmt::Display for Axiom {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(msg) = self.message.as_ref() {
write!(
f,
"Received {} on {} {}: {}",
self.status, self.method, self.path, msg
)
} else {
write!(
f,
"Received {} on {} {})",
self.method, self.path, self.status
)
}
}
}