chore(deps): refresh workspace dependencies and hotpath profiling (#8380)

* chore(deps): update workspace dependencies

Co-Authored-By: heihutu <heihutu@gmail.com>

Co-Authored-By: zhi22915 <qiuzgang@gmail.com>

* fix: allow hotpath label marker attributes

Co-Authored-By: heihutu <heihutu@gmail.com>

Co-Authored-By: zhi22915 <qiuzgang@gmail.com>

* fix: refine hotpath profiling attribution

Co-Authored-By: heihutu <heihutu@gmail.com>

Co-Authored-By: zhi22915 <qiuzgang@gmail.com>

* test: guard object hotpath attribution

Co-Authored-By: heihutu <heihutu@gmail.com>

Co-Authored-By: zhi22915 <qiuzgang@gmail.com>

* Add ProfileReasonCode to CPU profile capture

Signed-off-by: Hauser <housemecn@gmail.com>

* fix: restore CPU profile test import

Co-Authored-By: heihutu <heihutu@gmail.com>

Co-Authored-By: zhi22915 <qiuzgang@gmail.com>

---------

Signed-off-by: Hauser <housemecn@gmail.com>
Co-authored-by: zhi22915 <qiuzgang@gmail.com>
Co-authored-by: Chris <anzhengchao@gmail.com>
This commit is contained in:
Hauser
2026-10-07 18:02:39 +08:00
committed by GitHub
parent 2f0143ef15
commit 14eb28dcd6
11 changed files with 221 additions and 186 deletions
+1
View File
@@ -3943,6 +3943,7 @@ impl DefaultObjectUsecase {
}
#[instrument(name = "execute_get_object", level = "trace", skip(self, req))]
#[hotpath::measure(impl_type = "DefaultObjectUsecase", future = true)]
pub async fn execute_get_object(&self, req: S3Request<GetObjectInput>) -> S3Result<S3Response<GetObjectOutput>> {
self.execute_get_object_boxed(req).await
}
+1 -8
View File
@@ -364,14 +364,7 @@ impl DefaultObjectUsecase {
map_quota_check_outcome(bucket, quota_checker.check_quota(bucket, op, size).await).map(Some)
}
#[hotpath::measure(
label = "rustfs::app::object_usecase::DefaultObjectUsecase::execute_put_object",
impl_type = "DefaultObjectUsecase"
)]
#[hotpath::measure(
label = "rustfs::app::object_usecase::DefaultObjectUsecase::execute_get_object",
impl_type = "DefaultObjectUsecase"
)]
#[hotpath::measure(impl_type = "DefaultObjectUsecase", future = true)]
#[instrument(level = "debug", skip(self, req))]
pub async fn execute_select_object_content(
&self,
+1
View File
@@ -1183,6 +1183,7 @@ impl DefaultObjectUsecase {
}
#[instrument(name = "execute_put_object", level = "info", skip(self, _fs, req))]
#[hotpath::measure(impl_type = "DefaultObjectUsecase", future = true)]
pub async fn execute_put_object(&self, _fs: &FS, req: S3Request<PutObjectInput>) -> S3Result<S3Response<PutObjectOutput>> {
self.execute_put_object_boxed(_fs, req).await
}
+3 -1
View File
@@ -22,9 +22,11 @@ mod profile_cpu;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
#[cfg(not(feature = "pyroscope"))]
use profile_cpu::ProfileReasonCode;
use profile_cpu::{
CPU_PROFILE_CAPABILITY, LocalProfileConsent, MAX_PROFILE_DURATION, ProfileCaptureRequest, ProfileError, ProfileOutcome,
ProfileProvenance, ProfileReasonCode, capture_cpu_profile,
ProfileProvenance, capture_cpu_profile,
};
use tokio_util::sync::CancellationToken;
@@ -0,0 +1,47 @@
// Copyright 2024 RustFS Team
//
// 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.
const GET_OBJECT: &str = include_str!("../src/app/object/get.rs");
const PUT_OBJECT: &str = include_str!("../src/app/object/put.rs");
const SELECT_OBJECT: &str = include_str!("../src/app/object/mod.rs");
fn assert_async_method_is_measured(source: &str, method: &str) {
let method_marker = format!("pub async fn {method}");
let method_start = source
.find(&method_marker)
.unwrap_or_else(|| panic!("missing method {method}"));
let prefix = &source[..method_start];
let attribute_start = prefix
.rfind("#[hotpath::measure(")
.unwrap_or_else(|| panic!("missing hotpath measurement for {method}"));
let attribute = &prefix[attribute_start..];
let attribute = attribute
.split_once(")]")
.map(|(attribute, _)| attribute)
.unwrap_or_else(|| panic!("malformed hotpath measurement for {method}"));
assert!(method_start - attribute_start < 256, "hotpath measurement is not attached to {method}",);
assert!(
attribute.contains("impl_type = \"DefaultObjectUsecase\""),
"{method} must retain CPU symbol attribution",
);
assert!(attribute.contains("future = true"), "{method} must expose async future lifecycle metrics",);
}
#[test]
fn object_request_profiling_is_attached_to_the_matching_operation() {
assert_async_method_is_measured(GET_OBJECT, "execute_get_object");
assert_async_method_is_measured(PUT_OBJECT, "execute_put_object");
assert_async_method_is_measured(SELECT_OBJECT, "execute_select_object_content");
}