mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-31 17:28:12 +00:00
refactor(logging): reduce runtime noise (#3363)
This commit is contained in:
@@ -81,6 +81,13 @@ use tracing::{debug, error, info, warn};
|
||||
use uuid::Uuid;
|
||||
use xxhash_rust::xxh64;
|
||||
|
||||
const LOG_COMPONENT_ECSTORE: &str = "ecstore";
|
||||
const LOG_SUBSYSTEM_LIFECYCLE: &str = "lifecycle";
|
||||
const EVENT_LIFECYCLE_WORKER_STATE: &str = "lifecycle_worker_state";
|
||||
const EVENT_LIFECYCLE_TRANSITION_COMPENSATION: &str = "lifecycle_transition_compensation";
|
||||
const EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP: &str = "lifecycle_stale_multipart_cleanup";
|
||||
const EVENT_LIFECYCLE_SCAN_SKIPPED: &str = "lifecycle_scan_skipped";
|
||||
|
||||
pub type TimeFn = Arc<dyn Fn() -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync + 'static>;
|
||||
pub type TraceFn =
|
||||
Arc<dyn Fn(String, HashMap<String, String>) -> Pin<Box<dyn Future<Output = ()> + Send>> + Send + Sync + 'static>;
|
||||
@@ -189,7 +196,15 @@ impl LifecycleSys {
|
||||
Ok((lc, _)) => Some(lc),
|
||||
Err(Error::ConfigNotFound) => None,
|
||||
Err(err) => {
|
||||
warn!(bucket, error = ?err, "failed to load lifecycle config");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_SCAN_SKIPPED,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
bucket,
|
||||
error = ?err,
|
||||
reason = "lifecycle_config_unavailable",
|
||||
"Skipped lifecycle config lookup"
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
@@ -204,13 +219,16 @@ impl LifecycleSys {
|
||||
let name = name.clone();
|
||||
let version_id = version_id.clone();
|
||||
Box::pin(async move {
|
||||
info!(
|
||||
debug!(
|
||||
bucket = %bucket,
|
||||
object = %name,
|
||||
version_id = %version_id,
|
||||
action = %_action,
|
||||
"ILM lifecycle trace: {} on {}/{} (version: {})",
|
||||
_action, bucket, name, version_id
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "trace",
|
||||
"Lifecycle trace event"
|
||||
);
|
||||
})
|
||||
})
|
||||
@@ -482,7 +500,14 @@ impl ExpiryState {
|
||||
loop {
|
||||
select! {
|
||||
_ = cancel_token.cancelled() => {
|
||||
info!("lifecycle expiry worker received shutdown signal, exiting");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "stopped",
|
||||
reason = "shutdown_signal",
|
||||
"Lifecycle expiry worker stopped"
|
||||
);
|
||||
break;
|
||||
}
|
||||
v = rx.recv() => {
|
||||
@@ -513,12 +538,16 @@ impl ExpiryState {
|
||||
else if v.as_any().is::<Jentry>() {
|
||||
let v = v.as_any().downcast_ref::<Jentry>().expect("Jentry downcast failed");
|
||||
if let Err(err) = delete_object_from_remote_tier(&v.obj_name, &v.version_id, &v.tier_name).await {
|
||||
warn!(
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
object = %v.obj_name,
|
||||
version_id = %v.version_id,
|
||||
tier = %v.tier_name,
|
||||
error = ?err,
|
||||
"failed to delete transitioned object from remote tier"
|
||||
reason = "remote_tier_delete_failed",
|
||||
"Lifecycle worker skipped remote tier delete"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -532,14 +561,18 @@ impl ExpiryState {
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!(
|
||||
debug!(
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
remote_object = %oi.transitioned_object.name,
|
||||
remote_version_id = %oi.transitioned_object.version_id,
|
||||
tier = %oi.transitioned_object.tier,
|
||||
error = ?err,
|
||||
"failed to sweep transitioned free version from remote tier"
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
reason = "remote_tier_delete_failed",
|
||||
"Lifecycle worker skipped remote tier delete"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
@@ -562,14 +595,18 @@ impl ExpiryState {
|
||||
}
|
||||
Err(err) if is_err_version_not_found(&err) || is_err_object_not_found(&err) => continue,
|
||||
Err(err) => {
|
||||
warn!(
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
remote_object = %oi.transitioned_object.name,
|
||||
remote_version_id = %oi.transitioned_object.version_id,
|
||||
tier = %oi.transitioned_object.tier,
|
||||
error = ?err,
|
||||
"failed to delete transitioned free version after remote tier sweep"
|
||||
reason = "local_free_version_delete_failed",
|
||||
"Lifecycle worker failed local free-version cleanup"
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -577,19 +614,29 @@ impl ExpiryState {
|
||||
}
|
||||
|
||||
if !deleted_locally {
|
||||
warn!(
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
remote_object = %oi.transitioned_object.name,
|
||||
remote_version_id = %oi.transitioned_object.version_id,
|
||||
tier = %oi.transitioned_object.tier,
|
||||
"transitioned free version was not found during local cleanup"
|
||||
reason = "local_free_version_missing",
|
||||
"Lifecycle worker could not find transitioned free version locally"
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//info!("Invalid work type - {:?}", v);
|
||||
warn!("lifecycle worker received unsupported operation type");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_WORKER_STATE,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "unsupported_task",
|
||||
"Lifecycle worker received unsupported operation type"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -689,14 +736,37 @@ impl TransitionState {
|
||||
scheduled.lock().unwrap().remove(&bucket);
|
||||
Self::add_counter(&state.compensation_running_tasks, -1);
|
||||
state.record_scanner_transition_state();
|
||||
warn!(bucket = %bucket, "transition compensation skipped because object layer is unavailable");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
bucket = %bucket,
|
||||
state = "skipped",
|
||||
reason = "object_layer_unavailable",
|
||||
"Skipped transition compensation"
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
if let Err(err) = enqueue_transition_for_existing_objects(api, &bucket).await {
|
||||
warn!(bucket = %bucket, error = ?err, "transition compensation backfill failed");
|
||||
warn!(
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
bucket = %bucket,
|
||||
state = "failed",
|
||||
error = ?err,
|
||||
"Transition compensation backfill failed"
|
||||
);
|
||||
} else {
|
||||
info!(bucket = %bucket, "transition compensation backfill completed");
|
||||
info!(
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
bucket = %bucket,
|
||||
state = "completed",
|
||||
"Completed transition compensation backfill"
|
||||
);
|
||||
}
|
||||
|
||||
scheduled.lock().unwrap().remove(&bucket);
|
||||
@@ -744,43 +814,59 @@ impl TransitionState {
|
||||
match failure {
|
||||
ImmediateEnqueueFailure::ForcedTimeout => {
|
||||
Self::inc_counter(&self.queue_send_timeout_tasks);
|
||||
warn!(
|
||||
debug!(
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
source = ?src,
|
||||
compensation_scheduled = scheduled,
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "queue_timeout_forced",
|
||||
"transition enqueue forced into timeout path for test fault injection"
|
||||
);
|
||||
}
|
||||
ImmediateEnqueueFailure::QueueClosed { timeout_ms } => match timeout_ms {
|
||||
Some(timeout_ms) => {
|
||||
warn!(
|
||||
debug!(
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
source = ?src,
|
||||
timeout_ms,
|
||||
compensation_scheduled = scheduled,
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "queue_closed",
|
||||
"transition enqueue failed because the queue is closed"
|
||||
);
|
||||
}
|
||||
None => {
|
||||
warn!(
|
||||
debug!(
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
source = ?src,
|
||||
compensation_scheduled = scheduled,
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "queue_closed",
|
||||
"transition enqueue failed because the queue is closed"
|
||||
);
|
||||
}
|
||||
},
|
||||
ImmediateEnqueueFailure::QueueSendTimedOut { timeout_ms } => {
|
||||
Self::inc_counter(&self.queue_send_timeout_tasks);
|
||||
warn!(
|
||||
debug!(
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
source = ?src,
|
||||
timeout_ms,
|
||||
compensation_scheduled = scheduled,
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "queue_send_timed_out",
|
||||
"transition enqueue timed out under backpressure"
|
||||
);
|
||||
}
|
||||
@@ -850,10 +936,14 @@ impl TransitionState {
|
||||
);
|
||||
}
|
||||
Err(async_channel::TrySendError::Closed(_)) => {
|
||||
warn!(
|
||||
debug!(
|
||||
bucket = %oi.bucket,
|
||||
object = %oi.name,
|
||||
source = ?src,
|
||||
event = EVENT_LIFECYCLE_TRANSITION_COMPENSATION,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "queue_closed",
|
||||
"transition enqueue failed because the queue is closed"
|
||||
);
|
||||
}
|
||||
@@ -1229,7 +1319,14 @@ async fn cleanup_empty_multipart_sha_dirs_on_local_disks(set: &Arc<SetDisks>) {
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
if err != DiskError::FileNotFound && err != DiskError::VolumeNotFound {
|
||||
warn!(error = ?err, "failed to list multipart root during empty sha cleanup");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
error = ?err,
|
||||
reason = "multipart_root_list_failed",
|
||||
"Skipped empty multipart sha cleanup"
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1244,7 +1341,15 @@ async fn cleanup_empty_multipart_sha_dirs_on_local_disks(set: &Arc<SetDisks>) {
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
if err != DiskError::FileNotFound && err != DiskError::VolumeNotFound {
|
||||
warn!(sha_dir = %sha_dir, error = ?err, "failed to list multipart sha dir during empty sha cleanup");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
sha_dir = %sha_dir,
|
||||
error = ?err,
|
||||
reason = "multipart_sha_dir_list_failed",
|
||||
"Skipped empty multipart sha cleanup"
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1260,7 +1365,15 @@ async fn cleanup_empty_multipart_sha_dirs_on_local_disks(set: &Arc<SetDisks>) {
|
||||
&& err != DiskError::FileNotFound
|
||||
&& err != DiskError::VolumeNotFound
|
||||
{
|
||||
warn!(sha_dir = %sha_dir, error = ?err, "failed to remove empty multipart sha dir");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
sha_dir = %sha_dir,
|
||||
error = ?err,
|
||||
reason = "multipart_sha_dir_remove_failed",
|
||||
"Failed to remove empty multipart sha dir"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1282,7 +1395,14 @@ async fn cleanup_stale_multipart_uploads_in_set(set: &Arc<SetDisks>, now: Offset
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
if err != DiskError::FileNotFound && err != DiskError::VolumeNotFound {
|
||||
warn!(error = ?err, "failed to list multipart root during stale cleanup");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
error = ?err,
|
||||
reason = "multipart_root_list_failed",
|
||||
"Skipped stale multipart cleanup"
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1297,7 +1417,15 @@ async fn cleanup_stale_multipart_uploads_in_set(set: &Arc<SetDisks>, now: Offset
|
||||
Ok(entries) => entries,
|
||||
Err(err) => {
|
||||
if err != DiskError::FileNotFound && err != DiskError::VolumeNotFound {
|
||||
warn!(sha_dir = %sha_dir, error = ?err, "failed to list multipart sha dir during stale cleanup");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
sha_dir = %sha_dir,
|
||||
error = ?err,
|
||||
reason = "multipart_sha_dir_list_failed",
|
||||
"Skipped stale multipart cleanup"
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -1317,7 +1445,15 @@ async fn cleanup_stale_multipart_uploads_in_set(set: &Arc<SetDisks>, now: Offset
|
||||
Ok(candidate) => candidate,
|
||||
Err(err) => {
|
||||
if err != DiskError::FileNotFound {
|
||||
warn!(path = %candidate_path, error = ?err, "failed to read multipart metadata during stale cleanup");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
path = %candidate_path,
|
||||
error = ?err,
|
||||
reason = "multipart_metadata_read_failed",
|
||||
"Multipart metadata unavailable during stale cleanup"
|
||||
);
|
||||
}
|
||||
let initiated = initiated_from_upload_dir(&upload_dir, None);
|
||||
StaleMultipartUploadCandidate {
|
||||
@@ -1351,18 +1487,39 @@ async fn cleanup_stale_multipart_uploads_in_set(set: &Arc<SetDisks>, now: Offset
|
||||
deleted += 1;
|
||||
let upload_id = encode_stale_upload_id(&upload_dir);
|
||||
if let Some(metadata) = candidate.metadata.as_ref() {
|
||||
info!(
|
||||
debug!(
|
||||
bucket = metadata.get(RUSTFS_MULTIPART_BUCKET_KEY).cloned().unwrap_or_default(),
|
||||
object = metadata.get(RUSTFS_MULTIPART_OBJECT_KEY).cloned().unwrap_or_default(),
|
||||
upload_id = %upload_id,
|
||||
due = ?due,
|
||||
"removed stale multipart upload"
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "removed",
|
||||
"Removed stale multipart upload"
|
||||
);
|
||||
} else {
|
||||
info!(path = %candidate.path, upload_id = %upload_id, due = ?due, "removed stale multipart upload");
|
||||
debug!(
|
||||
path = %candidate.path,
|
||||
upload_id = %upload_id,
|
||||
due = ?due,
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
state = "removed",
|
||||
"Removed stale multipart upload"
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(err) => warn!(path = %candidate.path, error = ?err, "failed to remove stale multipart upload"),
|
||||
Err(err) => debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
path = %candidate.path,
|
||||
error = ?err,
|
||||
reason = "multipart_remove_failed",
|
||||
"Failed to remove stale multipart upload"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1402,7 +1559,13 @@ pub fn init_background_stale_multipart_upload_cleanup(api: Arc<ECStore>) {
|
||||
|
||||
let deleted = cleanup_stale_multipart_uploads_once_at(api, OffsetDateTime::now_utc(), default_expiry).await;
|
||||
if deleted > 0 {
|
||||
info!(deleted, "completed stale multipart cleanup pass");
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_STALE_MULTIPART_CLEANUP,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
deleted,
|
||||
"Completed stale multipart cleanup pass"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -2061,9 +2224,14 @@ pub async fn eval_action_from_lifecycle(
|
||||
oi: &ObjectInfo,
|
||||
) -> lifecycle::Event {
|
||||
let event = lc.eval(&oi.to_lifecycle_opts()).await;
|
||||
//if serverDebugLog {
|
||||
info!("lifecycle: Secondary scan: {}", event.action);
|
||||
//}
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_SCAN_SKIPPED,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
action = ?event.action,
|
||||
state = "evaluated",
|
||||
"Evaluated lifecycle action during secondary scan"
|
||||
);
|
||||
|
||||
let lock_enabled = if let Some(lr) = lr { lr.mode.is_some() } else { false };
|
||||
|
||||
@@ -2079,15 +2247,25 @@ pub async fn eval_action_from_lifecycle(
|
||||
if lock_enabled && check_object_lock_for_deletion(&oi.bucket, oi, false).await.is_some() {
|
||||
//if serverDebugLog {
|
||||
if oi.version_id.is_some() {
|
||||
info!(
|
||||
"lifecycle: {} v({}) is locked, not deleting",
|
||||
oi.name,
|
||||
oi.version_id.map(|v| v.to_string()).unwrap_or_default()
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_SCAN_SKIPPED,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
object = %oi.name,
|
||||
version_id = %oi.version_id.map(|v| v.to_string()).unwrap_or_default(),
|
||||
reason = "object_locked",
|
||||
"Skipped lifecycle delete because object version is locked"
|
||||
);
|
||||
} else {
|
||||
info!("lifecycle: {} is locked, not deleting", oi.name);
|
||||
debug!(
|
||||
event = EVENT_LIFECYCLE_SCAN_SKIPPED,
|
||||
component = LOG_COMPONENT_ECSTORE,
|
||||
subsystem = LOG_SUBSYSTEM_LIFECYCLE,
|
||||
object = %oi.name,
|
||||
reason = "object_locked",
|
||||
"Skipped lifecycle delete because object is locked"
|
||||
);
|
||||
}
|
||||
//}
|
||||
return lifecycle::Event::default();
|
||||
}
|
||||
if let Some(rcfg) = rcfg
|
||||
|
||||
Reference in New Issue
Block a user