feat: add error code for search (#311)

* feat: add error code for search

* feat: add error_code for search

* fix: unit test

* feat: format http response
This commit is contained in:
Hengfei Yang
2023-03-18 11:44:23 +08:00
committed by GitHub
parent d000c189db
commit b355cafced
33 changed files with 445 additions and 209 deletions
@@ -49,12 +49,12 @@ pub async fn save_destination(
Some(_) => destinations::save_destination(org_id, name, dest).await,
None => Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Please specify valid template".to_string()),
"Please specify valid template".to_string(),
))),
},
Err(_) => Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Please specify valid template".to_string()),
"Please specify valid template".to_string(),
))),
}
}
@@ -20,8 +20,8 @@ use crate::service::logs;
/** Elasticsearch compatible _bulk ingestion API */
#[utoipa::path(
context_path = "/api",
tag = "Ingestion",
operation_id = "IngestionBulk",
tag = "Logs",
operation_id = "LogsIngestionBulk",
security(
("Authorization"= [])
),
@@ -47,8 +47,8 @@ pub async fn bulk(
/** ndjson (newline delimited json) multi ingestion API */
#[utoipa::path(
context_path = "/api",
tag = "Ingestion",
operation_id = "IngestionMulti",
tag = "Logs",
operation_id = "LogsIngestionMulti",
security(
("Authorization"= [])
),
@@ -75,8 +75,8 @@ pub async fn multi(
/** json ingestion API, accepts array of json records */
#[utoipa::path(
context_path = "/api",
tag = "Ingestion",
operation_id = "IngestionJson",
tag = "Logs",
operation_id = "LogsIngestionJson",
security(
("Authorization"= [])
),
+15
View File
@@ -0,0 +1,15 @@
// Copyright 2022 Zinc Labs Inc. and Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub mod ingest;
+1 -1
View File
@@ -15,7 +15,7 @@
pub mod alerts;
pub mod dashboards;
pub mod functions;
pub mod ingest;
pub mod logs;
pub mod organization;
pub mod prom;
pub mod search;
+1 -1
View File
@@ -32,7 +32,7 @@ pub async fn prometheus_write(
Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Bad Request".to_string()),
"Bad Request".to_string(),
)),
)
}
+27 -22
View File
@@ -22,10 +22,9 @@ use std::time::Instant;
use crate::common::http::get_stream_type_from_request;
use crate::infra::config::{CONFIG, LOCKER};
use crate::infra::metrics;
use crate::meta;
use crate::infra::{errors, metrics};
use crate::meta::http::HttpResponse as MetaHttpResponse;
use crate::meta::StreamType;
use crate::meta::{self, StreamType};
use crate::service::search as SearchService;
/** Search using SQL against a stream data */
@@ -106,7 +105,7 @@ pub async fn search(
Err(e) => {
return Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)))
}
};
@@ -117,14 +116,14 @@ pub async fn search(
Err(e) => {
return Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)))
}
};
if let Err(e) = req.decode() {
return Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)));
}
@@ -159,7 +158,6 @@ pub async fn search(
Ok(HttpResponse::Ok().json(res))
}
Err(err) => {
log::error!("search error: {:?}", err);
let time = start.elapsed().as_secs_f64();
metrics::HTTP_RESPONSE_TIME
.with_label_values(&[
@@ -179,12 +177,15 @@ pub async fn search(
stream_type.to_string().as_str(),
])
.inc();
Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
log::error!("search error: {:?}", err);
Ok(match err {
errors::Error::ErrorCode(code) => HttpResponse::InternalServerError()
.json(meta::http::HttpResponse::error_code(code)),
_ => HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(err.to_string()),
err.to_string(),
)),
)
})
}
}
}
@@ -245,7 +246,7 @@ pub async fn around(
Err(e) => {
return Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)))
}
};
@@ -285,7 +286,6 @@ pub async fn around(
let resp_forward = match SearchService::search(&org_id, stream_type, &req).await {
Ok(res) => res,
Err(err) => {
log::error!("search error: {:?}", err);
let time = start.elapsed().as_secs_f64();
metrics::HTTP_RESPONSE_TIME
.with_label_values(&[
@@ -305,12 +305,15 @@ pub async fn around(
stream_type.to_string().as_str(),
])
.inc();
return Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
log::error!("search around error: {:?}", err);
return Ok(match err {
errors::Error::ErrorCode(code) => HttpResponse::InternalServerError()
.json(meta::http::HttpResponse::error_code(code)),
_ => HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(err.to_string()),
err.to_string(),
)),
);
});
}
};
@@ -334,7 +337,6 @@ pub async fn around(
let resp_backward = match SearchService::search(&org_id, stream_type, &req).await {
Ok(res) => res,
Err(err) => {
log::error!("search error: {:?}", err);
let time = start.elapsed().as_secs_f64();
metrics::HTTP_RESPONSE_TIME
.with_label_values(&[
@@ -354,12 +356,15 @@ pub async fn around(
stream_type.to_string().as_str(),
])
.inc();
return Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
log::error!("search around error: {:?}", err);
return Ok(match err {
errors::Error::ErrorCode(code) => HttpResponse::InternalServerError()
.json(meta::http::HttpResponse::error_code(code)),
_ => HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(err.to_string()),
err.to_string(),
)),
);
});
}
};
+4 -4
View File
@@ -51,7 +51,7 @@ async fn schema(
return Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)),
)
}
@@ -92,7 +92,7 @@ async fn settings(
return Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)),
)
}
@@ -131,7 +131,7 @@ async fn delete(
return Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)),
)
}
@@ -165,7 +165,7 @@ async fn list(org_id: web::Path<String>, req: HttpRequest) -> impl Responder {
return Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(e.to_string()),
e.to_string(),
)),
)
}
+1 -1
View File
@@ -37,7 +37,7 @@ pub async fn traces_write(
Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Bad Request".to_string()),
"Bad Request".to_string(),
)),
)
}
+1 -1
View File
@@ -99,7 +99,7 @@ pub async fn update(
return Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Please specify appropriate fields to update user".to_string()),
"Please specify appropriate fields to update user".to_string(),
)),
);
}
+4 -4
View File
@@ -23,7 +23,7 @@ use super::auth::validator;
use super::request::alerts::*;
use super::request::dashboards::*;
use super::request::functions;
use super::request::ingest;
use super::request::logs;
use super::request::organization::*;
use super::request::prom::*;
use super::request::search;
@@ -91,9 +91,9 @@ pub fn get_service_routes(cfg: &mut web::ServiceConfig) {
.wrap(auth)
.wrap(cors)
.service(status::cache_status)
.service(ingest::bulk)
.service(ingest::multi)
.service(ingest::json)
.service(logs::ingest::bulk)
.service(logs::ingest::multi)
.service(logs::ingest::json)
.service(search::search)
.service(search::around)
.service(stream::schema)
+4 -4
View File
@@ -25,9 +25,9 @@ use crate::meta;
request::stream::schema,
request::stream::settings,
request::stream::delete,
request::ingest::bulk,
request::ingest::multi,
request::ingest::json,
request::logs::ingest::bulk,
request::logs::ingest::multi,
request::logs::ingest::json,
request::search::search,
request::search::around,
request::functions::list_functions,
@@ -108,7 +108,7 @@ use crate::meta;
modifiers(&SecurityAddon),
tags(
(name = "Auth", description = "User login authentication"),
(name = "Ingestion", description = "Data ingestion operations"),
(name = "Logs", description = "Logs data ingestion operations"),
(name = "Search", description = "Search/Query operations"),
(name = "Alerts", description = "Alerts retrieval & management operations"),
(name = "Functions", description = "Functions retrieval & management operations"),
+60
View File
@@ -28,10 +28,14 @@ pub enum Error {
SerdeJsonError(#[from] serde_json::Error),
#[error("SimdJsonError# {0}")]
SimdJsonError(#[from] simd_json::Error),
#[error("DataFusionError# {0}")]
DataFusionError(#[from] datafusion::error::DataFusionError),
#[error("Error# watcher is exists {0}")]
WatcherExists(String),
#[error("Error# {0}")]
Message(String),
#[error("ErrorCode# {0}")]
ErrorCode(ErrorCodes),
#[error("Not implemented")]
NotImplemented,
#[error("Unknown error")]
@@ -44,6 +48,62 @@ pub enum DbError {
KeyNotExists(String),
}
#[derive(ThisError, Debug)]
pub enum ErrorCodes {
ServerInternalError(String),
SearchSQLNotValid(String),
SearchStreamNotFound(String),
FullTextSearchFieldNotFound,
SearchFieldNotFound,
SearchFunctionNotDefined,
SearchParquetFileNotFound,
SearchFieldHasNoCompatibleDataType,
}
impl std::fmt::Display for ErrorCodes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
r#"{{"error_code": {}, "error_msg": "{}"}}"#,
self.get_code(),
self.get_message()
)
}
}
impl ErrorCodes {
pub fn get_code(&self) -> u16 {
match self {
ErrorCodes::ServerInternalError(_) => 10001,
ErrorCodes::SearchSQLNotValid(_) => 20001,
ErrorCodes::SearchStreamNotFound(_) => 20002,
ErrorCodes::FullTextSearchFieldNotFound => 20003,
ErrorCodes::SearchFieldNotFound => 20004,
ErrorCodes::SearchFunctionNotDefined => 20005,
ErrorCodes::SearchParquetFileNotFound => 20006,
ErrorCodes::SearchFieldHasNoCompatibleDataType => 20007,
}
}
pub fn get_message(&self) -> String {
match self {
ErrorCodes::ServerInternalError(msg) => msg.to_owned(),
ErrorCodes::SearchSQLNotValid(sql) => format!("Search SQL not valid, sql: [{}]", sql),
ErrorCodes::SearchStreamNotFound(stream) => {
format!("Search stream not found, stream: [{}]", stream)
}
ErrorCodes::FullTextSearchFieldNotFound => {
"Full text search field not found".to_string()
}
ErrorCodes::SearchFieldNotFound => "Search field not found".to_string(),
ErrorCodes::SearchFunctionNotDefined => "Search function not defined".to_string(),
ErrorCodes::SearchParquetFileNotFound => "Search parquet file not found".to_string(),
ErrorCodes::SearchFieldHasNoCompatibleDataType => {
"Search field has no compatible data type".to_string()
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
+36 -21
View File
@@ -15,13 +15,20 @@
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use crate::infra::errors;
/// HTTP response
/// code 200 is success
/// code 400 is error
/// code 404 is not found
/// code 500 is internal server error
/// code 503 is service unavailable
/// code >= 1000 is custom error code
/// message is the message or error message
#[derive(Clone, Debug, Serialize, Deserialize, ToSchema)]
pub struct HttpResponse {
pub code: u16,
#[serde(skip_serializing_if = "String::is_empty")]
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -32,41 +39,49 @@ pub struct ESResponse {
}
impl HttpResponse {
pub fn _new(code: u16, message: String, error: Option<String>) -> Self {
HttpResponse {
code,
message,
error,
}
}
pub fn message(code: u16, message: String) -> Self {
HttpResponse { code, message }
}
pub fn error(code: u16, error: String) -> Self {
HttpResponse {
code,
message,
error: None,
message: error,
}
}
pub fn error(code: u16, error: Option<String>) -> Self {
pub fn error_code(err: errors::ErrorCodes) -> Self {
HttpResponse {
code,
message: "".to_string(),
error,
code: err.get_code(),
message: err.get_message(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use actix_web::http;
use super::*;
#[test]
fn test_err_response() {
fn test_http_response() {
let msg = "This is an error response";
let err = HttpResponse::message(http::StatusCode::OK.into(), msg.to_string());
assert_eq!(err.code, http::StatusCode::OK);
assert_eq!(err.message, msg);
let err = HttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(msg.to_string()),
msg.to_string(),
);
assert_eq!(err.error.unwrap(), msg);
assert_eq!(err.code, http::StatusCode::INTERNAL_SERVER_ERROR);
assert_eq!(err.message, msg);
let errcode = errors::ErrorCodes::ServerInternalError(msg.to_string());
let err =
HttpResponse::error_code(errors::ErrorCodes::ServerInternalError(msg.to_string()));
assert_eq!(err.code, errcode.get_code());
assert_eq!(err.message, errcode.get_message());
}
}
+1 -1
View File
@@ -137,7 +137,7 @@ pub async fn handle_trigger(alert_name: &str, alert: Alert) {
}
}
Err(err) => {
log::error!("search error: {:?}", err);
log::error!("alert_manager search error: {:?}", err);
}
}
//}
+3 -3
View File
@@ -56,9 +56,9 @@ pub async fn delete_destination(org_id: String, name: String) -> Result<HttpResp
http::StatusCode::OK.into(),
"Alert destination deleted ".to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}
@@ -71,7 +71,7 @@ pub async fn get_destination(org_id: String, name: String) -> Result<HttpRespons
Ok(alert) => Ok(HttpResponse::Ok().json(alert)),
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some("Alert destination not found".to_string()),
"Alert destination not found".to_string(),
))),
}
}
+8 -8
View File
@@ -52,7 +52,7 @@ pub async fn save_alert(
if dest.is_none() {
return Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some(format!("Destination with name {} not found", in_dest)),
format!("Destination with name {} not found", in_dest),
)));
}
@@ -64,7 +64,7 @@ pub async fn save_alert(
if fields.is_empty() {
return Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some(format!("Stream with name {} not found", stream_name)),
format!("Stream with name {} not found", stream_name),
)));
}
@@ -104,10 +104,10 @@ pub async fn save_alert(
} else {
return Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(format!(
format!(
"Column named {} not found on stream {}",
&alert.condition.column, stream_name
)),
),
)));
}
//}
@@ -123,7 +123,7 @@ pub async fn save_alert(
if sql.is_err() {
return Ok(HttpResponse::BadRequest().json(MetaHttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(format!("Invalid query : {:?} ", sql.err())),
format!("Invalid query : {:?} ", sql.err()),
)));
}
}
@@ -179,9 +179,9 @@ pub async fn delete_alert(
http::StatusCode::OK.into(),
"Alert deleted ".to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}
@@ -198,7 +198,7 @@ pub async fn get_alert(
Ok(alert) => Ok(HttpResponse::Ok().json(alert)),
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some("alert not found".to_string()),
"alert not found".to_string(),
))),
}
}
+3 -3
View File
@@ -56,9 +56,9 @@ pub async fn delete_template(org_id: String, name: String) -> Result<HttpRespons
http::StatusCode::OK.into(),
"Alert template deleted ".to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}
@@ -71,7 +71,7 @@ pub async fn get_template(org_id: String, name: String) -> Result<HttpResponse,
Ok(alert) => Ok(HttpResponse::Ok().json(alert)),
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
http::StatusCode::NOT_FOUND.into(),
Some("Alert template not found".to_string()),
"Alert template not found".to_string(),
))),
}
}
+6 -6
View File
@@ -31,11 +31,11 @@ pub async fn get_dashboard(org_id: &str, name: &str) -> Result<HttpResponse, Err
Ok(Some(dashboard)) => Ok(HttpResponse::Ok().json(dashboard)),
Ok(None) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("Dashboard not found".to_string()),
"Dashboard not found".to_string(),
))),
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("Dashboard not found".to_string()),
"Dashboard not found".to_string(),
))),
}
}
@@ -53,10 +53,10 @@ pub async fn save_dashboard(
http::StatusCode::OK.into(),
"Dashboard saved".to_string(),
))),
Err(err) => Ok(
Err(e) => Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
StatusCode::BAD_REQUEST.into(),
Some(err.to_string()),
e.to_string(),
)),
),
}
@@ -78,9 +78,9 @@ pub async fn delete_dashboard(org_id: &str, name: &str) -> Result<HttpResponse,
http::StatusCode::OK.into(),
"Dashboard deleted".to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}
+4 -4
View File
@@ -61,7 +61,7 @@ pub async fn register_function(
Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some(msg.to_string()),
msg.to_string(),
)),
)
} else {
@@ -102,7 +102,7 @@ pub async fn register_function(
Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Not valid function".to_string()),
"Not valid function".to_string(),
)),
)
}
@@ -135,9 +135,9 @@ pub async fn delete_function(
http::StatusCode::OK.into(),
DELETED.to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}
+2 -2
View File
@@ -53,7 +53,7 @@ pub async fn ingest(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some("not an ingester".to_string()),
"not an ingester".to_string(),
)),
);
}
@@ -102,7 +102,7 @@ pub async fn ingest(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("stream [{}] is being deleted", stream_name)),
format!("stream [{}] is being deleted", stream_name),
)),
);
}
+2 -2
View File
@@ -53,7 +53,7 @@ pub async fn ingest(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some("not an ingester".to_string()),
"not an ingester".to_string(),
)),
);
}
@@ -63,7 +63,7 @@ pub async fn ingest(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("stream [{}] is being deleted", stream_name)),
format!("stream [{}] is being deleted", stream_name),
)),
);
}
+2 -2
View File
@@ -54,7 +54,7 @@ pub async fn ingest(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some("not an ingester".to_string()),
"not an ingester".to_string(),
)),
);
}
@@ -64,7 +64,7 @@ pub async fn ingest(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("stream [{}] is being deleted", stream_name)),
format!("stream [{}] is being deleted", stream_name),
)),
);
}
+2 -2
View File
@@ -66,7 +66,7 @@ pub async fn prometheus_write_proto(
return Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some("not an ingester".to_string()),
"not an ingester".to_string(),
)),
);
}
@@ -216,7 +216,7 @@ pub async fn prometheus_write_proto(
return Ok(HttpResponse::InternalServerError().json(
meta::http::HttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("stream [{}] is being deleted", metric_name)),
format!("stream [{}] is being deleted", metric_name),
),
));
}
+83 -21
View File
@@ -14,6 +14,7 @@
use ::datafusion::arrow::{datatypes::Schema, ipc, json as arrow_json, record_batch::RecordBatch};
use ahash::AHashMap as HashMap;
use datafusion_common::DataFusionError;
use http_auth_basic::Credentials;
use std::io::Cursor;
use std::sync::Arc;
@@ -27,11 +28,11 @@ use crate::handler::grpc::cluster_rpc;
use crate::infra::cluster;
use crate::infra::config::{CONFIG, ROOT_USER};
use crate::infra::db::etcd;
use crate::infra::errors::{Error, ErrorCodes};
use crate::meta;
use crate::meta::search::Response;
use crate::meta::StreamType;
use crate::service::db;
use crate::service::file_list;
use crate::service::{db, file_list};
mod cache;
pub mod datafusion;
@@ -39,13 +40,13 @@ pub mod exec;
pub mod sql;
mod storage;
pub type SearchResult = Result<(HashMap<String, Vec<RecordBatch>>, usize, usize), anyhow::Error>;
pub type SearchResult = Result<(HashMap<String, Vec<RecordBatch>>, usize, usize), Error>;
pub async fn search(
org_id: &str,
stream_type: StreamType,
req: &meta::search::Request,
) -> Result<Response, anyhow::Error> {
) -> Result<Response, Error> {
let root_span = info_span!("service:search:enter");
let mut req: cluster_rpc::SearchRequest = req.to_owned().into();
@@ -72,20 +73,19 @@ pub async fn search(
if result.is_err() {
let err = result.err();
log::error!("search error: {:?}", err);
return Err(anyhow::anyhow!("error: {:?}", err));
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(format!(
"{:?}",
err
))));
}
match result.unwrap() {
Ok(res) => Ok(res),
Err(err) => {
log::error!("search error: {:?}", err);
Err(anyhow::anyhow!("error: {:?}", err))
}
Err(err) => Err(err),
}
}
#[tracing::instrument(name = "service:search:local:enter", skip(req))]
async fn search_in_local(req: cluster_rpc::SearchRequest) -> Result<Response, anyhow::Error> {
async fn search_in_local(req: cluster_rpc::SearchRequest) -> Result<Response, Error> {
let resp = match exec::search(&req).await {
Ok(res) => res,
Err(err) => return Err(err),
@@ -104,7 +104,14 @@ async fn search_in_local(req: cluster_rpc::SearchRequest) -> Result<Response, an
reader.num_batches()
);
let batches = reader.into_iter().map(Result::unwrap).collect::<Vec<_>>();
let json_rows = arrow_json::writer::record_batches_to_json_rows(&batches[..])?;
let json_rows = match arrow_json::writer::record_batches_to_json_rows(&batches[..]) {
Ok(res) => res,
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
let sources: Vec<serde_json::Value> = json_rows
.into_iter()
.map(serde_json::Value::Object)
@@ -125,7 +132,14 @@ async fn search_in_local(req: cluster_rpc::SearchRequest) -> Result<Response, an
reader.num_batches()
);
let batches = reader.into_iter().map(Result::unwrap).collect::<Vec<_>>();
let json_rows = arrow_json::writer::record_batches_to_json_rows(&batches[..])?;
let json_rows = match arrow_json::writer::record_batches_to_json_rows(&batches[..]) {
Ok(res) => res,
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
let sources: Vec<serde_json::Value> = json_rows
.into_iter()
.map(serde_json::Value::Object)
@@ -155,7 +169,7 @@ async fn search_in_local(req: cluster_rpc::SearchRequest) -> Result<Response, an
}
#[tracing::instrument(name = "service:search:cluster:enter", skip(req))]
async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response, anyhow::Error> {
async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response, Error> {
// start time
let start = std::time::Instant::now();
let stream_type: StreamType = StreamType::from(req.stream_type.as_str());
@@ -167,8 +181,9 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
match locker.lock(0).await {
Ok(res) => res,
Err(err) => {
log::error!("search in cluster get lock error: {}", err);
return Err(anyhow::anyhow!(err));
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
@@ -388,7 +403,14 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
}
for task in tasks {
let result = task.await?;
let result = match task.await {
Ok(res) => res,
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
match result {
Ok(res) => {
results.push(res);
@@ -398,7 +420,9 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
if let Err(e) = locker.unlock().await {
log::error!("search in cluster unlock error: {}", e);
}
return Err(err);
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
}
}
@@ -473,7 +497,11 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
.await
{
Ok(res) => res,
Err(err) => return Err(anyhow::anyhow!(err)),
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
}
}
@@ -490,7 +518,15 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
None => Vec::new(),
};
if !batches_query.is_empty() {
let json_rows = arrow_json::writer::record_batches_to_json_rows(&batches_query[0][..])?;
let json_rows = match arrow_json::writer::record_batches_to_json_rows(&batches_query[0][..])
{
Ok(res) => res,
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)))
}
};
let sources: Vec<serde_json::Value> = json_rows
.into_iter()
.map(serde_json::Value::Object)
@@ -506,7 +542,14 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
continue;
}
let name = name.strip_prefix("agg_").unwrap().to_string();
let json_rows = arrow_json::writer::record_batches_to_json_rows(&batch[0][..])?;
let json_rows = match arrow_json::writer::record_batches_to_json_rows(&batch[0][..]) {
Ok(res) => res,
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
let sources: Vec<serde_json::Value> = json_rows
.into_iter()
.map(serde_json::Value::Object)
@@ -538,6 +581,25 @@ async fn search_in_cluster(req: cluster_rpc::SearchRequest) -> Result<Response,
Ok(result)
}
pub fn handle_datafusion_error(err: DataFusionError) -> Error {
let err = err.to_string();
if err.contains("Schema error: No field named") {
return Error::ErrorCode(ErrorCodes::SearchFieldNotFound);
}
if err.contains("parquet not found") {
return Error::ErrorCode(ErrorCodes::SearchParquetFileNotFound);
}
if err.contains("Invalid function ") {
return Error::ErrorCode(ErrorCodes::SearchFunctionNotDefined);
}
if err.contains("Incompatible data types") {
return Error::ErrorCode(ErrorCodes::SearchFieldHasNoCompatibleDataType);
}
Error::ErrorCode(ErrorCodes::ServerInternalError(
"sql execute error".to_string(),
))
}
struct MetadataMap<'a>(&'a mut tonic::metadata::MetadataMap);
impl<'a> opentelemetry::propagation::Injector for MetadataMap<'a> {
+29 -8
View File
@@ -23,6 +23,7 @@ use super::datafusion::storage::file_list::SessionType;
use super::sql::Sql;
use crate::common::file::scan_files;
use crate::infra::config::{self, CONFIG};
use crate::infra::errors::{Error, ErrorCodes};
use crate::meta;
use crate::service::db;
use crate::service::file_list::calculate_local_files_size;
@@ -54,7 +55,15 @@ pub async fn search(
let span2 = info_span!("service:search:cache:calculate_files_size");
let guard2 = span2.enter();
let scan_size = calculate_local_files_size(&files).await?;
let scan_size = match calculate_local_files_size(&files).await {
Ok(size) => size,
Err(err) => {
log::error!("calculate files size error: {}", err);
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
"calculate files size error".to_string(),
)));
}
};
log::info!(
"[TRACE] cache->search: load files {}, scan_size {}",
file_count,
@@ -66,7 +75,15 @@ pub async fn search(
let _guard3 = span3.enter();
// fetch all schema versions, get latest schema
let schema = db::schema::get(&sql.org_id, &sql.stream_name, Some(stream_type)).await?;
let schema = match db::schema::get(&sql.org_id, &sql.stream_name, Some(stream_type)).await {
Ok(schema) => schema,
Err(err) => {
log::error!("get schema error: {}", err);
return Err(Error::ErrorCode(ErrorCodes::SearchStreamNotFound(
sql.stream_name.clone(),
)));
}
};
let schema = Arc::new(
schema
.to_owned()
@@ -77,7 +94,7 @@ pub async fn search(
id: session_id.to_string(),
data_type: SessionType::Cache,
};
let result = super::datafusion::exec::sql(
let result = match super::datafusion::exec::sql(
&session,
stream_type,
Some(schema),
@@ -86,7 +103,14 @@ pub async fn search(
&files,
FileType::JSON,
)
.await?;
.await
{
Ok(res) => res,
Err(err) => {
log::error!("datafusion execute error: {}", err);
return Err(super::handle_datafusion_error(err));
}
};
// searching done.
drop(searching);
@@ -96,10 +120,7 @@ pub async fn search(
/// get file list from local cache, no need match_source, each file will be searched
#[inline]
async fn get_file_list(
sql: &Sql,
stream_type: meta::StreamType,
) -> Result<Vec<String>, anyhow::Error> {
async fn get_file_list(sql: &Sql, stream_type: meta::StreamType) -> Result<Vec<String>, Error> {
let pattern = format!(
"{}/files/{}/{}/{}/*.json",
&CONFIG.common.data_wal_dir, &sql.org_id, stream_type, &sql.stream_name
+16 -4
View File
@@ -19,12 +19,13 @@ use tracing::{info_span, Instrument};
use crate::handler::grpc::cluster_rpc;
use crate::infra::config::CONFIG;
use crate::infra::errors::{Error, ErrorCodes};
use crate::meta::StreamType;
#[tracing::instrument(name = "service:search:exec", skip(req))]
pub async fn search(
req: &cluster_rpc::SearchRequest,
) -> Result<cluster_rpc::SearchResponse, anyhow::Error> {
) -> Result<cluster_rpc::SearchResponse, Error> {
let start = std::time::Instant::now();
let sql = super::sql::Sql::new(req).await;
if sql.is_err() {
@@ -84,7 +85,11 @@ pub async fn search(
Ok((search_result, file_count, scan_size)) => (search_result, file_count, scan_size),
Err(err) => return Err(err),
},
Err(err) => return Err(anyhow::anyhow!(err)),
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)))
}
};
if !batches1.is_empty() {
@@ -104,7 +109,11 @@ pub async fn search(
Ok((search_result, file_count, scan_size)) => (search_result, file_count, scan_size),
Err(err) => return Err(err),
},
Err(err) => return Err(anyhow::anyhow!(err)),
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)))
}
};
if !batches2.is_empty() {
@@ -142,7 +151,10 @@ pub async fn search(
.await
{
Ok(res) => res,
Err(err) => return Err(anyhow::anyhow!(err)),
Err(err) => {
log::error!("datafusion merge error: {}", err);
return Err(super::handle_datafusion_error(err));
}
};
}
+51 -37
View File
@@ -23,6 +23,7 @@ use std::fmt::{Display, Formatter};
use crate::common::str;
use crate::handler::grpc::cluster_rpc;
use crate::infra::config::CONFIG;
use crate::infra::errors::{Error, ErrorCodes};
use crate::meta::sql::Sql as MetaSql;
use crate::meta::StreamType;
use crate::service::stream::get_stream_setting_fts_fields;
@@ -70,7 +71,7 @@ impl Display for SqlMode {
impl Sql {
#[tracing::instrument(name = "service:search:sql:new", skip(req))]
pub async fn new(req: &cluster_rpc::SearchRequest) -> Result<Sql, anyhow::Error> {
pub async fn new(req: &cluster_rpc::SearchRequest) -> Result<Sql, Error> {
let req_query = req.query.as_ref().unwrap();
let req_time_range = (req_query.start_time, req_query.end_time);
let org_id = req.org_id.clone();
@@ -80,12 +81,12 @@ impl Sql {
// quick check SQL
if origin_sql.is_empty() {
return Err(anyhow::anyhow!("Query SQL is empty"));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"".to_string(),
)));
}
if !origin_sql.to_lowercase().contains(" from ") {
return Err(anyhow::anyhow!(
"Query SQL should likes [select * from table]"
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(origin_sql)));
}
// log::info!("[TRACE] origin_sql: {:?}", origin_sql);
@@ -101,35 +102,35 @@ impl Sql {
let re1 = Regex::new(r"(?i) (limit|offset|group|having|join|union) ").unwrap();
let re2 = Regex::new(r"(?i) (join|union) ").unwrap();
if sql_mode.eq(&SqlMode::Context) && re1.is_match(&origin_sql) {
return Err(anyhow::anyhow!(
"sql_mode=context, Query SQL is not supported [limit|offset|group by|having|join|union]",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"sql_mode=context, Query SQL does not supported [limit|offset|group by|having|join|union]".to_string()
)));
}
if sql_mode.eq(&SqlMode::Full) && re2.is_match(&origin_sql) {
return Err(anyhow::anyhow!(
"sql_mode=full, Query SQL is not supported [join|union]",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"sql_mode=full, Query SQL does not supported [join|union]".to_string(),
)));
}
// check time_range
if req_time_range.0 > 0
&& req_time_range.0 < Duration::seconds(1).num_microseconds().unwrap()
{
return Err(anyhow::anyhow!(
"Query SQL time_range start_time should be microseconds",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"Query SQL time_range start_time should be microseconds".to_string(),
)));
}
if req_time_range.1 > 0
&& req_time_range.1 < Duration::seconds(1).num_microseconds().unwrap()
{
return Err(anyhow::anyhow!(
"Query SQL time_range start_time should be microseconds",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"Query SQL time_range start_time should be microseconds".to_string(),
)));
}
if req_time_range.0 > 0 && req_time_range.1 > 0 && req_time_range.1 < req_time_range.0 {
return Err(anyhow::anyhow!(
"Query SQL time_range start_time should be less than end_time",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"Query SQL time_range start_time should be less than end_time".to_string(),
)));
}
// check Agg SQL
@@ -145,7 +146,9 @@ impl Sql {
req_aggs.insert(agg.name.to_string(), agg.sql.to_string());
}
if sql_mode.eq(&SqlMode::Full) && !req_aggs.is_empty() {
return Err(anyhow::anyhow!("sql_mode=full, Query not supported aggs"));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"sql_mode=full, Query not supported aggs".to_string(),
)));
}
// check aggs
@@ -154,14 +157,15 @@ impl Sql {
}
for sql in req_aggs.values() {
if !re1.is_match(sql.as_str()) {
return Err(anyhow::anyhow!(
"Aggregation SQL only support 'from query' as context",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"Aggregation SQL only support 'from query' as context".to_string(),
)));
}
if re2.is_match(sql.as_str()) {
return Err(anyhow::anyhow!(
"Aggregation SQL is not supported 'select *' please specify the fields",
));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"Aggregation SQL is not supported 'select *' please specify the fields"
.to_string(),
)));
}
if re3.is_match(sql.as_str()) {
let caps = re3.captures(sql.as_str()).unwrap();
@@ -173,16 +177,16 @@ impl Sql {
let select_caps = match re4.captures(sql.as_str()) {
Some(caps) => caps,
None => {
return Err(anyhow::anyhow!(
"Aggregation SQL should start with 'select'",
))
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
sql.to_owned(),
)));
}
};
if !select_caps.get(1).unwrap().as_str().contains(group_by) {
return Err(anyhow::anyhow!(
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(format!(
"Aggregation SQL used [group by] you should select the field [{}]",
group_by
));
))));
}
}
}
@@ -190,7 +194,12 @@ impl Sql {
// parse sql
let meta = MetaSql::new(&origin_sql);
if meta.is_err() {
return Err(anyhow::anyhow!(meta.err().unwrap()));
log::error!(
"parse sql error: {}, sql: {}",
meta.err().unwrap(),
origin_sql
);
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(origin_sql)));
}
let mut meta = meta.unwrap();
@@ -207,7 +216,9 @@ impl Sql {
let re = Regex::new(&format!(r#"(?i) from[ '"]+{}[ '"]?"#, stream_name)).unwrap();
let caps = match re.captures(origin_sql.as_str()) {
Some(caps) => caps,
None => return Err(anyhow::anyhow!("SQL should likes [select * from table]")),
None => {
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(origin_sql)));
}
};
origin_sql = origin_sql.replace(caps.get(0).unwrap().as_str(), " FROM tbl ");
@@ -281,7 +292,9 @@ impl Sql {
&& !origin_sql.contains(" count(")
&& !origin_sql.contains(&CONFIG.common.time_stamp_col)
{
return Err(anyhow::anyhow!("sql_mode=full, Query SQL must limit rows"));
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(
"sql_mode=full, Query SQL must limit rows".to_string(),
)));
}
}
@@ -345,7 +358,7 @@ impl Sql {
fulltext_search.push(format!("\"{}\" {} '%{}%'", field.name(), func, item.1));
}
if fulltext_search.is_empty() {
return Err(anyhow::anyhow!("No full text search field found"));
return Err(Error::ErrorCode(ErrorCodes::FullTextSearchFieldNotFound));
}
let fulltext_search = format!("({})", fulltext_search.join(" OR "));
origin_sql = origin_sql.replace(item.0.as_str(), &fulltext_search);
@@ -452,7 +465,8 @@ impl Sql {
}
let sql_meta = MetaSql::new(sql.clone().as_str());
if sql_meta.is_err() {
return Err(sql_meta.err().unwrap());
log::error!("parse sql error: {}, sql: {}", sql_meta.err().unwrap(), sql);
return Err(Error::ErrorCode(ErrorCodes::SearchSQLNotValid(sql)));
}
for cap in re_histogram.captures_iter(sql.clone().as_str()) {
let attrs = cap
+49 -17
View File
@@ -23,6 +23,7 @@ use super::datafusion::storage::file_list::SessionType;
use super::sql::Sql;
use crate::infra::cache::file_data;
use crate::infra::config::CONFIG;
use crate::infra::errors::{Error, ErrorCodes};
use crate::meta;
use crate::service::{db, file_list};
@@ -77,12 +78,16 @@ pub async fn search(
for task in tasks {
match task.await {
Ok(ret) => {
if let Err(e) = ret {
return Err(anyhow::anyhow!(e));
if let Err(err) = ret {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
}
Err(e) => {
return Err(anyhow::anyhow!(e));
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
}
@@ -93,9 +98,19 @@ pub async fn search(
// fetch all schema versions, group files by version
let schema_versions =
db::schema::get_versions(&sql.org_id, &sql.stream_name, Some(stream_type)).await?;
match db::schema::get_versions(&sql.org_id, &sql.stream_name, Some(stream_type)).await {
Ok(versions) => versions,
Err(err) => {
log::error!("get schema error: {}", err);
return Err(Error::ErrorCode(ErrorCodes::SearchStreamNotFound(
sql.stream_name.clone(),
)));
}
};
if schema_versions.is_empty() {
return Err(anyhow::anyhow!("stream not found"));
return Err(Error::ErrorCode(ErrorCodes::SearchStreamNotFound(
sql.stream_name.clone(),
)));
}
let schema_latest = schema_versions.last().unwrap();
let schema_latest_id = schema_versions.len() - 1;
@@ -103,7 +118,15 @@ pub async fn search(
HashMap::with_capacity(schema_versions.len());
let mut scan_size = 0;
if !CONFIG.common.widening_schema_evoluation || schema_versions.len() == 1 {
scan_size = file_list::calculate_files_size(&files.to_vec()).await?;
scan_size = match file_list::calculate_files_size(&files.to_vec()).await {
Ok(size) => size,
Err(err) => {
log::error!("calculate files size error: {}", err);
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
"calculate files size error".to_string(),
)));
}
};
files_group.insert(schema_latest_id, files);
} else {
for file in files {
@@ -193,12 +216,15 @@ pub async fn search(
group.extend(v);
}
}
Err(e) => {
return Err(anyhow::anyhow!(e));
Err(err) => {
log::error!("datafusion execute error: {}", err);
return Err(super::handle_datafusion_error(err));
}
},
Err(e) => {
return Err(anyhow::anyhow!(e));
Err(err) => {
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
err.to_string(),
)));
}
};
}
@@ -207,19 +233,25 @@ pub async fn search(
}
#[inline]
async fn get_file_list(
sql: &Sql,
stream_type: meta::StreamType,
) -> Result<Vec<String>, anyhow::Error> {
async fn get_file_list(sql: &Sql, stream_type: meta::StreamType) -> Result<Vec<String>, Error> {
let (time_min, time_max) = sql.meta.time_range.unwrap();
let results = file_list::get_file_list(
let results = match file_list::get_file_list(
&sql.org_id,
&sql.stream_name,
Some(stream_type),
time_min,
time_max,
)
.await?;
.await
{
Ok(results) => results,
Err(err) => {
log::error!("get file list error: {}", err);
return Err(Error::ErrorCode(ErrorCodes::ServerInternalError(
"get file list error".to_string(),
)));
}
};
let mut files = Vec::new();
for file in results {
+7 -7
View File
@@ -50,7 +50,7 @@ pub async fn get_stream(
} else {
Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("stream not found".to_owned()),
"stream not found".to_string(),
)))
}
}
@@ -175,7 +175,7 @@ pub async fn save_stream_settings(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("stream [{}] is being deleted", stream_name)),
format!("stream [{}] is being deleted", stream_name),
)),
);
}
@@ -217,7 +217,7 @@ pub async fn delete_stream(
if schema.is_empty() {
return Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("stream not found".to_owned()),
"stream not found".to_string(),
)));
}
@@ -227,7 +227,7 @@ pub async fn delete_stream(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("failed to delete stream: {}", e)),
format!("failed to delete stream: {}", e),
)),
);
}
@@ -237,7 +237,7 @@ pub async fn delete_stream(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("failed to delete stream: {}", e)),
format!("failed to delete stream: {}", e),
)),
);
}
@@ -254,14 +254,14 @@ pub async fn delete_stream(
return Ok(
HttpResponse::InternalServerError().json(MetaHttpResponse::error(
StatusCode::INTERNAL_SERVER_ERROR.into(),
Some(format!("failed to delete stream: {}", e)),
format!("failed to delete stream: {}", e),
)),
);
};
Ok(HttpResponse::Ok().json(MetaHttpResponse::message(
StatusCode::OK.into(),
"stream deleted".to_owned(),
"stream deleted".to_string(),
)))
}
+1 -1
View File
@@ -63,7 +63,7 @@ pub async fn handle_trace_request(
return Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some("not an ingester".to_string()),
"not an ingester".to_string(),
)),
);
}
+2 -2
View File
@@ -68,7 +68,7 @@ pub async fn traces_json(
return Ok(
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
http::StatusCode::INTERNAL_SERVER_ERROR.into(),
Some("not an ingester".to_string()),
"not an ingester".to_string(),
)),
);
}
@@ -253,7 +253,7 @@ pub async fn traces_json(
return Ok(
HttpResponse::BadRequest().json(meta::http::HttpResponse::error(
http::StatusCode::BAD_REQUEST.into(),
Some("Bad Request".to_string()),
"Bad Request".to_string(),
)),
);
}
+3 -3
View File
@@ -42,9 +42,9 @@ pub async fn delete_trigger(alert_name: String) -> Result<HttpResponse, Error> {
http::StatusCode::OK.into(),
"Trigger deleted ".to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}
@@ -61,7 +61,7 @@ pub async fn get_alert(
Ok(alert) => Ok(HttpResponse::Ok().json(alert)),
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("alert not found".to_string()),
"alert not found".to_string(),
))),
}
}
+9 -9
View File
@@ -178,7 +178,7 @@ pub async fn update_user(
}
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("User not found".to_string()),
"User not found".to_string(),
))),
}
} else {
@@ -193,13 +193,13 @@ pub async fn update_user(
}
None => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("User not found".to_string()),
"User not found".to_string(),
))),
}
} else {
Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("User not found".to_string()),
"User not found".to_string(),
)))
}
}
@@ -251,13 +251,13 @@ pub async fn add_user_to_org(
} else {
Ok(HttpResponse::Unauthorized().json(MetaHttpResponse::error(
StatusCode::UNAUTHORIZED.into(),
Some("Not Allowed".to_string()),
"Not Allowed".to_string(),
)))
}
} else {
Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("User not found".to_string()),
"User not found".to_string(),
)))
}
}
@@ -326,13 +326,13 @@ pub async fn remove_user_from_org(org_id: &str, email_id: &str) -> Result<HttpRe
} else {
Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("User for the organization not found".to_owned()),
"User for the organization not found".to_string(),
)))
}
}
Err(_) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some("User for the organization not found".to_owned()),
"User for the organization not found".to_string(),
))),
}
}
@@ -344,9 +344,9 @@ pub async fn delete_user(email_id: &str) -> Result<HttpResponse, Error> {
http::StatusCode::OK.into(),
"User deleted".to_string(),
))),
Err(err) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
Err(e) => Ok(HttpResponse::NotFound().json(MetaHttpResponse::error(
StatusCode::NOT_FOUND.into(),
Some(err.to_string()),
e.to_string(),
))),
}
}