mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-26 05:56:50 +00:00
feat(obs): Add metric to count all s3 operations (#2088)
Co-authored-by: loverustfs <hello@rustfs.com> Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
@@ -25,7 +25,6 @@ use crate::storage::s3_api::{acl, encryption, replication, tagging};
|
|||||||
use crate::storage::*;
|
use crate::storage::*;
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use metrics::counter;
|
|
||||||
use rustfs_config::RUSTFS_REGION;
|
use rustfs_config::RUSTFS_REGION;
|
||||||
use rustfs_ecstore::bucket::{
|
use rustfs_ecstore::bucket::{
|
||||||
lifecycle::bucket_lifecycle_ops::validate_transition_tier,
|
lifecycle::bucket_lifecycle_ops::validate_transition_tier,
|
||||||
@@ -163,8 +162,6 @@ impl DefaultBucketUsecase {
|
|||||||
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string()));
|
||||||
};
|
};
|
||||||
|
|
||||||
counter!("rustfs_create_bucket_total").increment(1);
|
|
||||||
|
|
||||||
let make_result = store
|
let make_result = store
|
||||||
.make_bucket(
|
.make_bucket(
|
||||||
&bucket,
|
&bucket,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
use crate::app::bucket_usecase::DefaultBucketUsecase;
|
use crate::app::bucket_usecase::DefaultBucketUsecase;
|
||||||
use crate::app::multipart_usecase::DefaultMultipartUsecase;
|
use crate::app::multipart_usecase::DefaultMultipartUsecase;
|
||||||
use crate::app::object_usecase::DefaultObjectUsecase;
|
use crate::app::object_usecase::DefaultObjectUsecase;
|
||||||
|
use crate::storage::s3_metrics::{S3Operation, record_s3_op};
|
||||||
use rustfs_ecstore::{
|
use rustfs_ecstore::{
|
||||||
bucket::tagging::decode_tags_to_map,
|
bucket::tagging::decode_tags_to_map,
|
||||||
error::{is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found},
|
error::{is_err_bucket_not_found, is_err_object_not_found, is_err_version_not_found},
|
||||||
@@ -97,7 +98,7 @@ impl AsyncSeek for InMemoryAsyncReader {
|
|||||||
|
|
||||||
impl FS {
|
impl FS {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
// let store: ECStore = ECStore::new(address, endpoint_pools).await?;
|
crate::storage::s3_metrics::init_s3_metrics();
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<AbortMultipartUploadInput>,
|
req: S3Request<AbortMultipartUploadInput>,
|
||||||
) -> S3Result<S3Response<AbortMultipartUploadOutput>> {
|
) -> S3Result<S3Response<AbortMultipartUploadOutput>> {
|
||||||
|
record_s3_op(S3Operation::AbortMultipartUpload, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_abort_multipart_upload(req).await
|
usecase.execute_abort_multipart_upload(req).await
|
||||||
}
|
}
|
||||||
@@ -198,6 +200,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<CompleteMultipartUploadInput>,
|
req: S3Request<CompleteMultipartUploadInput>,
|
||||||
) -> S3Result<S3Response<CompleteMultipartUploadOutput>> {
|
) -> S3Result<S3Response<CompleteMultipartUploadOutput>> {
|
||||||
|
record_s3_op(S3Operation::CompleteMultipartUpload, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_complete_multipart_upload(req).await
|
usecase.execute_complete_multipart_upload(req).await
|
||||||
}
|
}
|
||||||
@@ -205,6 +208,7 @@ impl S3 for FS {
|
|||||||
/// Copy an object from one location to another
|
/// Copy an object from one location to another
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn copy_object(&self, req: S3Request<CopyObjectInput>) -> S3Result<S3Response<CopyObjectOutput>> {
|
async fn copy_object(&self, req: S3Request<CopyObjectInput>) -> S3Result<S3Response<CopyObjectOutput>> {
|
||||||
|
record_s3_op(S3Operation::CopyObject, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_copy_object(req).await
|
usecase.execute_copy_object(req).await
|
||||||
}
|
}
|
||||||
@@ -215,6 +219,7 @@ impl S3 for FS {
|
|||||||
fields(start_time=?time::OffsetDateTime::now_utc())
|
fields(start_time=?time::OffsetDateTime::now_utc())
|
||||||
)]
|
)]
|
||||||
async fn create_bucket(&self, req: S3Request<CreateBucketInput>) -> S3Result<S3Response<CreateBucketOutput>> {
|
async fn create_bucket(&self, req: S3Request<CreateBucketInput>) -> S3Result<S3Response<CreateBucketOutput>> {
|
||||||
|
record_s3_op(S3Operation::CreateBucket, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_create_bucket(req).await
|
usecase.execute_create_bucket(req).await
|
||||||
}
|
}
|
||||||
@@ -224,6 +229,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<CreateMultipartUploadInput>,
|
req: S3Request<CreateMultipartUploadInput>,
|
||||||
) -> S3Result<S3Response<CreateMultipartUploadOutput>> {
|
) -> S3Result<S3Response<CreateMultipartUploadOutput>> {
|
||||||
|
record_s3_op(S3Operation::CreateMultipartUpload, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_create_multipart_upload(req).await
|
usecase.execute_create_multipart_upload(req).await
|
||||||
}
|
}
|
||||||
@@ -231,12 +237,14 @@ impl S3 for FS {
|
|||||||
/// Delete a bucket
|
/// Delete a bucket
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn delete_bucket(&self, req: S3Request<DeleteBucketInput>) -> S3Result<S3Response<DeleteBucketOutput>> {
|
async fn delete_bucket(&self, req: S3Request<DeleteBucketInput>) -> S3Result<S3Response<DeleteBucketOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucket, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket(req).await
|
usecase.execute_delete_bucket(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn delete_bucket_cors(&self, req: S3Request<DeleteBucketCorsInput>) -> S3Result<S3Response<DeleteBucketCorsOutput>> {
|
async fn delete_bucket_cors(&self, req: S3Request<DeleteBucketCorsInput>) -> S3Result<S3Response<DeleteBucketCorsOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucketCors, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket_cors(req).await
|
usecase.execute_delete_bucket_cors(req).await
|
||||||
}
|
}
|
||||||
@@ -245,6 +253,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeleteBucketEncryptionInput>,
|
req: S3Request<DeleteBucketEncryptionInput>,
|
||||||
) -> S3Result<S3Response<DeleteBucketEncryptionOutput>> {
|
) -> S3Result<S3Response<DeleteBucketEncryptionOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucketEncryption, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket_encryption(req).await
|
usecase.execute_delete_bucket_encryption(req).await
|
||||||
}
|
}
|
||||||
@@ -254,6 +263,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeleteBucketLifecycleInput>,
|
req: S3Request<DeleteBucketLifecycleInput>,
|
||||||
) -> S3Result<S3Response<DeleteBucketLifecycleOutput>> {
|
) -> S3Result<S3Response<DeleteBucketLifecycleOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucketLifecycle, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket_lifecycle(req).await
|
usecase.execute_delete_bucket_lifecycle(req).await
|
||||||
}
|
}
|
||||||
@@ -262,6 +272,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeleteBucketPolicyInput>,
|
req: S3Request<DeleteBucketPolicyInput>,
|
||||||
) -> S3Result<S3Response<DeleteBucketPolicyOutput>> {
|
) -> S3Result<S3Response<DeleteBucketPolicyOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucketPolicy, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket_policy(req).await
|
usecase.execute_delete_bucket_policy(req).await
|
||||||
}
|
}
|
||||||
@@ -270,6 +281,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeleteBucketReplicationInput>,
|
req: S3Request<DeleteBucketReplicationInput>,
|
||||||
) -> S3Result<S3Response<DeleteBucketReplicationOutput>> {
|
) -> S3Result<S3Response<DeleteBucketReplicationOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucketReplication, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket_replication(req).await
|
usecase.execute_delete_bucket_replication(req).await
|
||||||
}
|
}
|
||||||
@@ -279,6 +291,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeleteBucketTaggingInput>,
|
req: S3Request<DeleteBucketTaggingInput>,
|
||||||
) -> S3Result<S3Response<DeleteBucketTaggingOutput>> {
|
) -> S3Result<S3Response<DeleteBucketTaggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteBucketTagging, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_bucket_tagging(req).await
|
usecase.execute_delete_bucket_tagging(req).await
|
||||||
}
|
}
|
||||||
@@ -288,6 +301,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeletePublicAccessBlockInput>,
|
req: S3Request<DeletePublicAccessBlockInput>,
|
||||||
) -> S3Result<S3Response<DeletePublicAccessBlockOutput>> {
|
) -> S3Result<S3Response<DeletePublicAccessBlockOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeletePublicAccessBlock, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_delete_public_access_block(req).await
|
usecase.execute_delete_public_access_block(req).await
|
||||||
}
|
}
|
||||||
@@ -295,6 +309,7 @@ impl S3 for FS {
|
|||||||
/// Delete an object
|
/// Delete an object
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn delete_object(&self, req: S3Request<DeleteObjectInput>) -> S3Result<S3Response<DeleteObjectOutput>> {
|
async fn delete_object(&self, req: S3Request<DeleteObjectInput>) -> S3Result<S3Response<DeleteObjectOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteObject, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_delete_object(req).await
|
usecase.execute_delete_object(req).await
|
||||||
}
|
}
|
||||||
@@ -304,6 +319,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<DeleteObjectTaggingInput>,
|
req: S3Request<DeleteObjectTaggingInput>,
|
||||||
) -> S3Result<S3Response<DeleteObjectTaggingOutput>> {
|
) -> S3Result<S3Response<DeleteObjectTaggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteObjectTagging, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_delete_object_tagging(req).await
|
usecase.execute_delete_object_tagging(req).await
|
||||||
}
|
}
|
||||||
@@ -311,17 +327,20 @@ impl S3 for FS {
|
|||||||
/// Delete multiple objects
|
/// Delete multiple objects
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn delete_objects(&self, req: S3Request<DeleteObjectsInput>) -> S3Result<S3Response<DeleteObjectsOutput>> {
|
async fn delete_objects(&self, req: S3Request<DeleteObjectsInput>) -> S3Result<S3Response<DeleteObjectsOutput>> {
|
||||||
|
record_s3_op(S3Operation::DeleteObjects, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_delete_objects(req).await
|
usecase.execute_delete_objects(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_bucket_acl(&self, req: S3Request<GetBucketAclInput>) -> S3Result<S3Response<GetBucketAclOutput>> {
|
async fn get_bucket_acl(&self, req: S3Request<GetBucketAclInput>) -> S3Result<S3Response<GetBucketAclOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketAcl, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_acl(req).await
|
usecase.execute_get_bucket_acl(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_bucket_cors(&self, req: S3Request<GetBucketCorsInput>) -> S3Result<S3Response<GetBucketCorsOutput>> {
|
async fn get_bucket_cors(&self, req: S3Request<GetBucketCorsInput>) -> S3Result<S3Response<GetBucketCorsOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketCors, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_cors(req).await
|
usecase.execute_get_bucket_cors(req).await
|
||||||
}
|
}
|
||||||
@@ -330,6 +349,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetBucketEncryptionInput>,
|
req: S3Request<GetBucketEncryptionInput>,
|
||||||
) -> S3Result<S3Response<GetBucketEncryptionOutput>> {
|
) -> S3Result<S3Response<GetBucketEncryptionOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketEncryption, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_encryption(req).await
|
usecase.execute_get_bucket_encryption(req).await
|
||||||
}
|
}
|
||||||
@@ -339,6 +359,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetBucketLifecycleConfigurationInput>,
|
req: S3Request<GetBucketLifecycleConfigurationInput>,
|
||||||
) -> S3Result<S3Response<GetBucketLifecycleConfigurationOutput>> {
|
) -> S3Result<S3Response<GetBucketLifecycleConfigurationOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketLifecycleConfiguration, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_lifecycle_configuration(req).await
|
usecase.execute_get_bucket_lifecycle_configuration(req).await
|
||||||
}
|
}
|
||||||
@@ -346,6 +367,7 @@ impl S3 for FS {
|
|||||||
/// Get bucket location
|
/// Get bucket location
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn get_bucket_location(&self, req: S3Request<GetBucketLocationInput>) -> S3Result<S3Response<GetBucketLocationOutput>> {
|
async fn get_bucket_location(&self, req: S3Request<GetBucketLocationInput>) -> S3Result<S3Response<GetBucketLocationOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketLocation, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_location(req).await
|
usecase.execute_get_bucket_location(req).await
|
||||||
}
|
}
|
||||||
@@ -354,11 +376,13 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetBucketNotificationConfigurationInput>,
|
req: S3Request<GetBucketNotificationConfigurationInput>,
|
||||||
) -> S3Result<S3Response<GetBucketNotificationConfigurationOutput>> {
|
) -> S3Result<S3Response<GetBucketNotificationConfigurationOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketNotificationConfiguration, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_notification_configuration(req).await
|
usecase.execute_get_bucket_notification_configuration(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_bucket_policy(&self, req: S3Request<GetBucketPolicyInput>) -> S3Result<S3Response<GetBucketPolicyOutput>> {
|
async fn get_bucket_policy(&self, req: S3Request<GetBucketPolicyInput>) -> S3Result<S3Response<GetBucketPolicyOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketPolicy, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_policy(req).await
|
usecase.execute_get_bucket_policy(req).await
|
||||||
}
|
}
|
||||||
@@ -367,6 +391,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetBucketPolicyStatusInput>,
|
req: S3Request<GetBucketPolicyStatusInput>,
|
||||||
) -> S3Result<S3Response<GetBucketPolicyStatusOutput>> {
|
) -> S3Result<S3Response<GetBucketPolicyStatusOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketPolicyStatus, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_policy_status(req).await
|
usecase.execute_get_bucket_policy_status(req).await
|
||||||
}
|
}
|
||||||
@@ -375,12 +400,14 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetBucketReplicationInput>,
|
req: S3Request<GetBucketReplicationInput>,
|
||||||
) -> S3Result<S3Response<GetBucketReplicationOutput>> {
|
) -> S3Result<S3Response<GetBucketReplicationOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketReplication, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_replication(req).await
|
usecase.execute_get_bucket_replication(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_bucket_tagging(&self, req: S3Request<GetBucketTaggingInput>) -> S3Result<S3Response<GetBucketTaggingOutput>> {
|
async fn get_bucket_tagging(&self, req: S3Request<GetBucketTaggingInput>) -> S3Result<S3Response<GetBucketTaggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketTagging, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_tagging(req).await
|
usecase.execute_get_bucket_tagging(req).await
|
||||||
}
|
}
|
||||||
@@ -390,6 +417,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetPublicAccessBlockInput>,
|
req: S3Request<GetPublicAccessBlockInput>,
|
||||||
) -> S3Result<S3Response<GetPublicAccessBlockOutput>> {
|
) -> S3Result<S3Response<GetPublicAccessBlockOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetPublicAccessBlock, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_public_access_block(req).await
|
usecase.execute_get_public_access_block(req).await
|
||||||
}
|
}
|
||||||
@@ -399,6 +427,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetBucketVersioningInput>,
|
req: S3Request<GetBucketVersioningInput>,
|
||||||
) -> S3Result<S3Response<GetBucketVersioningOutput>> {
|
) -> S3Result<S3Response<GetBucketVersioningOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketVersioning, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_get_bucket_versioning(req).await
|
usecase.execute_get_bucket_versioning(req).await
|
||||||
}
|
}
|
||||||
@@ -410,11 +439,13 @@ impl S3 for FS {
|
|||||||
fields(start_time=?time::OffsetDateTime::now_utc())
|
fields(start_time=?time::OffsetDateTime::now_utc())
|
||||||
)]
|
)]
|
||||||
async fn get_object(&self, req: S3Request<GetObjectInput>) -> S3Result<S3Response<GetObjectOutput>> {
|
async fn get_object(&self, req: S3Request<GetObjectInput>) -> S3Result<S3Response<GetObjectOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObject, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object(req).await
|
usecase.execute_get_object(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_object_acl(&self, req: S3Request<GetObjectAclInput>) -> S3Result<S3Response<GetObjectAclOutput>> {
|
async fn get_object_acl(&self, req: S3Request<GetObjectAclInput>) -> S3Result<S3Response<GetObjectAclOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObjectAcl, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object_acl(req).await
|
usecase.execute_get_object_acl(req).await
|
||||||
}
|
}
|
||||||
@@ -423,6 +454,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetObjectAttributesInput>,
|
req: S3Request<GetObjectAttributesInput>,
|
||||||
) -> S3Result<S3Response<GetObjectAttributesOutput>> {
|
) -> S3Result<S3Response<GetObjectAttributesOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObjectAttributes, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object_attributes(req).await
|
usecase.execute_get_object_attributes(req).await
|
||||||
}
|
}
|
||||||
@@ -431,6 +463,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetObjectLegalHoldInput>,
|
req: S3Request<GetObjectLegalHoldInput>,
|
||||||
) -> S3Result<S3Response<GetObjectLegalHoldOutput>> {
|
) -> S3Result<S3Response<GetObjectLegalHoldOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObjectLegalHold, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object_legal_hold(req).await
|
usecase.execute_get_object_legal_hold(req).await
|
||||||
}
|
}
|
||||||
@@ -440,6 +473,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetObjectLockConfigurationInput>,
|
req: S3Request<GetObjectLockConfigurationInput>,
|
||||||
) -> S3Result<S3Response<GetObjectLockConfigurationOutput>> {
|
) -> S3Result<S3Response<GetObjectLockConfigurationOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObjectLockConfiguration, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object_lock_configuration(req).await
|
usecase.execute_get_object_lock_configuration(req).await
|
||||||
}
|
}
|
||||||
@@ -448,38 +482,45 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<GetObjectRetentionInput>,
|
req: S3Request<GetObjectRetentionInput>,
|
||||||
) -> S3Result<S3Response<GetObjectRetentionOutput>> {
|
) -> S3Result<S3Response<GetObjectRetentionOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObjectRetention, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object_retention(req).await
|
usecase.execute_get_object_retention(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn get_object_tagging(&self, req: S3Request<GetObjectTaggingInput>) -> S3Result<S3Response<GetObjectTaggingOutput>> {
|
async fn get_object_tagging(&self, req: S3Request<GetObjectTaggingInput>) -> S3Result<S3Response<GetObjectTaggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetObjectTagging, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_get_object_tagging(req).await
|
usecase.execute_get_object_tagging(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, _req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn get_object_torrent(&self, _req: S3Request<GetObjectTorrentInput>) -> S3Result<S3Response<GetObjectTorrentOutput>> {
|
async fn get_object_torrent(&self, req: S3Request<GetObjectTorrentInput>) -> S3Result<S3Response<GetObjectTorrentOutput>> {
|
||||||
// Torrent functionality is not implemented in RustFS
|
// Torrent functionality is not implemented in RustFS
|
||||||
// Per S3 API test expectations, return 404 NoSuchKey (not 501 Not Implemented)
|
// Per S3 API test expectations, return 404 NoSuchKey (not 501 Not Implemented)
|
||||||
// This allows clients to gracefully handle the absence of torrent support
|
// This allows clients to gracefully handle the absence of torrent support
|
||||||
|
record_s3_op(S3Operation::GetObjectTorrent, &req.input.bucket);
|
||||||
Err(S3Error::new(S3ErrorCode::NoSuchKey))
|
Err(S3Error::new(S3ErrorCode::NoSuchKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn head_bucket(&self, req: S3Request<HeadBucketInput>) -> S3Result<S3Response<HeadBucketOutput>> {
|
async fn head_bucket(&self, req: S3Request<HeadBucketInput>) -> S3Result<S3Response<HeadBucketOutput>> {
|
||||||
|
record_s3_op(S3Operation::HeadBucket, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_head_bucket(req).await
|
usecase.execute_head_bucket(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn head_object(&self, req: S3Request<HeadObjectInput>) -> S3Result<S3Response<HeadObjectOutput>> {
|
async fn head_object(&self, req: S3Request<HeadObjectInput>) -> S3Result<S3Response<HeadObjectOutput>> {
|
||||||
|
record_s3_op(S3Operation::HeadObject, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_head_object(req).await
|
usecase.execute_head_object(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn list_buckets(&self, req: S3Request<ListBucketsInput>) -> S3Result<S3Response<ListBucketsOutput>> {
|
async fn list_buckets(&self, req: S3Request<ListBucketsInput>) -> S3Result<S3Response<ListBucketsOutput>> {
|
||||||
|
// List buckets not associated with a bucket, give it bucket label "*" to denote "all".
|
||||||
|
record_s3_op(S3Operation::ListBuckets, "*");
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_list_buckets(req).await
|
usecase.execute_list_buckets(req).await
|
||||||
}
|
}
|
||||||
@@ -488,6 +529,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<ListMultipartUploadsInput>,
|
req: S3Request<ListMultipartUploadsInput>,
|
||||||
) -> S3Result<S3Response<ListMultipartUploadsOutput>> {
|
) -> S3Result<S3Response<ListMultipartUploadsOutput>> {
|
||||||
|
record_s3_op(S3Operation::ListMultipartUploads, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_list_multipart_uploads(req).await
|
usecase.execute_list_multipart_uploads(req).await
|
||||||
}
|
}
|
||||||
@@ -496,40 +538,47 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<ListObjectVersionsInput>,
|
req: S3Request<ListObjectVersionsInput>,
|
||||||
) -> S3Result<S3Response<ListObjectVersionsOutput>> {
|
) -> S3Result<S3Response<ListObjectVersionsOutput>> {
|
||||||
|
record_s3_op(S3Operation::ListObjectVersions, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_list_object_versions(req).await
|
usecase.execute_list_object_versions(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn list_objects(&self, req: S3Request<ListObjectsInput>) -> S3Result<S3Response<ListObjectsOutput>> {
|
async fn list_objects(&self, req: S3Request<ListObjectsInput>) -> S3Result<S3Response<ListObjectsOutput>> {
|
||||||
|
record_s3_op(S3Operation::ListObjects, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_list_objects(req).await
|
usecase.execute_list_objects(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn list_objects_v2(&self, req: S3Request<ListObjectsV2Input>) -> S3Result<S3Response<ListObjectsV2Output>> {
|
async fn list_objects_v2(&self, req: S3Request<ListObjectsV2Input>) -> S3Result<S3Response<ListObjectsV2Output>> {
|
||||||
|
record_s3_op(S3Operation::ListObjectsV2, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_list_objects_v2(req).await
|
usecase.execute_list_objects_v2(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn list_parts(&self, req: S3Request<ListPartsInput>) -> S3Result<S3Response<ListPartsOutput>> {
|
async fn list_parts(&self, req: S3Request<ListPartsInput>) -> S3Result<S3Response<ListPartsOutput>> {
|
||||||
|
record_s3_op(S3Operation::ListParts, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_list_parts(req).await
|
usecase.execute_list_parts(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put_bucket_acl(&self, req: S3Request<PutBucketAclInput>) -> S3Result<S3Response<PutBucketAclOutput>> {
|
async fn put_bucket_acl(&self, req: S3Request<PutBucketAclInput>) -> S3Result<S3Response<PutBucketAclOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketAcl, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_acl(req).await
|
usecase.execute_put_bucket_acl(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn put_bucket_cors(&self, req: S3Request<PutBucketCorsInput>) -> S3Result<S3Response<PutBucketCorsOutput>> {
|
async fn put_bucket_cors(&self, req: S3Request<PutBucketCorsInput>) -> S3Result<S3Response<PutBucketCorsOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketCors, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_cors(req).await
|
usecase.execute_put_bucket_cors(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_bucket_logging(&self, req: S3Request<GetBucketLoggingInput>) -> S3Result<S3Response<GetBucketLoggingOutput>> {
|
async fn get_bucket_logging(&self, req: S3Request<GetBucketLoggingInput>) -> S3Result<S3Response<GetBucketLoggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::GetBucketLogging, &req.input.bucket);
|
||||||
let Some(store) = new_object_layer_fn() else {
|
let Some(store) = new_object_layer_fn() else {
|
||||||
return Err(s3_error!(InternalError, "Not init"));
|
return Err(s3_error!(InternalError, "Not init"));
|
||||||
};
|
};
|
||||||
@@ -541,6 +590,7 @@ impl S3 for FS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn put_bucket_logging(&self, req: S3Request<PutBucketLoggingInput>) -> S3Result<S3Response<PutBucketLoggingOutput>> {
|
async fn put_bucket_logging(&self, req: S3Request<PutBucketLoggingInput>) -> S3Result<S3Response<PutBucketLoggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketLogging, &req.input.bucket);
|
||||||
let Some(store) = new_object_layer_fn() else {
|
let Some(store) = new_object_layer_fn() else {
|
||||||
return Err(s3_error!(InternalError, "Not init"));
|
return Err(s3_error!(InternalError, "Not init"));
|
||||||
};
|
};
|
||||||
@@ -555,6 +605,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutBucketEncryptionInput>,
|
req: S3Request<PutBucketEncryptionInput>,
|
||||||
) -> S3Result<S3Response<PutBucketEncryptionOutput>> {
|
) -> S3Result<S3Response<PutBucketEncryptionOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketEncryption, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_encryption(req).await
|
usecase.execute_put_bucket_encryption(req).await
|
||||||
}
|
}
|
||||||
@@ -564,6 +615,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutBucketLifecycleConfigurationInput>,
|
req: S3Request<PutBucketLifecycleConfigurationInput>,
|
||||||
) -> S3Result<S3Response<PutBucketLifecycleConfigurationOutput>> {
|
) -> S3Result<S3Response<PutBucketLifecycleConfigurationOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketLifecycleConfiguration, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_lifecycle_configuration(req).await
|
usecase.execute_put_bucket_lifecycle_configuration(req).await
|
||||||
}
|
}
|
||||||
@@ -572,11 +624,13 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutBucketNotificationConfigurationInput>,
|
req: S3Request<PutBucketNotificationConfigurationInput>,
|
||||||
) -> S3Result<S3Response<PutBucketNotificationConfigurationOutput>> {
|
) -> S3Result<S3Response<PutBucketNotificationConfigurationOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketNotificationConfiguration, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_notification_configuration(req).await
|
usecase.execute_put_bucket_notification_configuration(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put_bucket_policy(&self, req: S3Request<PutBucketPolicyInput>) -> S3Result<S3Response<PutBucketPolicyOutput>> {
|
async fn put_bucket_policy(&self, req: S3Request<PutBucketPolicyInput>) -> S3Result<S3Response<PutBucketPolicyOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketPolicy, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_policy(req).await
|
usecase.execute_put_bucket_policy(req).await
|
||||||
}
|
}
|
||||||
@@ -585,6 +639,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutBucketReplicationInput>,
|
req: S3Request<PutBucketReplicationInput>,
|
||||||
) -> S3Result<S3Response<PutBucketReplicationOutput>> {
|
) -> S3Result<S3Response<PutBucketReplicationOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketReplication, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_replication(req).await
|
usecase.execute_put_bucket_replication(req).await
|
||||||
}
|
}
|
||||||
@@ -594,12 +649,14 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutPublicAccessBlockInput>,
|
req: S3Request<PutPublicAccessBlockInput>,
|
||||||
) -> S3Result<S3Response<PutPublicAccessBlockOutput>> {
|
) -> S3Result<S3Response<PutPublicAccessBlockOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutPublicAccessBlock, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_public_access_block(req).await
|
usecase.execute_put_public_access_block(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
async fn put_bucket_tagging(&self, req: S3Request<PutBucketTaggingInput>) -> S3Result<S3Response<PutBucketTaggingOutput>> {
|
async fn put_bucket_tagging(&self, req: S3Request<PutBucketTaggingInput>) -> S3Result<S3Response<PutBucketTaggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketTagging, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_tagging(req).await
|
usecase.execute_put_bucket_tagging(req).await
|
||||||
}
|
}
|
||||||
@@ -609,17 +666,20 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutBucketVersioningInput>,
|
req: S3Request<PutBucketVersioningInput>,
|
||||||
) -> S3Result<S3Response<PutBucketVersioningOutput>> {
|
) -> S3Result<S3Response<PutBucketVersioningOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutBucketVersioning, &req.input.bucket);
|
||||||
let usecase = DefaultBucketUsecase::from_global();
|
let usecase = DefaultBucketUsecase::from_global();
|
||||||
usecase.execute_put_bucket_versioning(req).await
|
usecase.execute_put_bucket_versioning(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn put_object(&self, req: S3Request<PutObjectInput>) -> S3Result<S3Response<PutObjectOutput>> {
|
async fn put_object(&self, req: S3Request<PutObjectInput>) -> S3Result<S3Response<PutObjectOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutObject, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_put_object(self, req).await
|
usecase.execute_put_object(self, req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn put_object_acl(&self, req: S3Request<PutObjectAclInput>) -> S3Result<S3Response<PutObjectAclOutput>> {
|
async fn put_object_acl(&self, req: S3Request<PutObjectAclInput>) -> S3Result<S3Response<PutObjectAclOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutObjectAcl, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_put_object_acl(req).await
|
usecase.execute_put_object_acl(req).await
|
||||||
}
|
}
|
||||||
@@ -628,6 +688,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutObjectLegalHoldInput>,
|
req: S3Request<PutObjectLegalHoldInput>,
|
||||||
) -> S3Result<S3Response<PutObjectLegalHoldOutput>> {
|
) -> S3Result<S3Response<PutObjectLegalHoldOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutObjectLegalHold, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_put_object_legal_hold(req).await
|
usecase.execute_put_object_legal_hold(req).await
|
||||||
}
|
}
|
||||||
@@ -637,6 +698,7 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutObjectLockConfigurationInput>,
|
req: S3Request<PutObjectLockConfigurationInput>,
|
||||||
) -> S3Result<S3Response<PutObjectLockConfigurationOutput>> {
|
) -> S3Result<S3Response<PutObjectLockConfigurationOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutObjectLockConfiguration, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_put_object_lock_configuration(req).await
|
usecase.execute_put_object_lock_configuration(req).await
|
||||||
}
|
}
|
||||||
@@ -645,17 +707,20 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<PutObjectRetentionInput>,
|
req: S3Request<PutObjectRetentionInput>,
|
||||||
) -> S3Result<S3Response<PutObjectRetentionOutput>> {
|
) -> S3Result<S3Response<PutObjectRetentionOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutObjectRetention, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_put_object_retention(req).await
|
usecase.execute_put_object_retention(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn put_object_tagging(&self, req: S3Request<PutObjectTaggingInput>) -> S3Result<S3Response<PutObjectTaggingOutput>> {
|
async fn put_object_tagging(&self, req: S3Request<PutObjectTaggingInput>) -> S3Result<S3Response<PutObjectTaggingOutput>> {
|
||||||
|
record_s3_op(S3Operation::PutObjectTagging, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_put_object_tagging(req).await
|
usecase.execute_put_object_tagging(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn restore_object(&self, req: S3Request<RestoreObjectInput>) -> S3Result<S3Response<RestoreObjectOutput>> {
|
async fn restore_object(&self, req: S3Request<RestoreObjectInput>) -> S3Result<S3Response<RestoreObjectOutput>> {
|
||||||
|
record_s3_op(S3Operation::RestoreObject, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_restore_object(req).await
|
usecase.execute_restore_object(req).await
|
||||||
}
|
}
|
||||||
@@ -664,18 +729,21 @@ impl S3 for FS {
|
|||||||
&self,
|
&self,
|
||||||
req: S3Request<SelectObjectContentInput>,
|
req: S3Request<SelectObjectContentInput>,
|
||||||
) -> S3Result<S3Response<SelectObjectContentOutput>> {
|
) -> S3Result<S3Response<SelectObjectContentOutput>> {
|
||||||
|
record_s3_op(S3Operation::SelectObjectContent, &req.input.bucket);
|
||||||
let usecase = DefaultObjectUsecase::from_global();
|
let usecase = DefaultObjectUsecase::from_global();
|
||||||
usecase.execute_select_object_content(req).await
|
usecase.execute_select_object_content(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn upload_part(&self, req: S3Request<UploadPartInput>) -> S3Result<S3Response<UploadPartOutput>> {
|
async fn upload_part(&self, req: S3Request<UploadPartInput>) -> S3Result<S3Response<UploadPartOutput>> {
|
||||||
|
record_s3_op(S3Operation::UploadPart, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_upload_part(req).await
|
usecase.execute_upload_part(req).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self, req))]
|
#[instrument(level = "debug", skip(self, req))]
|
||||||
async fn upload_part_copy(&self, req: S3Request<UploadPartCopyInput>) -> S3Result<S3Response<UploadPartCopyOutput>> {
|
async fn upload_part_copy(&self, req: S3Request<UploadPartCopyInput>) -> S3Result<S3Response<UploadPartCopyOutput>> {
|
||||||
|
record_s3_op(S3Operation::UploadPartCopy, &req.input.bucket);
|
||||||
let usecase = DefaultMultipartUsecase::from_global();
|
let usecase = DefaultMultipartUsecase::from_global();
|
||||||
usecase.execute_upload_part_copy(req).await
|
usecase.execute_upload_part_copy(req).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ pub mod options;
|
|||||||
pub(crate) mod readers;
|
pub(crate) mod readers;
|
||||||
pub mod rpc;
|
pub mod rpc;
|
||||||
pub(crate) mod s3_api;
|
pub(crate) mod s3_api;
|
||||||
|
pub(crate) mod s3_metrics;
|
||||||
mod sse;
|
mod sse;
|
||||||
pub mod tonic_service;
|
pub mod tonic_service;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,174 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
use metrics::{counter, describe_counter};
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
const S3_OPS_METRIC: &str = "rustfs_s3_operations_total";
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub enum S3Operation {
|
||||||
|
AbortMultipartUpload,
|
||||||
|
CompleteMultipartUpload,
|
||||||
|
CopyObject,
|
||||||
|
CreateBucket,
|
||||||
|
CreateMultipartUpload,
|
||||||
|
DeleteBucket,
|
||||||
|
DeleteBucketCors,
|
||||||
|
DeleteBucketEncryption,
|
||||||
|
DeleteBucketLifecycle,
|
||||||
|
DeleteBucketPolicy,
|
||||||
|
DeleteBucketReplication,
|
||||||
|
DeleteBucketTagging,
|
||||||
|
DeleteObject,
|
||||||
|
DeleteObjectTagging,
|
||||||
|
DeleteObjects,
|
||||||
|
DeletePublicAccessBlock,
|
||||||
|
GetBucketAcl,
|
||||||
|
GetBucketCors,
|
||||||
|
GetBucketEncryption,
|
||||||
|
GetBucketLifecycleConfiguration,
|
||||||
|
GetBucketLocation,
|
||||||
|
GetBucketLogging,
|
||||||
|
GetBucketNotificationConfiguration,
|
||||||
|
GetBucketPolicy,
|
||||||
|
GetBucketPolicyStatus,
|
||||||
|
GetBucketReplication,
|
||||||
|
GetBucketTagging,
|
||||||
|
GetBucketVersioning,
|
||||||
|
GetObject,
|
||||||
|
GetObjectAcl,
|
||||||
|
GetObjectAttributes,
|
||||||
|
GetObjectLegalHold,
|
||||||
|
GetObjectLockConfiguration,
|
||||||
|
GetObjectRetention,
|
||||||
|
GetObjectTagging,
|
||||||
|
GetObjectTorrent,
|
||||||
|
GetPublicAccessBlock,
|
||||||
|
HeadBucket,
|
||||||
|
HeadObject,
|
||||||
|
ListBuckets,
|
||||||
|
ListMultipartUploads,
|
||||||
|
ListObjectVersions,
|
||||||
|
ListObjects,
|
||||||
|
ListObjectsV2,
|
||||||
|
ListParts,
|
||||||
|
PutBucketAcl,
|
||||||
|
PutBucketCors,
|
||||||
|
PutBucketEncryption,
|
||||||
|
PutBucketLifecycleConfiguration,
|
||||||
|
PutBucketLogging,
|
||||||
|
PutBucketNotificationConfiguration,
|
||||||
|
PutBucketPolicy,
|
||||||
|
PutBucketReplication,
|
||||||
|
PutBucketTagging,
|
||||||
|
PutBucketVersioning,
|
||||||
|
PutObject,
|
||||||
|
PutObjectAcl,
|
||||||
|
PutObjectLegalHold,
|
||||||
|
PutObjectLockConfiguration,
|
||||||
|
PutObjectRetention,
|
||||||
|
PutObjectTagging,
|
||||||
|
PutPublicAccessBlock,
|
||||||
|
RestoreObject,
|
||||||
|
SelectObjectContent,
|
||||||
|
UploadPart,
|
||||||
|
UploadPartCopy,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl S3Operation {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::AbortMultipartUpload => "AbortMultipartUpload",
|
||||||
|
Self::CompleteMultipartUpload => "CompleteMultipartUpload",
|
||||||
|
Self::CopyObject => "CopyObject",
|
||||||
|
Self::CreateBucket => "CreateBucket",
|
||||||
|
Self::CreateMultipartUpload => "CreateMultipartUpload",
|
||||||
|
Self::DeleteBucket => "DeleteBucket",
|
||||||
|
Self::DeleteBucketCors => "DeleteBucketCors",
|
||||||
|
Self::DeleteBucketEncryption => "DeleteBucketEncryption",
|
||||||
|
Self::DeleteBucketLifecycle => "DeleteBucketLifecycle",
|
||||||
|
Self::DeleteBucketPolicy => "DeleteBucketPolicy",
|
||||||
|
Self::DeleteBucketReplication => "DeleteBucketReplication",
|
||||||
|
Self::DeleteBucketTagging => "DeleteBucketTagging",
|
||||||
|
Self::DeleteObject => "DeleteObject",
|
||||||
|
Self::DeleteObjectTagging => "DeleteObjectTagging",
|
||||||
|
Self::DeleteObjects => "DeleteObjects",
|
||||||
|
Self::DeletePublicAccessBlock => "DeletePublicAccessBlock",
|
||||||
|
Self::GetBucketAcl => "GetBucketAcl",
|
||||||
|
Self::GetBucketCors => "GetBucketCors",
|
||||||
|
Self::GetBucketEncryption => "GetBucketEncryption",
|
||||||
|
Self::GetBucketLifecycleConfiguration => "GetBucketLifecycleConfiguration",
|
||||||
|
Self::GetBucketLocation => "GetBucketLocation",
|
||||||
|
Self::GetBucketLogging => "GetBucketLogging",
|
||||||
|
Self::GetBucketNotificationConfiguration => "GetBucketNotificationConfiguration",
|
||||||
|
Self::GetBucketPolicy => "GetBucketPolicy",
|
||||||
|
Self::GetBucketPolicyStatus => "GetBucketPolicyStatus",
|
||||||
|
Self::GetBucketReplication => "GetBucketReplication",
|
||||||
|
Self::GetBucketTagging => "GetBucketTagging",
|
||||||
|
Self::GetBucketVersioning => "GetBucketVersioning",
|
||||||
|
Self::GetObject => "GetObject",
|
||||||
|
Self::GetObjectAcl => "GetObjectAcl",
|
||||||
|
Self::GetObjectAttributes => "GetObjectAttributes",
|
||||||
|
Self::GetObjectLegalHold => "GetObjectLegalHold",
|
||||||
|
Self::GetObjectLockConfiguration => "GetObjectLockConfiguration",
|
||||||
|
Self::GetObjectRetention => "GetObjectRetention",
|
||||||
|
Self::GetObjectTagging => "GetObjectTagging",
|
||||||
|
Self::GetObjectTorrent => "GetObjectTorrent",
|
||||||
|
Self::GetPublicAccessBlock => "GetPublicAccessBlock",
|
||||||
|
Self::HeadBucket => "HeadBucket",
|
||||||
|
Self::HeadObject => "HeadObject",
|
||||||
|
Self::ListBuckets => "ListBuckets",
|
||||||
|
Self::ListMultipartUploads => "ListMultipartUploads",
|
||||||
|
Self::ListObjectVersions => "ListObjectVersions",
|
||||||
|
Self::ListObjects => "ListObjects",
|
||||||
|
Self::ListObjectsV2 => "ListObjectsV2",
|
||||||
|
Self::ListParts => "ListParts",
|
||||||
|
Self::PutBucketAcl => "PutBucketAcl",
|
||||||
|
Self::PutBucketCors => "PutBucketCors",
|
||||||
|
Self::PutBucketEncryption => "PutBucketEncryption",
|
||||||
|
Self::PutBucketLifecycleConfiguration => "PutBucketLifecycleConfiguration",
|
||||||
|
Self::PutBucketLogging => "PutBucketLogging",
|
||||||
|
Self::PutBucketNotificationConfiguration => "PutBucketNotificationConfiguration",
|
||||||
|
Self::PutBucketPolicy => "PutBucketPolicy",
|
||||||
|
Self::PutBucketReplication => "PutBucketReplication",
|
||||||
|
Self::PutBucketTagging => "PutBucketTagging",
|
||||||
|
Self::PutBucketVersioning => "PutBucketVersioning",
|
||||||
|
Self::PutObject => "PutObject",
|
||||||
|
Self::PutObjectAcl => "PutObjectAcl",
|
||||||
|
Self::PutObjectLegalHold => "PutObjectLegalHold",
|
||||||
|
Self::PutObjectLockConfiguration => "PutObjectLockConfiguration",
|
||||||
|
Self::PutObjectRetention => "PutObjectRetention",
|
||||||
|
Self::PutObjectTagging => "PutObjectTagging",
|
||||||
|
Self::PutPublicAccessBlock => "PutPublicAccessBlock",
|
||||||
|
Self::RestoreObject => "RestoreObject",
|
||||||
|
Self::SelectObjectContent => "SelectObjectContent",
|
||||||
|
Self::UploadPart => "UploadPart",
|
||||||
|
Self::UploadPartCopy => "UploadPartCopy",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn record_s3_op(op: S3Operation, bucket: &str) {
|
||||||
|
counter!(S3_OPS_METRIC, "op" => op.as_str(), "bucket" => bucket.to_owned()).increment(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One-time registration of indicator meta information
|
||||||
|
/// This function ensures that metric descriptors are registered only once.
|
||||||
|
pub fn init_s3_metrics() {
|
||||||
|
static METRICS_DESC_INIT: OnceLock<()> = OnceLock::new();
|
||||||
|
METRICS_DESC_INIT.get_or_init(|| {
|
||||||
|
describe_counter!(S3_OPS_METRIC, "Total number of S3 API operations handled");
|
||||||
|
});
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user