From 8575b3346301f27cda2d1598a694d0b46a25ee7d Mon Sep 17 00:00:00 2001 From: zhang2014 Date: Tue, 8 Nov 2022 10:15:07 +0800 Subject: [PATCH 1/2] chore(cluster): exchange error backtrace --- src/common/exception/src/exception_flight.rs | 43 +++++++++++++++++-- .../exception/tests/it/exception_flight.rs | 37 ++++++++++++++++ src/common/exception/tests/it/main.rs | 1 + 3 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/common/exception/tests/it/exception_flight.rs diff --git a/src/common/exception/src/exception_flight.rs b/src/common/exception/src/exception_flight.rs index 8b30a653f82da..4b4dbaf0a571a 100644 --- a/src/common/exception/src/exception_flight.rs +++ b/src/common/exception/src/exception_flight.rs @@ -12,17 +12,32 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::sync::Arc; + use common_arrow::arrow_format::flight::data::FlightData; +use crate::exception::ErrorCodeBacktrace; use crate::ErrorCode; use crate::Result; impl From for FlightData { fn from(error: ErrorCode) -> Self { - // TODO: has stack trace + let error_message = error.message(); + let error_backtrace = error.backtrace_str(); + + let message = error_message.as_bytes(); + let backtrace = error_backtrace.as_bytes(); + + let mut data_body = Vec::with_capacity(16 + message.len() + backtrace.len()); + + data_body.extend((message.len() as u64).to_be_bytes()); + data_body.extend_from_slice(message); + data_body.extend((backtrace.len() as u64).to_be_bytes()); + data_body.extend_from_slice(backtrace); + FlightData { + data_body, app_metadata: vec![0x02], - data_body: error.message().into_bytes(), data_header: error.code().to_be_bytes().to_vec(), flight_descriptor: None, } @@ -37,8 +52,28 @@ impl TryFrom for ErrorCode { Err(_) => Err(ErrorCode::BadBytes("Cannot parse inf usize.")), Ok(slice) => { let code = u16::from_be_bytes(slice); - let message = String::from_utf8(flight_data.data_body)?; - Ok(ErrorCode::create(code, message, None, None)) + let data_body = flight_data.data_body; + + let message_len = u64::from_be_bytes(data_body[0..8].try_into().unwrap()) as usize; + let message = &data_body[8..8 + message_len]; + let backtrace = &data_body[16 + message_len..]; + + match backtrace.is_empty() { + true => Ok(ErrorCode::create( + code, + String::from_utf8(message.to_vec())?, + None, + None, + )), + false => Ok(ErrorCode::create( + code, + String::from_utf8(message.to_vec())?, + None, + Some(ErrorCodeBacktrace::Serialized(Arc::new(String::from_utf8( + backtrace.to_vec(), + )?))), + )), + } } } } diff --git a/src/common/exception/tests/it/exception_flight.rs b/src/common/exception/tests/it/exception_flight.rs new file mode 100644 index 0000000000000..1666ac9cb8906 --- /dev/null +++ b/src/common/exception/tests/it/exception_flight.rs @@ -0,0 +1,37 @@ +// Copyright 2022 Datafuse Labs. +// +// 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. + +use std::backtrace::Backtrace; +use std::sync::Arc; + +use common_arrow::arrow_format::flight::data::FlightData; +use common_exception::exception::ErrorCodeBacktrace; +use common_exception::ErrorCode; +use common_exception::Result; + +#[test] +fn test_serialize() -> Result<()> { + let error_code = ErrorCode::create( + 1, + String::from("test_message"), + None, + Some(ErrorCodeBacktrace::Origin(Arc::new(Backtrace::capture()))), + ); + let backtrace_str = error_code.backtrace_str(); + let error_code = ErrorCode::try_from(FlightData::from(error_code))?; + assert_eq!(1, error_code.code()); + assert_eq!(String::from("test_message"), error_code.message()); + assert_eq!(backtrace_str, error_code.backtrace_str()); + Ok(()) +} diff --git a/src/common/exception/tests/it/main.rs b/src/common/exception/tests/it/main.rs index 480c1fccf12d2..53b9037b2be5b 100644 --- a/src/common/exception/tests/it/main.rs +++ b/src/common/exception/tests/it/main.rs @@ -13,4 +13,5 @@ // limitations under the License. mod exception; +mod exception_flight; mod prelude; From db0e840560a5b630f1405f2ce42e86b30140e3fc Mon Sep 17 00:00:00 2001 From: zhang2014 Date: Tue, 8 Nov 2022 19:19:55 +0800 Subject: [PATCH 2/2] chore(cluster): apply review comment --- src/common/exception/src/exception_flight.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/common/exception/src/exception_flight.rs b/src/common/exception/src/exception_flight.rs index 4b4dbaf0a571a..3079afe7fc263 100644 --- a/src/common/exception/src/exception_flight.rs +++ b/src/common/exception/src/exception_flight.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::mem::size_of; use std::sync::Arc; use common_arrow::arrow_format::flight::data::FlightData; @@ -44,6 +45,10 @@ impl From for FlightData { } } +fn read_be_u64(bytes: &[u8]) -> u64 { + u64::from_be_bytes(bytes[0..size_of::()].try_into().unwrap()) +} + impl TryFrom for ErrorCode { type Error = ErrorCode; @@ -54,9 +59,13 @@ impl TryFrom for ErrorCode { let code = u16::from_be_bytes(slice); let data_body = flight_data.data_body; - let message_len = u64::from_be_bytes(data_body[0..8].try_into().unwrap()) as usize; - let message = &data_body[8..8 + message_len]; - let backtrace = &data_body[16 + message_len..]; + let mut data_offset = 0; + let message_len = read_be_u64(&data_body) as usize; + data_offset += size_of::(); + let message = &data_body[data_offset..data_offset + message_len]; + data_offset += message_len; + data_offset += size_of::(); + let backtrace = &data_body[data_offset..]; match backtrace.is_empty() { true => Ok(ErrorCode::create(